diff --git a/agents/gsd-intel-updater.md b/agents/gsd-intel-updater.md index c64ba191d..f238b0988 100644 --- a/agents/gsd-intel-updater.md +++ b/agents/gsd-intel-updater.md @@ -57,14 +57,23 @@ The /gsd-intel command has already confirmed that intel.enabled is true before s ## Project Scope -When analyzing this project, use ONLY canonical source locations: +**Runtime layout detection (do this first):** Check which runtime root exists by running: +```bash +ls -d .kilo 2>/dev/null && echo "kilo" || (ls -d .claude/get-shit-done 2>/dev/null && echo "claude") || echo "unknown" +``` -- `agents/*.md` -- Agent instruction files -- `commands/gsd/*.md` -- Command files -- `get-shit-done/bin/` -- CLI tooling -- `get-shit-done/workflows/` -- Workflow files -- `get-shit-done/references/` -- Reference docs -- `hooks/*.js` -- Git hooks +Use the detected root to resolve all canonical paths below: + +| Source type | Standard `.claude` layout | `.kilo` layout | +|-------------|--------------------------|----------------| +| Agent files | `agents/*.md` | `.kilo/agents/*.md` | +| Command files | `commands/gsd/*.md` | `.kilo/command/*.md` | +| CLI tooling | `get-shit-done/bin/` | `.kilo/get-shit-done/bin/` | +| Workflow files | `get-shit-done/workflows/` | `.kilo/get-shit-done/workflows/` | +| Reference docs | `get-shit-done/references/` | `.kilo/get-shit-done/references/` | +| Hook files | `hooks/*.js` | `.kilo/hooks/*.js` | + +When analyzing this project, use ONLY the canonical source locations matching the detected layout. Do not fall back to the standard layout paths if the `.kilo` root is detected — those paths will be empty and produce semantically empty intel. EXCLUDE from counts and analysis: @@ -72,8 +81,8 @@ EXCLUDE from counts and analysis: - `node_modules/`, `dist/`, `build/`, `.git/` **Count accuracy:** When reporting component counts in stack.json or arch.md, always derive -counts by running Glob on canonical locations above, not from memory or CLAUDE.md. -Example: `Glob("agents/*.md")` for agent count. +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")`. ## Forbidden Files diff --git a/tests/bug-2351-intel-kilo-layout.test.cjs b/tests/bug-2351-intel-kilo-layout.test.cjs new file mode 100644 index 000000000..c305329a9 --- /dev/null +++ b/tests/bug-2351-intel-kilo-layout.test.cjs @@ -0,0 +1,77 @@ +/** + * Regression test for bug #2351 + * + * gsd-intel-updater used hardcoded canonical paths (`agents/*.md`, + * `commands/gsd/*.md`, `hooks/*.js`, etc.) that assumed the standard + * `.claude/` runtime layout. Under a `.kilo` install, the runtime root is + * `.kilo/`, and the command directory is `command/` (not `commands/gsd/`). + * Globs against the old paths returned no results, producing semantically + * empty intel files (`"entries": {}`). + * + * Fix: add runtime layout detection and a mapping table so the agent + * resolves paths against the correct root. + */ + +'use strict'; + +const { test, describe } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +const AGENT_PATH = path.join(__dirname, '..', 'agents', 'gsd-intel-updater.md'); + +describe('bug #2351: intel updater kilo layout support', () => { + let content; + + test('agent file exists', () => { + assert.ok(fs.existsSync(AGENT_PATH), 'agents/gsd-intel-updater.md must exist'); + content = fs.readFileSync(AGENT_PATH, 'utf-8'); + }); + + test('scope section includes layout detection step', () => { + content = content || fs.readFileSync(AGENT_PATH, 'utf-8'); + const hasDetection = + content.includes('ls -d .kilo') || + content.includes('Runtime layout detection') || + content.includes('detected layout') || + content.includes('layout detection'); + assert.ok( + hasDetection, + 'gsd-intel-updater.md must instruct the agent to detect the runtime layout ' + + '(.kilo vs .claude) before resolving canonical paths (#2351)' + ); + }); + + test('scope section maps .kilo/agents path', () => { + content = content || fs.readFileSync(AGENT_PATH, 'utf-8'); + assert.ok( + content.includes('.kilo/agents'), + 'scope section must include the .kilo/agents/*.md path so agent count is correct under kilo layout' + ); + }); + + test('scope section maps .kilo/command path (not commands/gsd)', () => { + content = content || fs.readFileSync(AGENT_PATH, 'utf-8'); + assert.ok( + content.includes('.kilo/command'), + 'scope section must include .kilo/command path — kilo uses "command/" not "commands/gsd/"' + ); + }); + + test('scope section maps .kilo/hooks path', () => { + content = content || fs.readFileSync(AGENT_PATH, 'utf-8'); + assert.ok( + content.includes('.kilo/hooks'), + 'scope section must include .kilo/hooks path for hook file counts' + ); + }); + + test('scope section retains standard layout paths for .claude installs', () => { + content = content || fs.readFileSync(AGENT_PATH, 'utf-8'); + assert.ok( + content.includes('agents/*.md') || content.includes('Standard `.claude` layout'), + 'scope section must still document the standard .claude layout paths for non-kilo installs' + ); + }); +});