* fix(#1000): align gsd-intel-updater output to canonical intel filenames The intel-updater agent was instructed to write short names (files.json, apis.json, deps.json) and a markdown arch.md, but the intel library + gsd-tools intel CLI read only the canonical long names from INTEL_FILES (file-roles.json, api-map.json, dependency-graph.json, arch-decisions.json as JSON). After /gsd:map-codebase --query refresh the agent output was orphaned — intel status and validate reported the canonical files missing and intel query returned nothing. Renames every short reference to its INTEL_FILES canonical name and converts the arch output from markdown to queryable arch-decisions.json. Adds a drift-proof regression test (derived from the exported INTEL_FILES map) in the owning module's test file tests/intel.test.cjs, reviving the maintainer-approved approach from closed PR #608. Closes #1000 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#1000): backfill changeset PR number to 1037 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
5
.changeset/1000-intel-updater-canonical-filenames.md
Normal file
5
.changeset/1000-intel-updater-canonical-filenames.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 1037
|
||||
---
|
||||
**`gsd-intel-updater` now writes the canonical intel filenames the `gsd-tools intel` CLI actually reads** — the agent was instructed to emit short names (`files.json`, `apis.json`, `deps.json`) and a markdown `arch.md`, but the intel library reads only `file-roles.json`, `api-map.json`, `dependency-graph.json`, and `arch-decisions.json` (JSON). After `/gsd:map-codebase --query refresh` the output was orphaned, so `intel status`/`validate` reported the files missing and `intel query` returned nothing. The agent now emits the canonical long names and structured `arch-decisions.json`. (#1000)
|
||||
@@ -88,7 +88,7 @@ EXCLUDE from counts and analysis:
|
||||
- `.planning/` -- Planning docs, not project code
|
||||
- `node_modules/`, `dist/`, `build/`, `.git/`
|
||||
|
||||
**Count accuracy:** When reporting component counts in stack.json or arch.md, always derive
|
||||
**Count accuracy:** When reporting component counts in stack.json or arch-decisions.json, always derive
|
||||
counts by running Glob on the layout-resolved canonical locations above, not from memory or CLAUDE.md.
|
||||
Example (standard layout): `Glob("agents/*.md")`. Example (kilo): `Glob(".kilo/agents/*.md")`.
|
||||
|
||||
@@ -108,7 +108,7 @@ If encountered, skip silently. Do NOT include contents.
|
||||
|
||||
All JSON files include a `_meta` object with `updated_at` (ISO timestamp) and `version` (integer, start at 1, increment on update).
|
||||
|
||||
### files.json -- File Graph
|
||||
### file-roles.json -- File Graph
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -127,7 +127,7 @@ All JSON files include a `_meta` object with `updated_at` (ISO timestamp) and `v
|
||||
|
||||
Types: `entry-point`, `module`, `config`, `test`, `script`, `type-def`, `style`, `template`, `data`.
|
||||
|
||||
### apis.json -- API Surfaces
|
||||
### api-map.json -- API Surfaces
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -144,7 +144,7 @@ Types: `entry-point`, `module`, `config`, `test`, `script`, `type-def`, `style`,
|
||||
}
|
||||
```
|
||||
|
||||
### deps.json -- Dependency Chains
|
||||
### dependency-graph.json -- Dependency Chains
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -180,31 +180,24 @@ Each dependency entry should also include `"invocation": "<method or npm script>
|
||||
|
||||
Identify non-code content formats that are structurally important to the project and include them in `content_formats`.
|
||||
|
||||
### arch.md -- Architecture Summary
|
||||
### arch-decisions.json -- Architecture Summary
|
||||
|
||||
```markdown
|
||||
---
|
||||
updated_at: "ISO-8601"
|
||||
---
|
||||
arch-decisions.json is JSON (NOT markdown). The `gsd-tools intel` CLI reads, validates, and queries it as JSON. Capture the architecture as descriptive keyed entries:
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
{pattern name and description}
|
||||
|
||||
## Key Components
|
||||
|
||||
| Component | Path | Responsibility |
|
||||
|-----------|------|---------------|
|
||||
|
||||
## Data Flow
|
||||
|
||||
{entry point} -> {processing} -> {output}
|
||||
|
||||
## Conventions
|
||||
|
||||
{naming, file organization, import patterns}
|
||||
```json
|
||||
{
|
||||
"_meta": { "updated_at": "ISO-8601", "version": 1 },
|
||||
"entries": {
|
||||
"overview": { "pattern": "{architecture pattern name}", "description": "{what it is and why}" },
|
||||
"data-flow": { "flow": "{entry} -> {processing} -> {output}", "description": "{detail}" },
|
||||
"conventions": { "naming": "{...}", "file-organization": "{...}", "imports": "{...}" },
|
||||
"component:{Name}": { "path": "{path}", "responsibility": "{what it does}" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add one `component:{Name}` entry per key component, plus any other descriptive keys that fit (e.g. `security`, `modes`, a domain engine). Keys and string values are what `intel query <term>` searches, so keep them descriptive.
|
||||
|
||||
<execution_flow>
|
||||
## Exploration Process
|
||||
|
||||
@@ -226,9 +219,9 @@ gsd-tools intel patch-meta .planning/intel/stack.json
|
||||
|
||||
Glob source files (`**/*.ts`, `**/*.js`, `**/*.py`, etc., excluding node_modules/dist/build).
|
||||
Read key files (entry points, configs, core modules) for imports/exports.
|
||||
Write `files.json`. Then patch its timestamp:
|
||||
Write `file-roles.json`. Then patch its timestamp:
|
||||
```bash
|
||||
gsd-tools intel patch-meta .planning/intel/files.json
|
||||
gsd-tools intel patch-meta .planning/intel/file-roles.json
|
||||
```
|
||||
|
||||
Focus on files that matter -- entry points, core modules, configs. Skip test files and generated code unless they reveal architecture.
|
||||
@@ -237,24 +230,27 @@ Focus on files that matter -- entry points, core modules, configs. Skip test fil
|
||||
|
||||
Grep for route definitions, endpoint declarations, CLI command registrations.
|
||||
Patterns to search: `app.get(`, `router.post(`, `@GetMapping`, `def route`, express route patterns.
|
||||
Write `apis.json`. If no API endpoints found, write an empty entries object. Then patch its timestamp:
|
||||
Write `api-map.json`. If no API endpoints found, write an empty entries object. Then patch its timestamp:
|
||||
```bash
|
||||
gsd-tools intel patch-meta .planning/intel/apis.json
|
||||
gsd-tools intel patch-meta .planning/intel/api-map.json
|
||||
```
|
||||
|
||||
### Step 5: Dependencies
|
||||
|
||||
Read package.json (dependencies, devDependencies), requirements.txt, go.mod, Cargo.toml.
|
||||
Cross-reference with actual imports to populate `used_by`.
|
||||
Write `deps.json`. Then patch its timestamp:
|
||||
Write `dependency-graph.json`. Then patch its timestamp:
|
||||
```bash
|
||||
gsd-tools intel patch-meta .planning/intel/deps.json
|
||||
gsd-tools intel patch-meta .planning/intel/dependency-graph.json
|
||||
```
|
||||
|
||||
### Step 6: Architecture
|
||||
|
||||
Synthesize patterns from steps 2-5 into a human-readable summary.
|
||||
Write `arch.md`.
|
||||
Synthesize patterns from steps 2-5 into structured JSON.
|
||||
Write `arch-decisions.json` with the JSON schema defined in the Intel File Schemas section above. Then patch its timestamp:
|
||||
```bash
|
||||
gsd-tools intel patch-meta .planning/intel/arch-decisions.json
|
||||
```
|
||||
|
||||
### Step 6.5: Self-Check
|
||||
|
||||
@@ -278,8 +274,8 @@ This writes `.last-refresh.json` with accurate timestamps and hashes. Do NOT wri
|
||||
## Partial Updates
|
||||
|
||||
When `focus: partial --files <paths>` is specified:
|
||||
1. Only update entries in files.json/apis.json/deps.json that reference the given paths
|
||||
2. Do NOT rewrite stack.json or arch.md (these need full context)
|
||||
1. Only update entries in file-roles.json/api-map.json/dependency-graph.json that reference the given paths
|
||||
2. Do NOT rewrite stack.json or arch-decisions.json (these need full context)
|
||||
3. Preserve existing entries not related to the specified paths
|
||||
4. Read existing intel files first, merge updates, write back
|
||||
|
||||
@@ -287,13 +283,13 @@ When `focus: partial --files <paths>` is specified:
|
||||
|
||||
| File | Target | Hard Limit |
|
||||
|------|--------|------------|
|
||||
| files.json | <=2000 tokens | 3000 tokens |
|
||||
| apis.json | <=1500 tokens | 2500 tokens |
|
||||
| deps.json | <=1000 tokens | 1500 tokens |
|
||||
| file-roles.json | <=2000 tokens | 3000 tokens |
|
||||
| api-map.json | <=1500 tokens | 2500 tokens |
|
||||
| dependency-graph.json | <=1000 tokens | 1500 tokens |
|
||||
| stack.json | <=500 tokens | 800 tokens |
|
||||
| arch.md | <=1500 tokens | 2000 tokens |
|
||||
| arch-decisions.json | <=1500 tokens | 2000 tokens |
|
||||
|
||||
For large codebases, prioritize coverage of key files over exhaustive listing. Include the most important 50-100 source files in files.json rather than attempting to list every file.
|
||||
For large codebases, prioritize coverage of key files over exhaustive listing. Include the most important 50-100 source files in file-roles.json rather than attempting to list every file.
|
||||
|
||||
<success_criteria>
|
||||
- [ ] All 5 intel files written to .planning/intel/
|
||||
|
||||
@@ -25,6 +25,7 @@ const {
|
||||
intelApiSurface,
|
||||
ensureIntelDir,
|
||||
isIntelEnabled,
|
||||
INTEL_FILES,
|
||||
} = require('../gsd-core/bin/lib/intel.cjs');
|
||||
|
||||
// ─── Helpers ────────────────────────────────────────────────────────────────
|
||||
@@ -846,3 +847,42 @@ describe('intelApiSurface', () => {
|
||||
assert.ok('stale' in result, 'result must have stale field');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#1000 regression: gsd-intel-updater emits canonical intel filenames', () => {
|
||||
// allow-test-rule: source-text-is-the-product — agents/gsd-intel-updater.md IS the
|
||||
// system prompt the intel-updater agent runs under; asserting its filename references
|
||||
// verifies the deployed agent surface contract matches the INTEL_FILES the CLI reads.
|
||||
const agentPromptPath = path.join(__dirname, '..', 'agents', 'gsd-intel-updater.md');
|
||||
const agentPrompt = fs.readFileSync(agentPromptPath, 'utf8');
|
||||
|
||||
test('references every canonical INTEL_FILES name', () => {
|
||||
for (const filename of Object.values(INTEL_FILES)) {
|
||||
assert.ok(
|
||||
agentPrompt.includes(filename),
|
||||
`gsd-intel-updater.md must instruct writing the canonical intel file "${filename}" (from INTEL_FILES) that the gsd-tools intel CLI reads; it was missing.`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('does not reference orphaned short filenames the CLI never reads', () => {
|
||||
// Short forms `${key}.json` that are NOT canonical INTEL_FILES values are orphaned —
|
||||
// the agent must not emit them. Also forbid the markdown arch.md output.
|
||||
const canonical = new Set(Object.values(INTEL_FILES));
|
||||
const forbidden = Object.keys(INTEL_FILES)
|
||||
.map((k) => `${k}.json`)
|
||||
.filter((short) => !canonical.has(short));
|
||||
forbidden.push('arch.md');
|
||||
for (const shortName of forbidden) {
|
||||
// Guard against substring false-positives (e.g. 'files.json' inside 'file-roles.json'):
|
||||
// canonical long names never contain these short tokens, verified by the canonical set.
|
||||
const offendingLines = agentPrompt
|
||||
.split('\n')
|
||||
.filter((line) => line.includes(shortName));
|
||||
assert.strictEqual(
|
||||
offendingLines.length,
|
||||
0,
|
||||
`gsd-intel-updater.md must not reference orphaned short name "${shortName}" the intel CLI never reads. Offending line(s):\n${offendingLines.join('\n')}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user