nightralph 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +5 -0
- package/AGENTS.md +60 -0
- package/CLAUDE.md +1 -0
- package/PROMPT.md +95 -0
- package/README.md +138 -0
- package/WIP.md +5 -0
- package/dist/docs-templates/domain.md +36 -0
- package/dist/docs-templates/issue-tracker-github.md +228 -0
- package/dist/docs-templates/issue-tracker.md +30 -0
- package/dist/docs-templates/triage-labels.md +15 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +7 -0
- package/dist/meta.json +207 -0
- package/dist/orchestrator.js +273 -0
- package/dist/orchestrator.js.map +7 -0
- package/dist/resolve.js +71 -0
- package/dist/resolve.js.map +7 -0
- package/dist/setup.js +151 -0
- package/dist/setup.js.map +7 -0
- package/dist/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/dist/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/dist/skills/domain-modeling/SKILL.md +74 -0
- package/dist/skills/domain-modeling/agents/openai.yaml +3 -0
- package/dist/skills/grill/SKILL.md +7 -0
- package/dist/skills/grill/agents/openai.yaml +5 -0
- package/dist/skills/grilling/SKILL.md +28 -0
- package/dist/skills/grilling/agents/openai.yaml +3 -0
- package/dist/skills/tdd/SKILL.md +38 -0
- package/dist/skills/tdd/agents/openai.yaml +3 -0
- package/dist/skills/tdd/mocking.md +59 -0
- package/dist/skills/tdd/tests.md +77 -0
- package/dist/skills/to-spec/SKILL.md +75 -0
- package/dist/skills/to-spec/agents/openai.yaml +5 -0
- package/dist/skills/to-tickets/SKILL.md +105 -0
- package/dist/skills/to-tickets/agents/openai.yaml +5 -0
- package/dist/skills/upstream.json +5 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/orchestrator.d.ts +31 -0
- package/dist/src/orchestrator.d.ts.map +1 -0
- package/dist/src/resolve.d.ts +10 -0
- package/dist/src/resolve.d.ts.map +1 -0
- package/dist/src/setup.d.ts +13 -0
- package/dist/src/setup.d.ts.map +1 -0
- package/dist/test/integration.test.js +848 -0
- package/dist/test/integration.test.js.map +7 -0
- package/dist/test/orchestrator.test.js +749 -0
- package/dist/test/orchestrator.test.js.map +7 -0
- package/dist/test/setup.test.js +574 -0
- package/dist/test/setup.test.js.map +7 -0
- package/docs/README.md +12 -0
- package/docs/agents/domain.md +36 -0
- package/docs/agents/issue-tracker.md +30 -0
- package/docs/agents/triage-labels.md +15 -0
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase-2-future-work.md +144 -0
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase_01.md +292 -0
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/phase_02.md +212 -0
- package/docs/implementation-plans/2026-08-27-issue-tracker-choice/test-requirements.md +203 -0
- package/docs/skills.md +58 -0
- package/docs/test-plans/2026-08-27-issue-tracker-choice.md +95 -0
- package/eslint.config.js +142 -0
- package/lib.es5.d.ts +19 -0
- package/package.json +36 -0
- package/progress.log +190 -0
- package/ralph_claude.sh +263 -0
- package/scripts/clone-skills.sh +52 -0
- package/specs/prd.json +172 -0
- package/src/docs-templates/domain.md +36 -0
- package/src/docs-templates/issue-tracker-github.md +228 -0
- package/src/docs-templates/issue-tracker.md +30 -0
- package/src/docs-templates/triage-labels.md +15 -0
- package/src/index.ts +184 -0
- package/src/orchestrator.ts +324 -0
- package/src/resolve.ts +73 -0
- package/src/setup.ts +157 -0
- package/src/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/src/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/src/skills/domain-modeling/SKILL.md +74 -0
- package/src/skills/domain-modeling/agents/openai.yaml +3 -0
- package/src/skills/grill/SKILL.md +7 -0
- package/src/skills/grill/agents/openai.yaml +5 -0
- package/src/skills/grilling/SKILL.md +28 -0
- package/src/skills/grilling/agents/openai.yaml +3 -0
- package/src/skills/tdd/SKILL.md +38 -0
- package/src/skills/tdd/agents/openai.yaml +3 -0
- package/src/skills/tdd/mocking.md +59 -0
- package/src/skills/tdd/tests.md +77 -0
- package/src/skills/to-spec/SKILL.md +75 -0
- package/src/skills/to-spec/agents/openai.yaml +5 -0
- package/src/skills/to-tickets/SKILL.md +105 -0
- package/src/skills/to-tickets/agents/openai.yaml +5 -0
- package/src/skills/upstream.json +5 -0
- package/tasks/prd-integration-test-coverage.md +243 -0
- package/test/integration.test.ts +636 -0
- package/test/mock-agent-echo-args.js +4 -0
- package/test/mock-agent-fail.js +3 -0
- package/test/mock-agent-pass.js +3 -0
- package/test/orchestrator.test.ts +609 -0
- package/test/setup.test.ts +417 -0
- package/tsconfig.build.json +7 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../test/setup.test.ts", "../../src/setup.ts"],
|
|
4
|
+
"sourcesContent": ["import { test } from '@substrate-system/tapzero'\nimport {\n mkdtempSync, mkdirSync, writeFileSync, existsSync,\n lstatSync, readlinkSync, readFileSync,\n} from 'node:fs'\nimport { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport {\n setup, SKILL_DIRS, DOC_TEMPLATES, checkGhAuth,\n} from '../src/setup.js'\n\nfunction makeTempProject ():{\n projectDir:string;\n bundledSkillsDir:string;\n docsTemplatesDir:string;\n} {\n const base = mkdtempSync(\n join(tmpdir(), 'nightralph-test-')\n )\n const projectDir = join(base, 'project')\n mkdirSync(projectDir, { recursive:true })\n\n const bundledSkillsDir = join(base, 'bundled')\n mkdirSync(bundledSkillsDir, { recursive:true })\n\n writeFileSync(\n join(bundledSkillsDir, 'upstream.json'),\n JSON.stringify({\n repo:'test/repo',\n commit:'abc123',\n })\n )\n\n for (const skill of SKILL_DIRS) {\n const dir = join(bundledSkillsDir, skill)\n mkdirSync(dir, { recursive:true })\n writeFileSync(\n join(dir, 'SKILL.md'),\n `# ${skill}`\n )\n }\n\n const docsTemplatesDir = join(base, 'docs-templates')\n mkdirSync(docsTemplatesDir, { recursive:true })\n for (const tmpl of DOC_TEMPLATES) {\n writeFileSync(\n join(docsTemplatesDir, tmpl),\n `# ${tmpl}`\n )\n }\n writeFileSync(\n join(docsTemplatesDir, 'issue-tracker.md'),\n '# issue-tracker.md'\n )\n writeFileSync(\n join(docsTemplatesDir, 'issue-tracker-github.md'),\n '# issue-tracker-github.md'\n )\n\n return { projectDir, bundledSkillsDir, docsTemplatesDir }\n}\n\ntest('setup copies skills to .agents/skills', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n for (const skill of SKILL_DIRS) {\n const dest = join(\n projectDir, '.agents', 'skills', skill\n )\n t.ok(\n existsSync(dest),\n `${skill}/ should exist in .agents/skills`\n )\n t.ok(\n existsSync(join(dest, 'SKILL.md')),\n `${skill}/SKILL.md should be copied`\n )\n }\n})\n\ntest('setup does NOT create .claude/skills by default', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n const claudeSkills = join(\n projectDir, '.claude', 'skills'\n )\n t.ok(\n !existsSync(claudeSkills),\n '.claude/skills should not exist without --claude'\n )\n})\n\ntest('setup --claude creates symlinks in .claude/skills', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n claude:true,\n tracker:'local',\n })\n\n for (const skill of SKILL_DIRS) {\n const agentsDest = join(\n projectDir, '.agents', 'skills', skill\n )\n t.ok(\n existsSync(agentsDest),\n `${skill}/ should exist in .agents/skills`\n )\n\n const claudeDest = join(\n projectDir, '.claude', 'skills', skill\n )\n t.ok(\n existsSync(claudeDest),\n `${skill}/ should exist in .claude/skills`\n )\n\n if (!existsSync(claudeDest)) {\n t.fail(`symlink missing for ${skill}`)\n continue\n }\n\n const stat = lstatSync(claudeDest)\n t.ok(\n stat.isSymbolicLink(),\n `.claude/skills/${skill} should be a symlink`\n )\n\n const target = readlinkSync(claudeDest)\n const expected = join(\n '..', '..', '.agents', 'skills', skill\n )\n t.equal(\n target,\n expected,\n `symlink should point to ${expected}`\n )\n }\n})\n\ntest('setup creates docs/agents/ templates', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n for (const tmpl of DOC_TEMPLATES) {\n const dest = join(\n projectDir, 'docs', 'agents', tmpl\n )\n t.ok(\n existsSync(dest),\n `docs/agents/${tmpl} should be created`\n )\n }\n})\n\ntest('setup does not overwrite non-tracker docs', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n const triagePath = join(\n projectDir, 'docs', 'agents', 'triage-labels.md'\n )\n mkdirSync(join(projectDir, 'docs', 'agents'), {\n recursive:true,\n })\n writeFileSync(triagePath, 'custom triage content')\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n const content = readFileSync(triagePath, 'utf8')\n t.equal(\n content,\n 'custom triage content',\n 'should preserve existing triage-labels.md'\n )\n})\n\ntest('setup is idempotent', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n const opts = {\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n claude:true,\n tracker:'local' as const,\n }\n\n setup(opts)\n setup(opts)\n\n for (const skill of SKILL_DIRS) {\n const agentsDest = join(\n projectDir, '.agents', 'skills', skill\n )\n t.ok(\n existsSync(agentsDest),\n `${skill}/ should still exist after second run`\n )\n\n const claudeDest = join(\n projectDir, '.claude', 'skills', skill\n )\n if (!existsSync(claudeDest)) {\n t.fail(`symlink missing for ${skill}`)\n continue\n }\n const stat = lstatSync(claudeDest)\n t.ok(\n stat.isSymbolicLink(),\n `${skill} symlink should still be valid`\n )\n }\n\n for (const tmpl of DOC_TEMPLATES) {\n const dest = join(\n projectDir, 'docs', 'agents', tmpl\n )\n t.ok(\n existsSync(dest),\n `docs/agents/${tmpl} should still exist`\n )\n }\n})\n\ntest('checkGhAuth exists and is callable', t => {\n t.equal(\n typeof checkGhAuth,\n 'function',\n 'checkGhAuth should be a function'\n )\n})\n\ntest('setup with tracker:local copies local markdown template', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n const trackerPath = join(\n projectDir, 'docs', 'agents', 'issue-tracker.md'\n )\n t.ok(\n existsSync(trackerPath),\n 'docs/agents/issue-tracker.md should exist'\n )\n const content = readFileSync(trackerPath, 'utf8')\n t.ok(\n content.includes('# issue-tracker.md'),\n 'should copy local markdown template'\n )\n})\n\ntest('setup with tracker:github copies github template', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'github',\n })\n\n const trackerPath = join(\n projectDir, 'docs', 'agents', 'issue-tracker.md'\n )\n t.ok(\n existsSync(trackerPath),\n 'docs/agents/issue-tracker.md should exist'\n )\n const content = readFileSync(trackerPath, 'utf8')\n t.ok(\n content.includes('# issue-tracker-github.md'),\n 'should copy github template'\n )\n})\n\ntest('setup creates AGENTS.md with local markdown text', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n const agentsMdPath = join(projectDir, 'AGENTS.md')\n t.ok(\n existsSync(agentsMdPath),\n 'AGENTS.md should exist'\n )\n const content = readFileSync(agentsMdPath, 'utf8')\n t.ok(\n content.includes('local markdown files'),\n 'should mention local markdown'\n )\n})\n\ntest('setup creates AGENTS.md with GitHub Issues text', t => {\n const {\n projectDir, bundledSkillsDir, docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'github',\n })\n\n const agentsMdPath = join(projectDir, 'AGENTS.md')\n t.ok(\n existsSync(agentsMdPath),\n 'AGENTS.md should exist'\n )\n const content = readFileSync(agentsMdPath, 'utf8')\n t.ok(\n content.includes('GitHub Issues'),\n 'should mention GitHub Issues'\n )\n})\n\ntest(\n 'tracker template overwrites when switching trackers',\n t => {\n const {\n projectDir, bundledSkillsDir,\n docsTemplatesDir,\n } = makeTempProject()\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'local',\n })\n\n const trackerPath = join(\n projectDir, 'docs', 'agents',\n 'issue-tracker.md'\n )\n const localContent = readFileSync(\n trackerPath, 'utf8'\n )\n t.ok(\n localContent.includes('# issue-tracker.md'),\n 'should have local template initially'\n )\n\n setup({\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n tracker:'github',\n })\n\n const githubContent = readFileSync(\n trackerPath, 'utf8'\n )\n t.ok(\n githubContent.includes('# issue-tracker-github.md'),\n 'should overwrite with GitHub template'\n )\n t.ok(\n !githubContent.includes('# issue-tracker.md'),\n 'should not contain local template anymore'\n )\n }\n)\n", "import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n symlinkSync,\n writeFileSync,\n} from 'node:fs'\nimport { join } from 'node:path'\nimport { execSync } from 'node:child_process'\n\nexport const SKILL_DIRS = [\n 'grill', 'grilling', 'domain-modeling',\n 'to-spec', 'to-tickets', 'tdd',\n] as const\n\nexport const DOC_TEMPLATES = [\n 'triage-labels.md',\n 'domain.md',\n] as const\n\nexport function checkGhAuth ():boolean {\n try {\n execSync('gh auth status', { stdio:'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nexport type TrackerKind = 'github'|'local'\n\nexport type SetupOpts = {\n bundledSkillsDir:string\n docsTemplatesDir:string\n projectDir:string\n claude?:boolean\n tracker:TrackerKind\n}\n\nconst TRACKER_TEMPLATES:Record<TrackerKind, string> = {\n local:'issue-tracker.md',\n github:'issue-tracker-github.md',\n}\n\nexport function setup (opts:SetupOpts):void {\n const {\n bundledSkillsDir,\n docsTemplatesDir,\n projectDir,\n claude,\n tracker,\n } = opts\n const agentsSkillsDir = join(\n projectDir, '.agents', 'skills'\n )\n\n const upstream = JSON.parse(\n readFileSync(\n join(bundledSkillsDir, 'upstream.json'),\n 'utf8'\n )\n ) as { repo:string; commit:string }\n\n console.log('Installing skills to .agents/skills/\\n')\n\n for (const skill of SKILL_DIRS) {\n const src = join(bundledSkillsDir, skill)\n const dest = join(agentsSkillsDir, skill)\n mkdirSync(dest, { recursive:true })\n cpSync(src, dest, { recursive:true })\n const files = readdirSync(src)\n console.log(\n ` ${skill}/ (${files.join(', ')})`\n )\n }\n\n if (claude) {\n const claudeSkillsDir = join(\n projectDir, '.claude', 'skills'\n )\n mkdirSync(claudeSkillsDir, { recursive:true })\n\n for (const skill of SKILL_DIRS) {\n const linkPath = join(claudeSkillsDir, skill)\n const target = join(\n '..', '..', '.agents', 'skills', skill\n )\n if (existsSync(linkPath)) continue\n symlinkSync(target, linkPath)\n }\n\n console.log(\n '\\nCreated symlinks in .claude/skills/'\n )\n }\n\n const docsAgentsDir = join(\n projectDir, 'docs', 'agents'\n )\n mkdirSync(docsAgentsDir, { recursive:true })\n\n console.log('')\n for (const tmpl of DOC_TEMPLATES) {\n const dest = join(docsAgentsDir, tmpl)\n if (existsSync(dest)) {\n console.log(\n ` docs/agents/${tmpl} (already exists)`\n )\n continue\n }\n const src = join(docsTemplatesDir, tmpl)\n writeFileSync(dest, readFileSync(src, 'utf8'))\n console.log(` docs/agents/${tmpl} (created)`)\n }\n\n const trackerSrc = join(\n docsTemplatesDir, TRACKER_TEMPLATES[tracker]\n )\n const trackerDest = join(docsAgentsDir, 'issue-tracker.md')\n writeFileSync(trackerDest, readFileSync(trackerSrc, 'utf8'))\n console.log(\n ` docs/agents/issue-tracker.md (${tracker})`\n )\n\n const trackerLine = tracker === 'github' ?\n 'Issues are tracked via GitHub Issues using the `gh` ' +\n 'CLI.' :\n 'Issues are tracked as local markdown files under ' +\n '`.scratch/`.'\n\n const agentsMd = [\n '## Agent skills',\n '',\n '### Issue tracker',\n '',\n `${trackerLine} See \\`docs/agents/issue-tracker.md\\`.`,\n '',\n '### Triage labels',\n '',\n 'Default label vocabulary. See ' +\n '`docs/agents/triage-labels.md`.',\n '',\n '### Domain docs',\n '',\n 'Single-context layout. See `docs/agents/domain.md`.',\n '',\n ].join('\\n')\n\n writeFileSync(join(projectDir, 'AGENTS.md'), agentsMd)\n console.log('\\n AGENTS.md (updated)')\n\n console.log(\n `\\nSource: ${upstream.repo} @ ${upstream.commit}`\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["mkdirSync", "writeFileSync", "existsSync", "readFileSync", "join", "join", "mkdirSync", "writeFileSync", "existsSync", "readFileSync"]
|
|
7
|
+
}
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Docs
|
|
2
|
+
|
|
3
|
+
## Some Links
|
|
4
|
+
|
|
5
|
+
* [`nightshift`](https://github.com/Shaurya-Sethi/nightshift/) -- a Rust CLI
|
|
6
|
+
designed specifically for the Pocock skills.
|
|
7
|
+
* [tracer bullets](https://www.aihero.dev/tracer-bullets) -- a metaphor that
|
|
8
|
+
I like, a good programming style
|
|
9
|
+
* [chainlink](https://github.com/dollspace-gay/chainlink) -- a CLI issue
|
|
10
|
+
tracker for AI Agents
|
|
11
|
+
* [mattpocock/skills](https://github.com/mattpocock/skills) -- the skills that
|
|
12
|
+
this CLI targets.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Domain Docs
|
|
2
|
+
|
|
3
|
+
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
|
|
4
|
+
|
|
5
|
+
## Before exploring, read these
|
|
6
|
+
|
|
7
|
+
- **`CONTEXT.md`** at the repo root, or
|
|
8
|
+
- **`CONTEXT-MAP.md`** at the repo root if it exists: it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
|
|
9
|
+
- **`docs/adr/`**: read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
|
|
10
|
+
|
|
11
|
+
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
|
|
12
|
+
|
|
13
|
+
## File structure
|
|
14
|
+
|
|
15
|
+
Single-context repo (most repos):
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/
|
|
19
|
+
├── CONTEXT.md
|
|
20
|
+
├── docs/adr/
|
|
21
|
+
│ ├── 0001-event-sourced-orders.md
|
|
22
|
+
│ └── 0002-postgres-for-write-model.md
|
|
23
|
+
└── src/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Use the glossary's vocabulary
|
|
27
|
+
|
|
28
|
+
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
|
|
29
|
+
|
|
30
|
+
If the concept you need isn't in the glossary yet, that's a signal: either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).
|
|
31
|
+
|
|
32
|
+
## Flag ADR conflicts
|
|
33
|
+
|
|
34
|
+
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
|
|
35
|
+
|
|
36
|
+
> _Contradicts ADR-0007 (event-sourced orders), but worth reopening because..._
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Issue tracker: Local Markdown
|
|
2
|
+
|
|
3
|
+
Issues and specs for this repo live as markdown files in `.scratch/`.
|
|
4
|
+
|
|
5
|
+
## Conventions
|
|
6
|
+
|
|
7
|
+
- One feature per directory: `.scratch/<feature-slug>/`
|
|
8
|
+
- The spec is `.scratch/<feature-slug>/spec.md`
|
|
9
|
+
- Implementation issues are one file per ticket at `.scratch/<feature-slug>/issues/<NN>-<slug>.md`, numbered from `01`, never a single combined tickets file
|
|
10
|
+
- Triage state is recorded as a `Status:` line near the top of each issue file (see `triage-labels.md` for the role strings)
|
|
11
|
+
- Comments and conversation history append to the bottom of the file under a `## Comments` heading
|
|
12
|
+
|
|
13
|
+
## When a skill says "publish to the issue tracker"
|
|
14
|
+
|
|
15
|
+
Create a new file under `.scratch/<feature-slug>/` (creating the directory if needed).
|
|
16
|
+
|
|
17
|
+
## When a skill says "fetch the relevant ticket"
|
|
18
|
+
|
|
19
|
+
Read the file at the referenced path. The user will normally pass the path or the issue number directly.
|
|
20
|
+
|
|
21
|
+
## Wayfinding operations
|
|
22
|
+
|
|
23
|
+
Used by `/wayfinder`. The **map** is a file with one **child** file per ticket.
|
|
24
|
+
|
|
25
|
+
- **Map**: `.scratch/<effort>/map.md` (the Notes / Decisions-so-far / Fog body).
|
|
26
|
+
- **Child ticket**: `.scratch/<effort>/issues/NN-<slug>.md`, numbered from `01`, with the question in the body. A `Type:` line records the ticket type (`research`/`prototype`/`grilling`/`task`); a `Status:` line records `claimed`/`resolved`.
|
|
27
|
+
- **Blocking**: a `Blocked by: NN, NN` line near the top. A ticket is unblocked when every file it lists is `resolved`.
|
|
28
|
+
- **Frontier**: scan `.scratch/<effort>/issues/` for files that are open, unblocked, and unclaimed; first by number wins.
|
|
29
|
+
- **Claim**: set `Status: claimed` and save before any work.
|
|
30
|
+
- **Resolve**: append the answer under an `## Answer` heading, set `Status: resolved`, then append a context pointer (gist + link) to the map's Decisions-so-far in `map.md`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Triage Labels
|
|
2
|
+
|
|
3
|
+
The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.
|
|
4
|
+
|
|
5
|
+
| Label in mattpocock/skills | Label in our tracker | Meaning |
|
|
6
|
+
| -------------------------- | -------------------- | ---------------------------------------- |
|
|
7
|
+
| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue |
|
|
8
|
+
| `needs-info` | `needs-info` | Waiting on reporter for more information |
|
|
9
|
+
| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent |
|
|
10
|
+
| `ready-for-human` | `ready-for-human` | Requires human implementation |
|
|
11
|
+
| `wontfix` | `wontfix` | Will not be actioned |
|
|
12
|
+
|
|
13
|
+
When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table.
|
|
14
|
+
|
|
15
|
+
Edit the right-hand column to match whatever vocabulary you actually use.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Phase 2: Future Work -- Orchestrator GitHub Support
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Enable `nightralph <provider>` to pull tickets from GitHub Issues instead of `.scratch/` when the project is configured for GitHub tracking. This allows teams to use GitHub Issues as a native issue tracking system while leveraging nightralph's orchestrator for workflow execution.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
Phase 1 established the choice between local markdown and GitHub Issues for issue tracking. Phase 2 extends the orchestrator (`src/orchestrator.ts`) to support GitHub-backed issues, enabling end-to-end integration from issue discovery through status updates.
|
|
10
|
+
|
|
11
|
+
## Changes Required in the Orchestrator
|
|
12
|
+
|
|
13
|
+
### Tracker Detection
|
|
14
|
+
|
|
15
|
+
The orchestrator needs to detect which tracker is in use by reading the title line from `docs/agents/issue-tracker.md`:
|
|
16
|
+
|
|
17
|
+
- If title is `# Issue tracker: GitHub`, use GitHub mode
|
|
18
|
+
- If title is `# Issue tracker: Local Markdown`, use local mode (current behavior)
|
|
19
|
+
|
|
20
|
+
### Scan Tickets (`scanTickets()` function)
|
|
21
|
+
|
|
22
|
+
Currently, `scanTickets()` reads `.scratch/<feature>/issues/` for numbered markdown files.
|
|
23
|
+
|
|
24
|
+
**GitHub variant:**
|
|
25
|
+
- Query `gh issue list --json number,title,body,labels,state --label <feature>` to retrieve issues
|
|
26
|
+
- Parse JSON output into ticket objects
|
|
27
|
+
- Handle pagination if needed
|
|
28
|
+
|
|
29
|
+
**Local variant:**
|
|
30
|
+
- Keep existing implementation (reads markdown files)
|
|
31
|
+
|
|
32
|
+
### Status Parsing
|
|
33
|
+
|
|
34
|
+
Currently, the orchestrator reads `Status:` lines from markdown files.
|
|
35
|
+
|
|
36
|
+
**GitHub variant:**
|
|
37
|
+
- Map GitHub labels to status: look for labels like `status-pending`, `status-in-progress`, `status-done`, `status-blocked`
|
|
38
|
+
- Extract status from issue label set
|
|
39
|
+
|
|
40
|
+
**Local variant:**
|
|
41
|
+
- Keep existing implementation (reads markdown Status: field)
|
|
42
|
+
|
|
43
|
+
### Blocker Parsing
|
|
44
|
+
|
|
45
|
+
Currently, the orchestrator reads `Blocked by:` lines from markdown files.
|
|
46
|
+
|
|
47
|
+
**GitHub variant:**
|
|
48
|
+
- Query issue dependencies via `gh api repos/{owner}/{repo}/issues/{issue_number}/blocking_issues_and_pull_requests`
|
|
49
|
+
- Extract blocker relationships from API response
|
|
50
|
+
|
|
51
|
+
**Local variant:**
|
|
52
|
+
- Keep existing implementation (reads markdown Blocked by: field)
|
|
53
|
+
|
|
54
|
+
### Status Updates
|
|
55
|
+
|
|
56
|
+
Currently, when a wave completes, the orchestrator writes `Status: done` to the markdown file.
|
|
57
|
+
|
|
58
|
+
**GitHub variant:**
|
|
59
|
+
- Run `gh issue close <issue_number>` to close the issue
|
|
60
|
+
- Optionally add a comment or label to mark completion
|
|
61
|
+
|
|
62
|
+
**Local variant:**
|
|
63
|
+
- Keep existing implementation (writes to markdown file)
|
|
64
|
+
|
|
65
|
+
## CLI Surface Changes
|
|
66
|
+
|
|
67
|
+
The `--dir` and `--spec` flags assume local file-based issues. GitHub mode requires different scoping mechanisms:
|
|
68
|
+
|
|
69
|
+
### New Flags for GitHub Mode
|
|
70
|
+
|
|
71
|
+
- `--label <label>` -- filter issues by GitHub label (e.g., `nightralph`, `phase-1`)
|
|
72
|
+
- `--milestone <milestone>` -- filter issues by GitHub milestone
|
|
73
|
+
- `--assignee <user>` -- filter issues assigned to a specific user
|
|
74
|
+
|
|
75
|
+
### Feature Selection
|
|
76
|
+
|
|
77
|
+
The `resolveIssuesDir` function in `index.ts` currently prompts for a local feature directory. A GitHub-aware variant would:
|
|
78
|
+
|
|
79
|
+
1. Query `gh issue list --label nightralph --json labels` to discover available labels
|
|
80
|
+
2. Prompt user to select which label(s) to execute
|
|
81
|
+
3. Optional: support milestone selection if `--milestone` is not specified
|
|
82
|
+
|
|
83
|
+
## Testing Considerations
|
|
84
|
+
|
|
85
|
+
### Test Strategy
|
|
86
|
+
|
|
87
|
+
GitHub orchestrator tests need to handle the challenge of testing against external API calls:
|
|
88
|
+
|
|
89
|
+
**Option 1: Mocked `gh` Output**
|
|
90
|
+
- Mock the `gh` command output using standard test mocking patterns
|
|
91
|
+
- Provide fixed JSON fixtures for different issue scenarios
|
|
92
|
+
- Tests run fast and require no network access
|
|
93
|
+
|
|
94
|
+
**Option 2: Test Repository**
|
|
95
|
+
- Set up a dedicated test GitHub repository
|
|
96
|
+
- Run integration tests against real GitHub Issues
|
|
97
|
+
- More realistic but slower and requires GitHub API rate-limit budget
|
|
98
|
+
|
|
99
|
+
**Option 3: Hybrid Approach**
|
|
100
|
+
- Unit tests with mocked `gh` output for core logic
|
|
101
|
+
- Optional integration tests with test repository for end-to-end validation
|
|
102
|
+
- Recommended for this project
|
|
103
|
+
|
|
104
|
+
### Execution Model Remains Unchanged
|
|
105
|
+
|
|
106
|
+
The wave-based execution model (parallel independent tickets, sequential blocked ones) stays the same. GitHub mode only changes the I/O layer for reading and writing issue state.
|
|
107
|
+
|
|
108
|
+
## Implementation Phases
|
|
109
|
+
|
|
110
|
+
### Phase 2a: Tracker Detection
|
|
111
|
+
- Add function to detect active tracker from `docs/agents/issue-tracker.md`
|
|
112
|
+
- Route `scanTickets()` based on detection
|
|
113
|
+
|
|
114
|
+
### Phase 2b: GitHub Scan and Parse
|
|
115
|
+
- Implement `scanTicketsFromGitHub()` function
|
|
116
|
+
- Add status and blocker parsing for GitHub labels and API calls
|
|
117
|
+
- Add error handling for `gh` CLI availability and authentication
|
|
118
|
+
|
|
119
|
+
### Phase 2c: GitHub Status Updates
|
|
120
|
+
- Implement status update logic for GitHub Issues
|
|
121
|
+
- Handle issue closing and labeling
|
|
122
|
+
|
|
123
|
+
### Phase 2d: CLI and UX
|
|
124
|
+
- Add `--label` and `--milestone` flags
|
|
125
|
+
- Implement GitHub-aware feature selection prompt
|
|
126
|
+
- Add documentation for GitHub workflow
|
|
127
|
+
|
|
128
|
+
### Phase 2e: Testing
|
|
129
|
+
- Write unit tests with mocked `gh` output
|
|
130
|
+
- Optional: add integration tests with test repository
|
|
131
|
+
- Verify backward compatibility with local markdown mode
|
|
132
|
+
|
|
133
|
+
## Dependencies
|
|
134
|
+
|
|
135
|
+
- `gh` CLI must be installed and authenticated
|
|
136
|
+
- GitHub repository must be configured in current git remote
|
|
137
|
+
- Existing test infrastructure (@substrate-system/tapzero, temp directories)
|
|
138
|
+
|
|
139
|
+
## Backward Compatibility
|
|
140
|
+
|
|
141
|
+
- Local markdown mode continues to work without changes
|
|
142
|
+
- Projects using local markdown issue tracking are unaffected
|
|
143
|
+
- The orchestrator can serve projects with either tracker type
|
|
144
|
+
- No breaking changes to existing CLI surface for local mode
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Issue Tracker Choice -- Implementation Plan
|
|
2
|
+
|
|
3
|
+
**Goal:** Add an inquirer prompt to `nightralph setup` that lets users choose between GitHub Issues and Local Markdown as their issue tracker, with `gh` prerequisite checking and correct template installation.
|
|
4
|
+
|
|
5
|
+
**Architecture:** The setup function gains a `tracker` field on `SetupOpts` (`'github' | 'local'`). The CLI handler in `index.ts` prompts for the choice via `@inquirer/prompts` `select`, runs `gh auth status` when GitHub is chosen, then passes the result to `setup()`. The `setup()` function copies the correct `issue-tracker*.md` template and writes an AGENTS.md that reflects the choice.
|
|
6
|
+
|
|
7
|
+
**Tech Stack:** TypeScript, yargs, @inquirer/prompts (already installed), Node child_process for `gh` CLI check
|
|
8
|
+
|
|
9
|
+
**Scope:** 2 phases from context bundle (phases 1-2)
|
|
10
|
+
|
|
11
|
+
**Codebase verified:** 2026-08-27
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Acceptance Criteria Coverage
|
|
16
|
+
|
|
17
|
+
This phase implements and tests:
|
|
18
|
+
|
|
19
|
+
### issue-tracker-choice.AC1: Tracker choice prompt
|
|
20
|
+
- **issue-tracker-choice.AC1.1 Success:** Running `nightralph setup` prompts user to choose between "GitHub Issues" and "Local Markdown"
|
|
21
|
+
- **issue-tracker-choice.AC1.2 Success:** Choosing "Local Markdown" installs the local markdown issue-tracker template to `docs/agents/issue-tracker.md`
|
|
22
|
+
|
|
23
|
+
### issue-tracker-choice.AC2: GitHub prerequisite check
|
|
24
|
+
- **issue-tracker-choice.AC2.1 Success:** Choosing "GitHub Issues" runs `gh auth status` and proceeds if authenticated
|
|
25
|
+
- **issue-tracker-choice.AC2.2 Failure:** If `gh` is not installed or not authenticated, setup prints a message and exits with code 2
|
|
26
|
+
- **issue-tracker-choice.AC2.3 Success:** If `gh` is authenticated, setup installs the GitHub issue-tracker template
|
|
27
|
+
|
|
28
|
+
### issue-tracker-choice.AC3: AGENTS.md reflects choice
|
|
29
|
+
- **issue-tracker-choice.AC3.1 Success:** After setup with Local Markdown, AGENTS.md issue tracker section says "local markdown files under `.scratch/`"
|
|
30
|
+
- **issue-tracker-choice.AC3.2 Success:** After setup with GitHub Issues, AGENTS.md issue tracker section says "GitHub Issues" with `gh` CLI reference
|
|
31
|
+
|
|
32
|
+
### issue-tracker-choice.AC4: Template installation
|
|
33
|
+
- **issue-tracker-choice.AC4.1 Success:** The correct `issue-tracker.md` is installed to `docs/agents/` based on tracker choice
|
|
34
|
+
- **issue-tracker-choice.AC4.2 Success:** Non-tracker templates (triage-labels.md, domain.md) are still installed with idempotency checks
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Phase 1: Setup Prompt, Template, and AGENTS.md
|
|
39
|
+
|
|
40
|
+
<!-- START_SUBCOMPONENT_A (tasks 1-2) -->
|
|
41
|
+
|
|
42
|
+
<!-- START_TASK_1 -->
|
|
43
|
+
### Task 1: Create GitHub issue tracker template
|
|
44
|
+
|
|
45
|
+
**Files:**
|
|
46
|
+
- Create: `src/docs-templates/issue-tracker-github.md`
|
|
47
|
+
|
|
48
|
+
**Implementation:**
|
|
49
|
+
|
|
50
|
+
Create the GitHub issue tracker template at `src/docs-templates/issue-tracker-github.md`. Optionally reference the Matt Pocock template at `~/.claude/plugins/cache/claude-plugins-official/mattpocock-skills/1.2.3/skills/engineering/setup-matt-pocock-skills/issue-tracker-github.md` for conventions (this path is machine-local and not a required input -- the template can be written from scratch using `gh` CLI documentation). Adapt to match nightralph's conventions (simpler, no GitLab, no PR triage surface).
|
|
51
|
+
|
|
52
|
+
The template should document:
|
|
53
|
+
- Title: `# Issue tracker: GitHub`
|
|
54
|
+
- How to create/read/list/comment/close issues via `gh` CLI
|
|
55
|
+
- How to apply and remove labels
|
|
56
|
+
- The "publish to issue tracker" instruction (create a GitHub issue)
|
|
57
|
+
- The "fetch the relevant ticket" instruction (`gh issue view`)
|
|
58
|
+
- Wayfinding operations using GitHub sub-issues or task lists
|
|
59
|
+
- Blocking via GitHub native issue dependencies
|
|
60
|
+
- Frontier query, claim (assign), and resolve (close) operations
|
|
61
|
+
|
|
62
|
+
The file is copied verbatim by the build system (`cp -r ./src/docs-templates/* ./dist/docs-templates`), so no build changes are needed.
|
|
63
|
+
|
|
64
|
+
**Verification:**
|
|
65
|
+
Run: `ls src/docs-templates/issue-tracker-github.md`
|
|
66
|
+
Expected: File exists
|
|
67
|
+
|
|
68
|
+
**Commit:** `feat: add GitHub issue tracker template`
|
|
69
|
+
<!-- END_TASK_1 -->
|
|
70
|
+
|
|
71
|
+
<!-- START_TASK_2 -->
|
|
72
|
+
### Task 2: Build and verify template is included
|
|
73
|
+
|
|
74
|
+
**Files:**
|
|
75
|
+
- None modified (build system verification)
|
|
76
|
+
|
|
77
|
+
**Verification:**
|
|
78
|
+
Run: `npm run build`
|
|
79
|
+
Expected: Build succeeds, `dist/docs-templates/issue-tracker-github.md` exists
|
|
80
|
+
|
|
81
|
+
Run: `ls dist/docs-templates/`
|
|
82
|
+
Expected: Shows `domain.md`, `issue-tracker-github.md`, `issue-tracker.md`, `triage-labels.md`
|
|
83
|
+
|
|
84
|
+
**Commit:** No commit needed -- build verification only.
|
|
85
|
+
<!-- END_TASK_2 -->
|
|
86
|
+
|
|
87
|
+
<!-- END_SUBCOMPONENT_A -->
|
|
88
|
+
|
|
89
|
+
<!-- START_SUBCOMPONENT_B (tasks 3-5) -->
|
|
90
|
+
|
|
91
|
+
<!-- START_TASK_3 -->
|
|
92
|
+
### Task 3: Add `checkGhAuth` function to setup.ts
|
|
93
|
+
|
|
94
|
+
**Verifies:** issue-tracker-choice.AC2.1, issue-tracker-choice.AC2.2
|
|
95
|
+
|
|
96
|
+
**Files:**
|
|
97
|
+
- Modify: `src/setup.ts:1-10` (add import for `execSync`)
|
|
98
|
+
|
|
99
|
+
**Implementation:**
|
|
100
|
+
|
|
101
|
+
Add a new exported function `checkGhAuth` to `src/setup.ts`. This function:
|
|
102
|
+
1. Calls `execSync('gh auth status', { stdio:'ignore' })` in a try/catch
|
|
103
|
+
2. Returns `true` if the command succeeds (exit 0)
|
|
104
|
+
3. Returns `false` if it throws (command not found or auth failure)
|
|
105
|
+
|
|
106
|
+
Keep it as a pure check -- no console output, no process.exit. The caller (`index.ts`) decides what to do with the result.
|
|
107
|
+
|
|
108
|
+
Add `execSync` to the imports from `node:child_process`.
|
|
109
|
+
|
|
110
|
+
**Testing:**
|
|
111
|
+
Tests must verify:
|
|
112
|
+
- issue-tracker-choice.AC2.1: `checkGhAuth` returns true when `gh` is authenticated
|
|
113
|
+
- issue-tracker-choice.AC2.2: `checkGhAuth` returns false when `gh` is not available
|
|
114
|
+
|
|
115
|
+
Note: this is a thin wrapper around exec. The function's behavior depends on the system state (`gh` installed/authenticated). Integration testing is appropriate -- unit tests with mocked exec would just test the mock. Testing guidance: verify the function exists and has the right signature; actual auth checking is tested via the CLI integration.
|
|
116
|
+
|
|
117
|
+
**Verification:**
|
|
118
|
+
Run: `npx tsc --noEmit`
|
|
119
|
+
Expected: No type errors
|
|
120
|
+
|
|
121
|
+
**Commit:** `feat: add checkGhAuth helper`
|
|
122
|
+
<!-- END_TASK_3 -->
|
|
123
|
+
|
|
124
|
+
<!-- START_TASK_4 -->
|
|
125
|
+
### Task 4: Refactor setup.ts for tracker-aware template copying
|
|
126
|
+
|
|
127
|
+
**Verifies:** issue-tracker-choice.AC1.2, issue-tracker-choice.AC2.3, issue-tracker-choice.AC4.1, issue-tracker-choice.AC4.2
|
|
128
|
+
|
|
129
|
+
**Files:**
|
|
130
|
+
- Modify: `src/setup.ts:12-21` (DOC_TEMPLATES constant)
|
|
131
|
+
- Modify: `src/setup.ts:23-28` (SetupOpts type)
|
|
132
|
+
- Modify: `src/setup.ts:80-103` (template copying section and end of function)
|
|
133
|
+
|
|
134
|
+
**Implementation:**
|
|
135
|
+
|
|
136
|
+
1. **Update `DOC_TEMPLATES`** -- remove `'issue-tracker.md'` from the array. It becomes tracker-specific and is handled separately. The constant becomes:
|
|
137
|
+
```typescript
|
|
138
|
+
export const DOC_TEMPLATES = [
|
|
139
|
+
'triage-labels.md',
|
|
140
|
+
'domain.md',
|
|
141
|
+
] as const
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
2. **Add tracker type and update `SetupOpts`** -- add a string literal union type and a `tracker` field:
|
|
145
|
+
```typescript
|
|
146
|
+
export type TrackerKind = 'github' | 'local'
|
|
147
|
+
|
|
148
|
+
export type SetupOpts = {
|
|
149
|
+
bundledSkillsDir:string
|
|
150
|
+
docsTemplatesDir:string
|
|
151
|
+
projectDir:string
|
|
152
|
+
claude?:boolean
|
|
153
|
+
tracker:TrackerKind
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
3. **Add tracker template mapping** -- define which source template maps to which tracker choice:
|
|
158
|
+
```typescript
|
|
159
|
+
const TRACKER_TEMPLATES:Record<TrackerKind, string> = {
|
|
160
|
+
local:'issue-tracker.md',
|
|
161
|
+
github:'issue-tracker-github.md',
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
4. **Add tracker template copy logic** -- after the existing `DOC_TEMPLATES` loop (line 98), add logic to copy the tracker-specific template. The destination is always `issue-tracker.md` in `docs/agents/`. Unlike other templates, this one overwrites existing content (so re-running setup with a different tracker choice takes effect):
|
|
166
|
+
```typescript
|
|
167
|
+
const trackerSrc = join(
|
|
168
|
+
docsTemplatesDir, TRACKER_TEMPLATES[tracker]
|
|
169
|
+
)
|
|
170
|
+
const trackerDest = join(docsAgentsDir, 'issue-tracker.md')
|
|
171
|
+
writeFileSync(trackerDest, readFileSync(trackerSrc, 'utf8'))
|
|
172
|
+
console.log(
|
|
173
|
+
` docs/agents/issue-tracker.md (${tracker})`
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
5. **Add AGENTS.md writing** -- after template copying, write AGENTS.md with tracker-appropriate content. AGENTS.md is fully regenerated on each setup run (not patched); any custom sections a user added will be overwritten. This is acceptable because the file is small and deterministic -- users who need custom content should edit it after setup. Define the issue tracker description based on the choice:
|
|
178
|
+
```typescript
|
|
179
|
+
const trackerLine = tracker === 'github' ?
|
|
180
|
+
'Issues are tracked via GitHub Issues using the `gh` CLI.' :
|
|
181
|
+
'Issues are tracked as local markdown files under `.scratch/`.'
|
|
182
|
+
|
|
183
|
+
const agentsMd = [
|
|
184
|
+
'## Agent skills',
|
|
185
|
+
'',
|
|
186
|
+
'### Issue tracker',
|
|
187
|
+
'',
|
|
188
|
+
`${trackerLine} See \`docs/agents/issue-tracker.md\`.`,
|
|
189
|
+
'',
|
|
190
|
+
'### Triage labels',
|
|
191
|
+
'',
|
|
192
|
+
'Default label vocabulary. See `docs/agents/triage-labels.md`.',
|
|
193
|
+
'',
|
|
194
|
+
'### Domain docs',
|
|
195
|
+
'',
|
|
196
|
+
'Single-context layout. See `docs/agents/domain.md`.',
|
|
197
|
+
'',
|
|
198
|
+
].join('\n')
|
|
199
|
+
|
|
200
|
+
writeFileSync(join(projectDir, 'AGENTS.md'), agentsMd)
|
|
201
|
+
console.log('\n AGENTS.md (updated)')
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Testing:**
|
|
205
|
+
Tests must verify:
|
|
206
|
+
- issue-tracker-choice.AC1.2: `setup({..., tracker:'local'})` creates `docs/agents/issue-tracker.md` with local markdown content
|
|
207
|
+
- issue-tracker-choice.AC2.3: `setup({..., tracker:'github'})` creates `docs/agents/issue-tracker.md` with GitHub content
|
|
208
|
+
- issue-tracker-choice.AC4.1: The installed template content matches the source template for the chosen tracker
|
|
209
|
+
- issue-tracker-choice.AC4.2: `triage-labels.md` and `domain.md` are still installed with idempotency
|
|
210
|
+
|
|
211
|
+
**Verification:**
|
|
212
|
+
Run: `npx tsc --noEmit`
|
|
213
|
+
Expected: No type errors
|
|
214
|
+
|
|
215
|
+
**Commit:** `feat: tracker-aware template copying and AGENTS.md generation`
|
|
216
|
+
<!-- END_TASK_4 -->
|
|
217
|
+
|
|
218
|
+
<!-- START_TASK_5 -->
|
|
219
|
+
### Task 5: Update index.ts with tracker prompt and gh check
|
|
220
|
+
|
|
221
|
+
**Verifies:** issue-tracker-choice.AC1.1, issue-tracker-choice.AC2.1, issue-tracker-choice.AC2.2, issue-tracker-choice.AC3.1, issue-tracker-choice.AC3.2
|
|
222
|
+
|
|
223
|
+
**Files:**
|
|
224
|
+
- Modify: `src/index.ts:7` (add `checkGhAuth` to setup import)
|
|
225
|
+
- Modify: `src/index.ts:8` (add `TrackerKind` type import)
|
|
226
|
+
- Modify: `src/index.ts:20-38` (setup command handler)
|
|
227
|
+
|
|
228
|
+
**Implementation:**
|
|
229
|
+
|
|
230
|
+
1. **Update imports** -- add `checkGhAuth` and `TrackerKind` to the import from `./setup.js`
|
|
231
|
+
|
|
232
|
+
2. **Make setup handler async** -- change the handler callback from sync to async
|
|
233
|
+
|
|
234
|
+
3. **Add tracker prompt** -- before calling `setup()`, prompt the user with `select`:
|
|
235
|
+
```typescript
|
|
236
|
+
const tracker = await select<TrackerKind>({
|
|
237
|
+
message:'Issue tracker format',
|
|
238
|
+
choices:[
|
|
239
|
+
{
|
|
240
|
+
name:'Local Markdown',
|
|
241
|
+
value:'local' as const,
|
|
242
|
+
description:'Issues as .md files in .scratch/',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
name:'GitHub Issues',
|
|
246
|
+
value:'github' as const,
|
|
247
|
+
description:'Issues via gh CLI',
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
})
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
4. **Add gh auth check** -- if tracker is `'github'`, call `checkGhAuth()`. If it returns false, print a message and exit:
|
|
254
|
+
```typescript
|
|
255
|
+
if (tracker === 'github') {
|
|
256
|
+
if (!checkGhAuth()) {
|
|
257
|
+
console.error(
|
|
258
|
+
'GitHub Issues requires the gh CLI, ' +
|
|
259
|
+
'authenticated.\n' +
|
|
260
|
+
'Install: https://cli.github.com\n' +
|
|
261
|
+
'Then run: gh auth login'
|
|
262
|
+
)
|
|
263
|
+
process.exit(2)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
5. **Pass tracker to setup** -- add `tracker` to the options object passed to `setup()`
|
|
269
|
+
|
|
270
|
+
**Testing:**
|
|
271
|
+
Tests must verify:
|
|
272
|
+
- issue-tracker-choice.AC1.1: The prompt is presented (this is an integration concern -- verified by running the CLI)
|
|
273
|
+
- issue-tracker-choice.AC2.1: GitHub path calls `checkGhAuth`
|
|
274
|
+
- issue-tracker-choice.AC2.2: Setup exits with code 2 when gh is not authenticated
|
|
275
|
+
|
|
276
|
+
Note: The CLI handler is thin glue -- its behavior is best tested via the unit tests on `setup()` and `checkGhAuth()` individually, plus a manual run of the CLI.
|
|
277
|
+
|
|
278
|
+
**Verification:**
|
|
279
|
+
Run: `npm run build`
|
|
280
|
+
Expected: Build succeeds
|
|
281
|
+
|
|
282
|
+
Run: `node dist/index.js setup --help`
|
|
283
|
+
Expected: Shows setup command help (the `--claude` flag)
|
|
284
|
+
|
|
285
|
+
**Commit:** `feat: add tracker choice prompt to setup command`
|
|
286
|
+
<!-- END_TASK_5 -->
|
|
287
|
+
|
|
288
|
+
<!-- END_SUBCOMPONENT_B -->
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
**Note:** After completing Phase 1, `npm test` will fail because existing tests call `setup()` without the new required `tracker` field. This is expected. Phase 2 Task 1 updates all existing test calls. Use `npx tsc --noEmit` and `npm run build` to verify Phase 1 correctness.
|