nitm-ai-dev-toolkit 3.0.23 → 5.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/CHANGELOG.md +44 -3
- package/README.md +93 -6
- package/bin/cli.js +155 -25
- package/bin/factory-archive.js +71 -0
- package/bin/factory-prune.js +79 -0
- package/bin/factory-watch.js +509 -0
- package/package.json +1 -1
- package/src/monorepo/.agents/skills/factory/SKILL.md +593 -0
- package/src/monorepo/.claude/agents/admin-portal.agent.md +1 -1
- package/src/monorepo/.claude/agents/api-specialist.agent.md +1 -1
- package/src/monorepo/.claude/agents/backend-architect.agent.md +1 -1
- package/src/monorepo/.claude/agents/documenter.agent.md +1 -1
- package/src/monorepo/.claude/agents/factory-approver.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-builder.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-reviewer-code.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-reviewer-security.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-reviewer-ui.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-reviewer-ux.agent.md +12 -0
- package/src/monorepo/.claude/agents/factory-spec-writer.agent.md +12 -0
- package/src/monorepo/.claude/agents/feature-builder.agent.md +1 -1
- package/src/monorepo/.claude/agents/frontend-developer.agent.md +1 -1
- package/src/monorepo/.claude/agents/green.agent.md +1 -1
- package/src/monorepo/.claude/agents/implementer.agent.md +1 -1
- package/src/monorepo/.claude/agents/planner.agent.md +1 -1
- package/src/monorepo/.claude/agents/red.agent.md +1 -1
- package/src/monorepo/.claude/agents/refactor.agent.md +1 -1
- package/src/monorepo/.claude/agents/researcher.agent.md +1 -1
- package/src/monorepo/.claude/agents/reviewer.agent.md +1 -1
- package/src/monorepo/.claude/agents/tdd.agent.md +1 -1
- package/src/monorepo/.claude/agents-snippets/factory-approver.md +72 -0
- package/src/monorepo/.claude/agents-snippets/factory-builder.md +101 -0
- package/src/monorepo/.claude/agents-snippets/factory-reviewer-code.md +57 -0
- package/src/monorepo/.claude/agents-snippets/factory-reviewer-security.md +48 -0
- package/src/monorepo/.claude/agents-snippets/factory-reviewer-ui.md +64 -0
- package/src/monorepo/.claude/agents-snippets/factory-reviewer-ux.md +64 -0
- package/src/monorepo/.claude/agents-snippets/factory-spec-writer.md +119 -0
- package/src/monorepo/.claude/agents-snippets/feature-builder.md +1 -1
- package/src/monorepo/.claude/commands/factory.md +24 -0
- package/src/monorepo/.claude/commands/ponytail-audit.md +4 -6
- package/src/monorepo/.claude/commands/ponytail-debt.md +3 -5
- package/src/monorepo/.claude/commands/ponytail-gain.md +2 -4
- package/src/monorepo/.claude/commands/ponytail-help.md +2 -4
- package/src/monorepo/.claude/commands/ponytail-review.md +3 -5
- package/src/monorepo/.claude/commands/ponytail.md +3 -5
- package/src/monorepo/.claude/prompt-snippets/assign-tasks.md +6 -2
- package/src/monorepo/.claude/prompt-snippets/bootstrap-patch.md +32 -17
- package/src/monorepo/.claude/prompt-snippets/bootstrap-upgrade.md +76 -51
- package/src/monorepo/.claude/prompt-snippets/bootstrap.md +57 -29
- package/src/monorepo/.claude/prompt-snippets/factory.md +20 -0
- package/src/monorepo/.claude/prompt-snippets/implement-feature.md +2 -2
- package/src/monorepo/.claude/prompt-snippets/tasks.md +49 -87
- package/src/monorepo/.claude/rules-snippets/documentation.md +8 -6
- package/src/monorepo/.cursor/agents/factory-approver.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-builder.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-reviewer-code.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-reviewer-security.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-reviewer-ui.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-reviewer-ux.agent.md +11 -0
- package/src/monorepo/.cursor/agents/factory-spec-writer.agent.md +11 -0
- package/src/monorepo/.cursor/commands/factory.md +24 -0
- package/src/monorepo/.github/agents/factory-approver.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-builder.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-reviewer-code.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-reviewer-security.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-reviewer-ui.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-reviewer-ux.agent.md +11 -0
- package/src/monorepo/.github/agents/factory-spec-writer.agent.md +11 -0
- package/src/monorepo/.github/prompts/factory.prompt.md +25 -0
- package/src/monorepo/.github/prompts/review-staged.prompt.md +1 -1
- package/src/monorepo/.opencode/agents/admin-portal.md +10 -4
- package/src/monorepo/.opencode/agents/api-specialist.md +10 -4
- package/src/monorepo/.opencode/agents/backend-architect.md +10 -4
- package/src/monorepo/.opencode/agents/documenter.md +10 -4
- package/src/monorepo/.opencode/agents/factory-approver.md +20 -0
- package/src/monorepo/.opencode/agents/factory-builder.md +20 -0
- package/src/monorepo/.opencode/agents/factory-reviewer-code.md +20 -0
- package/src/monorepo/.opencode/agents/factory-reviewer-security.md +20 -0
- package/src/monorepo/.opencode/agents/factory-reviewer-ui.md +20 -0
- package/src/monorepo/.opencode/agents/factory-reviewer-ux.md +20 -0
- package/src/monorepo/.opencode/agents/factory-spec-writer.md +20 -0
- package/src/monorepo/.opencode/agents/feature-builder.md +13 -5
- package/src/monorepo/.opencode/agents/frontend-developer.md +10 -4
- package/src/monorepo/.opencode/agents/green.md +10 -4
- package/src/monorepo/.opencode/agents/implementer.md +10 -4
- package/src/monorepo/.opencode/agents/planner.md +10 -4
- package/src/monorepo/.opencode/agents/red.md +10 -4
- package/src/monorepo/.opencode/agents/refactor.md +10 -4
- package/src/monorepo/.opencode/agents/researcher.md +10 -4
- package/src/monorepo/.opencode/agents/reviewer.md +10 -4
- package/src/monorepo/.opencode/agents/tdd.md +13 -5
- package/src/monorepo/.opencode/commands/factory.md +29 -0
- package/src/monorepo/.opencode/opencode.jsonc +8 -10
- package/src/monorepo/AGENTS.md +30 -1
- package/src/monorepo/CLAUDE.md +1 -1
- package/src/monorepo/README.md +20 -0
- package/src/monorepo/factory/README.md +194 -0
- package/src/monorepo/factory/_gitignore +5 -0
- package/src/repo/.agents/skills/factory/SKILL.md +593 -0
- package/src/repo/.claude/agents/admin-portal.agent.md +1 -1
- package/src/repo/.claude/agents/api-specialist.agent.md +1 -1
- package/src/repo/.claude/agents/backend-architect.agent.md +1 -1
- package/src/repo/.claude/agents/documenter.agent.md +2 -2
- package/src/repo/.claude/agents/factory-approver.agent.md +12 -0
- package/src/repo/.claude/agents/factory-builder.agent.md +12 -0
- package/src/repo/.claude/agents/factory-reviewer-code.agent.md +12 -0
- package/src/repo/.claude/agents/factory-reviewer-security.agent.md +12 -0
- package/src/repo/.claude/agents/factory-reviewer-ui.agent.md +12 -0
- package/src/repo/.claude/agents/factory-reviewer-ux.agent.md +12 -0
- package/src/repo/.claude/agents/factory-spec-writer.agent.md +12 -0
- package/src/repo/.claude/agents/feature-builder.agent.md +1 -1
- package/src/repo/.claude/agents/frontend-developer.agent.md +1 -1
- package/src/repo/.claude/agents/green.agent.md +1 -1
- package/src/repo/.claude/agents/implementer.agent.md +1 -1
- package/src/repo/.claude/agents/planner.agent.md +2 -2
- package/src/repo/.claude/agents/red.agent.md +1 -1
- package/src/repo/.claude/agents/refactor.agent.md +1 -1
- package/src/repo/.claude/agents/researcher.agent.md +2 -2
- package/src/repo/.claude/agents/reviewer.agent.md +2 -2
- package/src/repo/.claude/agents/tdd.agent.md +1 -1
- package/src/repo/.claude/agents-snippets/factory-approver.md +72 -0
- package/src/repo/.claude/agents-snippets/factory-builder.md +100 -0
- package/src/repo/.claude/agents-snippets/factory-reviewer-code.md +57 -0
- package/src/repo/.claude/agents-snippets/factory-reviewer-security.md +48 -0
- package/src/repo/.claude/agents-snippets/factory-reviewer-ui.md +64 -0
- package/src/repo/.claude/agents-snippets/factory-reviewer-ux.md +64 -0
- package/src/repo/.claude/agents-snippets/factory-spec-writer.md +117 -0
- package/src/repo/.claude/agents-snippets/feature-builder.md +1 -1
- package/src/repo/.claude/commands/factory.md +24 -0
- package/src/repo/.claude/commands/ponytail-audit.md +4 -6
- package/src/repo/.claude/commands/ponytail-debt.md +3 -5
- package/src/repo/.claude/commands/ponytail-gain.md +2 -4
- package/src/repo/.claude/commands/ponytail-help.md +2 -4
- package/src/repo/.claude/commands/ponytail-review.md +3 -5
- package/src/repo/.claude/commands/ponytail.md +3 -5
- package/src/repo/.claude/prompt-snippets/assign-tasks.md +6 -2
- package/src/repo/.claude/prompt-snippets/bootstrap-patch.md +32 -17
- package/src/repo/.claude/prompt-snippets/bootstrap-upgrade.md +87 -77
- package/src/repo/.claude/prompt-snippets/bootstrap.md +71 -74
- package/src/repo/.claude/prompt-snippets/factory.md +20 -0
- package/src/repo/.claude/prompt-snippets/implement-feature.md +2 -2
- package/src/repo/.claude/prompt-snippets/tasks.md +49 -112
- package/src/repo/.cursor/agents/factory-approver.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-builder.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-reviewer-code.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-reviewer-security.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-reviewer-ui.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-reviewer-ux.agent.md +11 -0
- package/src/repo/.cursor/agents/factory-spec-writer.agent.md +11 -0
- package/src/repo/.cursor/commands/factory.md +24 -0
- package/src/repo/.github/agents/factory-approver.agent.md +11 -0
- package/src/repo/.github/agents/factory-builder.agent.md +11 -0
- package/src/repo/.github/agents/factory-reviewer-code.agent.md +11 -0
- package/src/repo/.github/agents/factory-reviewer-security.agent.md +11 -0
- package/src/repo/.github/agents/factory-reviewer-ui.agent.md +11 -0
- package/src/repo/.github/agents/factory-reviewer-ux.agent.md +11 -0
- package/src/repo/.github/agents/factory-spec-writer.agent.md +11 -0
- package/src/repo/.github/prompts/factory.prompt.md +25 -0
- package/src/repo/.opencode/agents/admin-portal.md +10 -4
- package/src/repo/.opencode/agents/api-specialist.md +10 -4
- package/src/repo/.opencode/agents/backend-architect.md +10 -4
- package/src/repo/.opencode/agents/documenter.md +10 -4
- package/src/repo/.opencode/agents/factory-approver.md +20 -0
- package/src/repo/.opencode/agents/factory-builder.md +20 -0
- package/src/repo/.opencode/agents/factory-reviewer-code.md +20 -0
- package/src/repo/.opencode/agents/factory-reviewer-security.md +20 -0
- package/src/repo/.opencode/agents/factory-reviewer-ui.md +20 -0
- package/src/repo/.opencode/agents/factory-reviewer-ux.md +20 -0
- package/src/repo/.opencode/agents/factory-spec-writer.md +20 -0
- package/src/repo/.opencode/agents/feature-builder.md +13 -5
- package/src/repo/.opencode/agents/frontend-developer.md +10 -4
- package/src/repo/.opencode/agents/green.md +10 -4
- package/src/repo/.opencode/agents/implementer.md +10 -4
- package/src/repo/.opencode/agents/planner.md +10 -4
- package/src/repo/.opencode/agents/red.md +10 -4
- package/src/repo/.opencode/agents/refactor.md +10 -4
- package/src/repo/.opencode/agents/researcher.md +10 -4
- package/src/repo/.opencode/agents/reviewer.md +10 -4
- package/src/repo/.opencode/agents/tdd.md +13 -5
- package/src/repo/.opencode/commands/factory.md +29 -0
- package/src/repo/.opencode/opencode.jsonc +8 -10
- package/src/repo/AGENTS.md +27 -1
- package/src/repo/CLAUDE.md +1 -1
- package/src/repo/README.md +20 -0
- package/src/repo/factory/README.md +194 -0
- package/src/repo/factory/_gitignore +5 -0
- package/src/monorepo/.opencode/plugins/ponytail.mjs +0 -93
- package/src/repo/.opencode/plugins/ponytail.mjs +0 -93
package/CHANGELOG.md
CHANGED
|
@@ -7,8 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [5.0.0]
|
|
11
|
+
|
|
12
|
+
### Breaking
|
|
13
|
+
|
|
14
|
+
- `/tasks` now writes a slim `tasks.md`: one checklist line per task (checkbox, ID, short description, optional `[P]`, optional ` — <ticket key>`). Details stay in `spec.md` and `plan.md`. `/assign-tasks` and `/implement-feature` read the slim lines and write ticket keys back after the em dash. Existing `tasks.md` files are not rewritten; re-run `/tasks` on a feature to convert one.
|
|
15
|
+
- `upgrade` no longer overwrites your files. It used to run `install --force`. It now adds missing files and keeps existing ones (`patch` semantics), then re-emits the bootstrap handoff. Overwriting needs an explicit `upgrade --force`, which prints a warning first. Scripts that relied on `upgrade` to refresh templates must add `--force`.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Factory pipeline (opt-in): `/factory <request>` takes a feature through intake, spec gate, plan gate, build, parallel lens reviews, approval, and local merge, with subcommands `start`, `approve`, `rework`, `status`, and `watch`. Nothing runs until `/factory` is invoked. Job state lives in `factory/jobs/`, which is git-ignored. Entry points ship for Claude Code, GitHub Copilot, Cursor, and OpenCode; Codex uses the orchestrator skill `.agents/skills/factory/SKILL.md`.
|
|
20
|
+
- Factory gates and intake: intake reads `AGENTS.md`, related features in `docs/features/`, and the code it touches, asks at most five glaring questions, and saves the answers to `intake.md`. Every job stops at `awaiting-spec` and `awaiting-plan` in every approval mode, and nothing is ticketed or built before the operator confirms the plan. Change requests are saved as `spec-<k>.md` or `plan-<k>.md`.
|
|
21
|
+
- Factory feature folders and tracking: each job belongs to `docs/features/<KEY>-<slug>/` (or `docs/features/<slug>/` before a ticket exists). `job.json` records `feature_dir`, `issue_key`, `size`, `tracking`, and `worktree`. Large work with a documented tracker creates tickets through `/assign-tasks`, writes their keys onto `tasks.md`, and moves them through In Progress, In Review, and Done. Done only follows `/factory approve`.
|
|
22
|
+
- Factory builds run in a git worktree on `factory/<id>`. `--in-place` builds in the main checkout instead, and only from a clean default branch with no other in-place job open. The builder writes `qa.md` with suggested checks, printed before approval; it never gates anything.
|
|
23
|
+
- Factory agents: `factory-spec-writer`, `factory-builder`, `factory-reviewer-code`, `factory-reviewer-security`, `factory-reviewer-ux`, `factory-reviewer-ui`, and `factory-approver`, with shared snippets in `.claude/agents-snippets/`. Their OpenCode wrappers use native V2 `permissions`.
|
|
24
|
+
- `factory/` template folder (README, `_gitignore`) installed by default. CLI `factory status` (one-shot table) and `factory watch` (live view) are read-only over `factory/jobs/*/job.json`; `abandoned` jobs are shown as closed.
|
|
25
|
+
- Factory `/factory archive [--all] [--dry-run]` moves closed jobs (`merged` or `abandoned`) from `factory/jobs/` to `factory/archive/`. By default only jobs last updated more than 7 days ago move. `--all` moves every closed job, and open jobs never move. CLI `factory archive` makes the same moves. `/factory archive` also asks before deleting an archived abandoned job's branch and worktree, and never pushes. Archived jobs are not resumable (`/factory start` says they are closed), and their ids count toward job numbering until a prune removes them.
|
|
26
|
+
- Factory `/factory prune [--all] [--abandoned] [--dry-run]` permanently deletes closed jobs from `factory/jobs/` and `factory/archive/`. By default only `merged` jobs are deleted, and only those last updated more than 7 days ago. `--all` drops the age limit for merged jobs. `--abandoned` also deletes `abandoned` jobs under the same age rule. Without it, abandoned jobs are kept and counted, and the flow offers to rerun with `--abandoned`. It lists the candidates, asks once in chat, and deletes only after a yes. When abandoned jobs are pruned, it then asks, per abandoned branch, whether to delete the branch and its worktree, as archive does. Open jobs and `docs/features/` are never touched. `/factory archive` keeps its selection: merged and abandoned. CLI `factory prune` lists by default and deletes with `--yes`; `--abandoned` is accepted only by `factory prune`.
|
|
27
|
+
- Link checks in `test/links.test.js`: every relative markdown link and `@path` import in `src/repo` and `src/monorepo` must resolve, and so must every scoped install (each `--env` × layout).
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Factory dashboard: `factory status` and `factory watch` hide closed jobs by default and print `N closed jobs hidden (--all to show)`. `--all` shows closed jobs and archived ones.
|
|
32
|
+
- Scoped installs (`--env`) also copy `.agents/skills/`, `.claude/agents-snippets/`, `.claude/prompt-snippets/`, `.claude/rules-snippets/`, and `factory/`, the shared references every harness's wrappers use.
|
|
33
|
+
- Templates named `_gitignore` install as `.gitignore`, because npm drops `.gitignore` files from packages.
|
|
34
|
+
- Releases publish through npm trusted publishing (OIDC, with provenance) from `.github/workflows/publish.yml`, which now also does the auto patch bump and tag (`auto-patch-tag.yml` removed). The `NPM_TOKEN` secret is no longer used.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Scoped Cursor, Copilot, and OpenCode installs no longer leave dangling links: `.claude/rules-snippets/` is now shared by every scope, since Cursor rules link there.
|
|
39
|
+
- Scoped installs share only `.agents/skills/`, so Claude/Codex ambient rules in `.agents/rules/` no longer appear in Cursor, Copilot, or OpenCode installs.
|
|
40
|
+
- `doctor` placeholder scan matches names with digits (for example `{{DB2_HOST}}`), skips `templates/` blank forms, and ignores runtime-only placeholders (`ISSUE_ID`, `ISSUE_KEY`, `FEATURE_NAME`, `NAME`), so a bootstrapped project can report clean.
|
|
41
|
+
- `.cursor/rules/orient-to-recent-work.mdc` skill link now resolves (`../` → `../../`).
|
|
42
|
+
|
|
43
|
+
## [4.0.0]
|
|
44
|
+
|
|
45
|
+
### Migration
|
|
46
|
+
|
|
47
|
+
- Toolkit v4 / package 4.0.0 requires native OpenCode V2 for OpenCode use; oh-my-opencode-slim >=3.0.0 requires OpenCode >=2.0.7. Native host config uses plural maps, ordered permissions, skill directories, and `mcp.servers`. Back up V1 (converted files are incompatible with it), preserve user/global settings and Slim's separate strict schema, leave the external starter unchanged, and activate on the next run/restart. Config `instructions` are ignored, ambient `AGENTS.md` works, `@refs` require explicit reads, and `request.body.temperature` is preserved but not currently sent by the runner. Preserve `lsp: true`; use project checks, not unavailable V2 LSP tools. Plugin/runtime integration is untested; publishing has not been executed.
|
|
48
|
+
- Removed all three local Ponytail plugin copies (root, repo template, monorepo template). Both templates register the author's native V2 `@dietrichgebert/ponytail@4.12.0` package locally; `opentmux` remains commented as V1-only. No API port or bridge was added. The toolkit root alone omits `plugins` to inherit existing user/global registrations; no global config was changed. Existing targets remove only known obsolete toolkit Ponytail `.js`/`.mjs`/`.ts` copies after backup and approval, preserving unrelated plugins and deduplicating upstream registration locally.
|
|
49
|
+
|
|
10
50
|
### Fixed
|
|
11
51
|
|
|
52
|
+
- All six repo/monorepo bootstrap flows now require a fail-closed `opencode --version` preflight before changes for confirmed OpenCode use: accept an optional leading `v`, reject V1 before OpenCode customization/migration or toolkit 4.0.0 marking, and stop on a missing CLI or unparseable version. Slim >=3.0.0 enforces OpenCode >=2.0.7; other-harness-only setup is unaffected. Focused instruction-order/version-metadata regression checks cover the guard.
|
|
12
53
|
- Bootstrap audit/creation examples are explicitly conditional on confirmed Copilot use; completion reports describe performed harness-specific checks without assuming OpenCode configuration, Codex trust/loading, or Copilot/Cursor readiness. Codex-scoped install documentation now includes linked standards and their wrapper sources without implying other harness activation.
|
|
13
54
|
|
|
14
55
|
### Added
|
|
@@ -32,7 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
32
73
|
- `bkt-cli` skill — Bitbucket CLI (`bkt`) command reference for repo and monorepo templates
|
|
33
74
|
- `glab-cli` skill — GitLab CLI (`glab`) command reference for repo and monorepo templates
|
|
34
75
|
- Ponytail skill bundle — 6 YAGNI/stdlib/native/minimum-discipline skills (`ponytail`, `ponytail-audit`, `ponytail-debt`, `ponytail-gain`, `ponytail-help`, `ponytail-review`)
|
|
35
|
-
- Ponytail OpenCode plugin (
|
|
76
|
+
- Author's upstream Ponytail OpenCode plugin registration (`@dietrichgebert/ponytail@4.12.0`) in both template configs; no bundled local plugin source
|
|
36
77
|
- 7 ponytail hooks in `hooks/` (`ponytail-activate`, `ponytail-config`, `ponytail-instructions`, `ponytail-mode-tracker`, `ponytail-runtime`, `ponytail-statusline.sh`, `ponytail-statusline.ps1`), plus 2 hook configuration files for Claude/Codex and Copilot (`claude-codex-hooks.json`, `copilot-hooks.json`)
|
|
37
78
|
- Ponytail rule in `.agents/rules/` and `.cursor/rules/` for ambient agent context
|
|
38
79
|
- 6 ponytail commands (`ponytail`, `ponytail-audit`, `ponytail-debt`, `ponytail-gain`, `ponytail-help`, `ponytail-review`) with thin-wrapper sources in `.claude/prompt-snippets/`
|
|
@@ -74,7 +115,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
74
115
|
- Added missing templates referenced in templates/README.md
|
|
75
116
|
- `scripts/pre-commit-check.sh` — early-exit when no files are staged so the CHANGELOG check no longer fires on empty commits (PR #20 review)
|
|
76
117
|
- `scripts/check-parity.sh` — removed duplicate `check_body_match` call for the cursor ↔ github prompt body (PR #20 review)
|
|
77
|
-
- `.opencode/plugins/ponytail.mjs` — wrapped `writeMode` in a try/catch so an unwritable state directory no longer crashes the plugin (PR #20 review)
|
|
78
118
|
- `ponytail-help` SKILL.md and prompt snippet — added missing `ponytail-audit`, `ponytail-debt`, and `/ponytail-gain` entries; corrected OpenCode slash-command count to six; rewrote the Claude-Code-specific Update section to describe the template update flow (PR #20 review)
|
|
79
119
|
- `ponytail-gain` SKILL.md and prompt snippet (repo, monorepo, root) — replaced the phantom `benchmarks/` source reference with the upstream `DietrichGebert/ponytail` repo link (PR #20 review)
|
|
80
120
|
- `README.md` — corrected "8 activation hooks" to "7 activation hooks" to match CHANGELOG and the actual hook count (PR #20 review)
|
|
@@ -113,5 +153,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
113
153
|
- Documentation structure templates (`docs/features/`, `docs/fixes/`)
|
|
114
154
|
- Monthly fix log template
|
|
115
155
|
|
|
116
|
-
[Unreleased]: https://github.com/ninjasitm/ai-assisted-dev-toolkit/compare/
|
|
156
|
+
[Unreleased]: https://github.com/ninjasitm/ai-assisted-dev-toolkit/compare/v4.0.0...HEAD
|
|
157
|
+
[4.0.0]: https://github.com/ninjasitm/ai-assisted-dev-toolkit/compare/v3.0.23...v4.0.0
|
|
117
158
|
[0.1.0]: https://github.com/ninjasitm/ai-assisted-dev-toolkit/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ This repository serves as a **template source** for AI development instructions
|
|
|
36
36
|
│ │ │ ├── rules/ # Agent behavior rules (ponytail, etc.)
|
|
37
37
|
│ │ │ └── skills/ # Bundled skills (TDD, debugging, etc.)
|
|
38
38
|
│ │ ├── docs/ # Documentation structure templates
|
|
39
|
+
│ │ ├── factory/ # Opt-in factory pipeline (README, .gitignore)
|
|
39
40
|
│ │ ├── templates/ # Reusable document templates
|
|
40
41
|
│ │ ├── AGENTS.md # AI agent context template
|
|
41
42
|
│ │ └── README.md # Project README template
|
|
@@ -59,13 +60,14 @@ This repository serves as a **template source** for AI development instructions
|
|
|
59
60
|
│ ├── apps/ # App-specific templates
|
|
60
61
|
│ ├── packages/ # Package-specific templates
|
|
61
62
|
│ ├── docs/ # Documentation structure templates
|
|
63
|
+
│ ├── factory/ # Opt-in factory pipeline (README, .gitignore)
|
|
62
64
|
│ ├── templates/ # Reusable document templates
|
|
63
65
|
│ └── AGENTS.md # Monorepo agent context
|
|
64
66
|
│
|
|
65
67
|
├── .cursor/ # This toolkit's own Cursor config
|
|
66
68
|
├── .github/ # This toolkit's own GitHub config
|
|
67
69
|
├── .opencode/ # This toolkit's own OpenCode config
|
|
68
|
-
│ └── plugins/ # OpenCode plugins (
|
|
70
|
+
│ └── plugins/ # Other local OpenCode plugins (Ponytail uses upstream)
|
|
69
71
|
├── hooks/ # Claude Code / Copilot activation hooks (ponytail, etc.)
|
|
70
72
|
└── AGENTS.md # This toolkit's agent context
|
|
71
73
|
```
|
|
@@ -172,18 +174,52 @@ npx nitm-ai-dev-toolkit patch
|
|
|
172
174
|
# Inspect the install: missing files and unresolved placeholders
|
|
173
175
|
npx nitm-ai-dev-toolkit doctor
|
|
174
176
|
|
|
175
|
-
# Upgrade to the latest published version
|
|
177
|
+
# Upgrade to the latest published version: adds missing files and keeps your existing ones
|
|
176
178
|
npx nitm-ai-dev-toolkit upgrade
|
|
177
179
|
|
|
180
|
+
# Also overwrite existing files with the latest templates (back up customisations first)
|
|
181
|
+
npx nitm-ai-dev-toolkit upgrade --force
|
|
182
|
+
|
|
178
183
|
# Scaffold the oh-my-opencode-slim starter (delegates to `npx nitm-opencode-starter install`)
|
|
179
184
|
npx nitm-ai-dev-toolkit omo-slim-starter install
|
|
180
185
|
```
|
|
181
186
|
|
|
182
187
|
After `install`, ask your AI agent to read and follow `.nitm/BOOTSTRAP.md`. Harnesses that supply a toolkit `/bootstrap` wrapper can also use it; **Codex has no native toolkit `/bootstrap` command**. Use `doctor` to verify the result.
|
|
183
188
|
|
|
189
|
+
### Native OpenCode V2 (toolkit 4.0.0)
|
|
190
|
+
|
|
191
|
+
Toolkit v4 requires **OpenCode V2 (major >=2)** for OpenCode use; **oh-my-opencode-slim >=3.0.0** requires **OpenCode >=2.0.7**. All repo/monorepo bootstrap, patch, and upgrade flows run `opencode --version` before changes, accepting an optional leading `v`. V1 must stop before OpenCode customization/migration or marking toolkit 4.0.0: upgrade OpenCode or remain on toolkit 3.x. A missing CLI or unparseable version stops OpenCode steps and version marking until the user confirms/installs a supported version. Confirm harness use from runtime evidence or ask; scaffold directories are not proof. Other-harness-only setup is unaffected.
|
|
192
|
+
|
|
193
|
+
Publishing 4.0.0 has not been executed. The external `nitm-opencode-starter` is a separate package, not automatically upgraded.
|
|
194
|
+
|
|
195
|
+
With user approval, merge this reproducible registration without replacing user/global plugins:
|
|
196
|
+
|
|
197
|
+
```jsonc
|
|
198
|
+
{ "plugins": ["oh-my-opencode-slim@3.0.0"] }
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The toolkit root deliberately omits `plugins` to inherit user/global registrations; its existing upstream Ponytail registration is unchanged. Both target templates register the author's native V2 package `@dietrichgebert/ponytail@4.12.0` in their local `plugins` arrays, alongside `opencode-mem` and `@tarquinen/opencode-dcp@latest`; `opentmux` remains commented as V1-only. The local `ponytail.mjs` files are removed from the toolkit root and both templates; no local API port or bridge replaces them.
|
|
202
|
+
|
|
203
|
+
For existing targets, back up and obtain approval before removing only known obsolete toolkit `.opencode/plugins/ponytail.js`, `.mjs`, or `.ts` copies. Preserve unrelated local plugins; merge/deduplicate upstream package registration locally where appropriate, without editing or overwriting global plugins. Native local plugins are discovered automatically, so do not register them twice. Slim's separate strict schema keeps its own `prompt`, `permission`, and `variant`: do not host-migrate plugin-owned fields. The root's no-`plugins` policy is specific to this toolkit repository, not target templates.
|
|
204
|
+
|
|
205
|
+
| Setting | Native V2 form |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| Agents | `agents`, JSON `system` (Markdown body for file agents), `request.body.temperature`, model `provider/model#variant` |
|
|
208
|
+
| Permissions | Ordered `permissions` with `action`, `resource`, `effect`; `shell`/`subagent` actions; last match wins |
|
|
209
|
+
| Commands | `commands`; delegated commands use `subagent` |
|
|
210
|
+
| Plugins | `plugins`; options use `{ "package": "…", "options": {} }` |
|
|
211
|
+
| Skills | Directory-path array, e.g. `[".agents/skills"]`, not Markdown globs |
|
|
212
|
+
| MCP | `mcp.servers`; `disabled` inverts legacy `enabled`; `timeout.catalog`/`timeout.execution` |
|
|
213
|
+
|
|
214
|
+
Follow official V2 [migration](https://opencode.ai/v2/docs/migrate-v1), [config](https://opencode.ai/v2/docs/config), [agents](https://opencode.ai/v2/docs/agents), and [plugins](https://opencode.ai/v2/docs/build/plugins) docs. The published `https://opencode.ai/config.json` schema may describe V1; it is not native V2 validation authority.
|
|
215
|
+
|
|
216
|
+
**Runtime limits:** config `instructions` entries are accepted but not loaded; ambient `AGENTS.md` works. `@refs` are ordinary text, not automatic attachments: agents must read referenced snippets explicitly. `request.body.temperature` remains in config, but the current runner does not send it. Plugin/runtime integration has not been tested. Preserve `lsp: true`, but V2 currently exposes no LSP tools or diagnostics: use project lint/typecheck/compiler commands.
|
|
217
|
+
|
|
218
|
+
`--env opencode` includes minimal shared references for wrappers and AGENTS-linked standards without activating other harnesses. Merge, don't clobber: back up V1, preserve models/providers and user/global plugins, and ask before changes. Native-converted files are **incompatible with V1**. Activate on the next run/restart, then check behavior with the installed V2 runtime. `doctor` checks scaffold files/placeholders, not runtime behavior; do not substitute a V1 API/schema fetch or claim checks that were not run.
|
|
219
|
+
|
|
184
220
|
### Native Codex
|
|
185
221
|
|
|
186
|
-
- `--env codex` includes `.codex/`, `.agents/`, and shared context, plus `.github/instructions/`
|
|
222
|
+
- `--env codex` includes `.codex/`, `.agents/`, and shared context, plus `.github/instructions/` solely to supply the standards linked from `AGENTS.md`. The shared `.claude/rules-snippets/` standards are installed in every scope, so those standards' wrapper source content is present too. It does not install other harness command, agent, or config directories. These reference files neither establish Copilot/Claude use nor load automatically as Codex rules; other harness scopes are unchanged.
|
|
187
223
|
- Codex reads `AGENTS.md` and discovers `.agents/skills/*/SKILL.md` natively. Monorepos can use more-specific nested `AGENTS.md` files for app/package guidance. Linked standards are references to read as needed, not automatically loaded Claude/Copilot rules.
|
|
188
224
|
- The optional `.codex/config.toml` is deliberately comment-only: it preserves the user's inherited defaults. Codex loads project config only after the user explicitly trusts the project; the toolkit does not grant trust or set model/provider, approval, sandbox, security, or feature overrides.
|
|
189
225
|
- For manual copies without `.nitm/`, provide `.claude/prompt-snippets/bootstrap.md` to Codex directly. For incremental AI-guided merges, provide `.claude/prompt-snippets/bootstrap-patch.md` as a task document; the CLI `patch` command only adds missing files.
|
|
@@ -207,6 +243,7 @@ Templates use `{{PLACEHOLDER}}` syntax for values you need to customize. The boo
|
|
|
207
243
|
| `{{PACKAGE_MANAGER}}` | Package manager | `npm`, `composer`, `dotnet`, `pip`, `bundler`, `go`, `cargo`, `maven` |
|
|
208
244
|
| `{{FILE_EXTENSION}}` | File extension | `ts`, `php`, `cs`, `py`, `rb`, `go`, `rs`, `java` |
|
|
209
245
|
| `{{DEV_PORT}}` | Development server port | `3000`, `8000`, `5000` |
|
|
246
|
+
| `{{DEV_PORT_FLAG}}` | Flag or env var that sets the dev port | `--port 3000`, `PORT=3000` |
|
|
210
247
|
| `{{DEPLOY_PLATFORM}}` | Deployment target | `Vercel`, `AWS`, `Azure`, `Heroku` |
|
|
211
248
|
| `{{DATABASE}}` | Database/ORM | `Prisma`, `Eloquent`, `EF Core`, `SQLAlchemy`, `ActiveRecord` |
|
|
212
249
|
| `{{TEST_FRAMEWORK}}` | Testing framework | `Vitest`, `PHPUnit`, `xUnit`, `pytest`, `RSpec`, `JUnit` |
|
|
@@ -229,6 +266,7 @@ Templates use `{{PLACEHOLDER}}` syntax for values you need to customize. The boo
|
|
|
229
266
|
| Placeholder | Description | Example |
|
|
230
267
|
| --------------------- | -------------------- | --------------------------------------------------- |
|
|
231
268
|
| `{{INSTALL_COMMAND}}` | Install dependencies | `npm install`, `composer install`, `dotnet restore` |
|
|
269
|
+
| `{{SETUP_COMMAND}}` | Install command | `npm install`, `composer install`, `dotnet restore` |
|
|
232
270
|
| `{{DEV_COMMAND}}` | Run dev server | `npm run dev`, `php artisan serve`, `dotnet watch` |
|
|
233
271
|
| `{{BUILD_COMMAND}}` | Build for production | `npm run build`, `dotnet publish` |
|
|
234
272
|
| `{{TEST_COMMAND}}` | Run tests | `npm test`, `./vendor/bin/phpunit`, `dotnet test` |
|
|
@@ -260,6 +298,17 @@ Templates use `{{PLACEHOLDER}}` syntax for values you need to customize. The boo
|
|
|
260
298
|
| `{{APP_3}}` | Third app name | `web`, `marketing`, `landing` |
|
|
261
299
|
| `{{PROJECT_STRUCTURE}}` | Full project structure | (Generated tree diagram) |
|
|
262
300
|
|
|
301
|
+
### Factory Placeholders
|
|
302
|
+
|
|
303
|
+
Used by the opt-in factory (`.agents/skills/factory/SKILL.md` and `.claude/agents-snippets/factory-*.md`).
|
|
304
|
+
|
|
305
|
+
| Placeholder | Description | Example |
|
|
306
|
+
| --------------------------- | ------------------------------------------------------------------------------------------- | ------------------------ |
|
|
307
|
+
| `{{DEFAULT_BRANCH}}` | Branch factory jobs start from and merge into | `main`, `master` |
|
|
308
|
+
| `{{FACTORY_PORT_BASE}}` | Base dev-server port. Job `n` uses `base + 10n` for the builder, `+1` for ux, and `+2` for ui | `5100` |
|
|
309
|
+
| `{{APPROVAL_MODE}}` | `human` stops at `awaiting-human`; `auto` merges on approval | `human`, `auto` |
|
|
310
|
+
| `{{FACTORY_REVIEW_LENSES}}` | Review lenses to run. `ux` and `ui` need browser tooling | `code, security` |
|
|
311
|
+
|
|
263
312
|
## Supported Ecosystems
|
|
264
313
|
|
|
265
314
|
The bootstrap command supports the following language ecosystems:
|
|
@@ -585,6 +634,43 @@ The bundled skills complement custom agents:
|
|
|
585
634
|
- **`writing-plans`** — Creating the plans that Feature Builder and TDD agents execute
|
|
586
635
|
- **`test-driven-development`** — The TDD methodology that Red/Green/Refactor agents implement
|
|
587
636
|
|
|
637
|
+
## Factory (opt-in, v5)
|
|
638
|
+
|
|
639
|
+
The factory is an opt-in pipeline for feature-sized work. One orchestrator takes a feature through spec → plan gate → build → review → approve → merge. Each job belongs to a feature folder, `docs/features/<KEY>-<slug>/` (or `docs/features/<slug>/` before a ticket exists), which holds `spec.md` and, for large work, a slim `tasks.md`. Job state lives under `factory/jobs/<NNN-slug>/`, and each job builds in its own git worktree on branch `factory/<id>` (or in place on the job's branch, when you ask for `--in-place`).
|
|
640
|
+
|
|
641
|
+
It runs alongside Feature Builder and TDD and does not replace them. Nothing runs until you invoke `/factory`. Quick fixes stay direct.
|
|
642
|
+
|
|
643
|
+
- **Agents:** `factory-spec-writer`, `factory-builder`, `factory-reviewer-code`, `factory-reviewer-security`, `factory-reviewer-ux`, `factory-reviewer-ui`, and `factory-approver`. Wrappers ship for Claude Code, GitHub Copilot, Cursor, and OpenCode. Codex uses the orchestrator skill only.
|
|
644
|
+
- **Setup and reference:** [`src/repo/factory/README.md`](src/repo/factory/README.md) (the monorepo copy is in `src/monorepo/factory/`). The installer copies `factory/` into your project.
|
|
645
|
+
|
|
646
|
+
| Command | What it does |
|
|
647
|
+
| --- | --- |
|
|
648
|
+
| `/factory <feature request>` | Intake: reads the project and the features it touches, asks only the glaring questions, then asks you to continue or change the answers. Nothing is created before you continue |
|
|
649
|
+
| `/factory start <KEY \| slug \| job-id>` | Pick up an existing feature folder by ticket key or slug, or resume its open job (for example one waiting at a gate). Add `--in-place` only for a new job |
|
|
650
|
+
| `/factory approve <job-id>` | Merge a job waiting for you (`awaiting-human` or `needs-human`); on a `merged` job, move its tickets to Done |
|
|
651
|
+
| `/factory rework <job-id> <note>` | Restart the builder with your note and a fresh retry budget |
|
|
652
|
+
| `/factory status [--all]` | Summarize open jobs (read-only). Closed jobs are hidden unless `--all` |
|
|
653
|
+
| `/factory watch [--all]` | Show the status table here, then print the command to run the live view in your terminal (read-only). Closed jobs are hidden unless `--all` |
|
|
654
|
+
| `/factory archive [--all] [--dry-run]` | Move closed jobs (`merged` or `abandoned`) from `factory/jobs/` to `factory/archive/`. By default only jobs not updated for 7 days move. `--dry-run` moves nothing. Open jobs never move |
|
|
655
|
+
| `/factory prune [--all] [--abandoned] [--dry-run]` | Permanently delete closed jobs from `factory/jobs/` and `factory/archive/`, after one confirmation. By default only `merged` jobs (same 7-day age rule as archive; `--all` drops the age limit). `--abandoned` also deletes `abandoned` jobs. Open jobs and `docs/features/` are never touched |
|
|
656
|
+
|
|
657
|
+
**Two gates are mandatory.** Every job stops at `awaiting-spec` after the spec, and at `awaiting-plan` after the plan. At the spec gate you confirm the spec or request changes. At the plan gate you review the tasks, the size, the tracking proposal, and the build mode, then confirm or request changes. Leave either gate for later with `/factory start <job-id>`. Nothing is ticketed or built before you confirm the plan.
|
|
658
|
+
|
|
659
|
+
**The builder also writes `qa.md`.** It lists how to run the feature, numbered manual checks tied to the acceptance criteria, and what the automated tests do not cover. The orchestrator shows it before approval as suggested checks. It is not a gate.
|
|
660
|
+
|
|
661
|
+
**The approval gate is on by default.** With `{{APPROVAL_MODE}}` set to `human`, an approved job stops at `awaiting-human` until you run `/factory approve <job-id>`. Set `{{APPROVAL_MODE}}` to `auto` to merge on approval instead. The approver still escalates changes to auth, payments, migrations, and similar high-risk areas. Merges are local, and the factory never pushes.
|
|
662
|
+
|
|
663
|
+
Check jobs from a terminal:
|
|
664
|
+
|
|
665
|
+
```bash
|
|
666
|
+
npx nitm-ai-dev-toolkit factory status [--all] # one-shot table of open jobs (--all: closed too)
|
|
667
|
+
npx nitm-ai-dev-toolkit factory watch [--all] # live view: ↑/↓ to select, Enter to open, q to quit
|
|
668
|
+
npx nitm-ai-dev-toolkit factory archive [--all] [--dry-run] # move closed jobs to factory/archive/
|
|
669
|
+
npx nitm-ai-dev-toolkit factory prune [--all] [--abandoned] [--dry-run] # list merged jobs to delete; add --yes to delete them
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
`status` and `watch` read `factory/jobs/*/job.json`, write nothing, and hide closed jobs unless `--all` is passed. `archive` moves closed jobs and touches no git state. `prune` permanently deletes merged jobs from both folders, after you confirm. Pass `--abandoned` to delete abandoned jobs too. Neither touches open jobs or `docs/features/`. The factory's placeholders are listed under [Factory Placeholders](#factory-placeholders).
|
|
673
|
+
|
|
588
674
|
## AI Agent Skills
|
|
589
675
|
|
|
590
676
|
Enhance your AI agents with specialized capabilities using the **Agent Skills** open format. Skills are folders of instructions, scripts, and resources that agents can discover and use to perform tasks more accurately and efficiently.
|
|
@@ -662,7 +748,7 @@ Skills are installed to `{.cursor|.agents|.github}/skills/` and automatically av
|
|
|
662
748
|
|
|
663
749
|
### Bundled Universal Skills
|
|
664
750
|
|
|
665
|
-
This toolkit includes **
|
|
751
|
+
This toolkit includes **33 pre-installed universal skills** in the `.agents/skills/` folder. These skills are copied automatically when you set up your project and require **no additional installation**.
|
|
666
752
|
|
|
667
753
|
| Skill | Description |
|
|
668
754
|
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
@@ -671,6 +757,7 @@ This toolkit includes **32 pre-installed universal skills** in the `.agents/skil
|
|
|
671
757
|
| **verification-before-completion** | Quality checks before claiming work is done. Evidence before assertions, always. |
|
|
672
758
|
| **writing-plans** | Creating clear implementation plans before coding. |
|
|
673
759
|
| **executing-plans** | Following through on implementation plans systematically. |
|
|
760
|
+
| **factory** | Opt-in spec-to-merge feature pipeline with review lenses and an approval gate. |
|
|
674
761
|
| **requesting-code-review** | Best practices for requesting code reviews from teammates. |
|
|
675
762
|
| **receiving-code-review** | Responding constructively to review feedback. |
|
|
676
763
|
| **brainstorming** | Structured ideation and problem-solving sessions. |
|
|
@@ -701,7 +788,7 @@ This toolkit includes **32 pre-installed universal skills** in the `.agents/skil
|
|
|
701
788
|
|
|
702
789
|
**These skills are ready to use immediately after copying the templates.** No `npx -y skills add -a <agent> <owner/repo> --skill '*' --agent github-copilot cursor` commands needed.
|
|
703
790
|
|
|
704
|
-
The **ponytail** skill bundle is an integrated optional skill set from [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail) that adds YAGNI/stdlib/native/one-line/minimum discipline to your AI agents. It includes 6 skills, 6 commands,
|
|
791
|
+
The **ponytail** skill bundle is an integrated optional skill set from [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail) that adds YAGNI/stdlib/native/one-line/minimum discipline to your AI agents. It includes 6 skills, 6 commands, 7 activation hooks, and ambient agent rules. OpenCode uses the author's upstream `@dietrichgebert/ponytail@4.12.0` package, not a bundled local plugin. See [native setup](#native-opencode-v2-toolkit-400); scaffolding alone does not establish activation.
|
|
705
792
|
|
|
706
793
|
### Additional Recommended Skills
|
|
707
794
|
|
|
@@ -862,7 +949,7 @@ After copying templates and installing additional skills, your project will have
|
|
|
862
949
|
│ └── SKILL.md
|
|
863
950
|
├── verification-before-completion/
|
|
864
951
|
│ └── SKILL.md
|
|
865
|
-
└── ... (
|
|
952
|
+
└── ... (33 skills total)
|
|
866
953
|
|
|
867
954
|
.cursor/ # or .github/ for GitHub Copilot
|
|
868
955
|
├── rules/ # IDE behavior rules (from this toolkit)
|
package/bin/cli.js
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
const fs = require('fs');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const { execSync, spawnSync } = require('child_process');
|
|
12
|
+
const factory = require('./factory-watch.js');
|
|
13
|
+
const factoryArchive = require('./factory-archive.js');
|
|
14
|
+
const factoryPrune = require('./factory-prune.js');
|
|
12
15
|
|
|
13
16
|
const PKG_ROOT = path.join(__dirname, '..');
|
|
14
17
|
const SRC_DIR = path.join(PKG_ROOT, 'src');
|
|
@@ -16,10 +19,13 @@ const SRC_DIR = path.join(PKG_ROOT, 'src');
|
|
|
16
19
|
// Platform config dirs per harness. Claude and Codex share `.agents` (universal skills).
|
|
17
20
|
const ENV_DIRS = {
|
|
18
21
|
claude: ['.claude', '.agents'],
|
|
19
|
-
codex: ['.codex', '.agents', path.join('.github', 'instructions')
|
|
22
|
+
codex: ['.codex', '.agents', path.join('.github', 'instructions')],
|
|
20
23
|
copilot: ['.github', '.vscode'],
|
|
21
24
|
cursor: ['.cursor'],
|
|
22
|
-
|
|
25
|
+
// Shared reference sources, not other harnesses' active config/agent wrappers.
|
|
26
|
+
opencode: ['.opencode', path.join('.agents', 'skills'),
|
|
27
|
+
path.join('.claude', 'agents-snippets'), path.join('.claude', 'prompt-snippets'),
|
|
28
|
+
path.join('.github', 'instructions')],
|
|
23
29
|
};
|
|
24
30
|
const ENV_INFO = {
|
|
25
31
|
claude: { name: 'Claude Code', command: '/bootstrap (Claude Code command in .claude/commands/)' },
|
|
@@ -30,8 +36,17 @@ const ENV_INFO = {
|
|
|
30
36
|
};
|
|
31
37
|
// Files/dirs copied for every environment (shared across harnesses).
|
|
32
38
|
const SHARED_ROOT = ['AGENTS.md', 'README.md', 'CLAUDE.md', '.mcp.json'];
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
// `factory` is the job queue every harness reads and writes, so it is shared.
|
|
40
|
+
// Agent/skill bodies and prompt snippets are referenced by wrappers in every harness
|
|
41
|
+
// (e.g. `.claude/agents-snippets/*` from Cursor and Copilot agents), so they are shared too.
|
|
42
|
+
// `.claude/rules-snippets` is linked the same way from every harness's rules and instructions.
|
|
43
|
+
// Only `.agents/skills` is shared: `.agents/rules` is Claude/Codex ambient config.
|
|
44
|
+
const SHARED_DIRS = ['docs', 'templates', 'hooks', 'factory', path.join('.agents', 'skills'),
|
|
45
|
+
path.join('.claude', 'agents-snippets'), path.join('.claude', 'prompt-snippets'),
|
|
46
|
+
path.join('.claude', 'rules-snippets')];
|
|
47
|
+
// npm drops `.gitignore` files from packages, so templates ship them as `_gitignore`
|
|
48
|
+
// and install them under the real name.
|
|
49
|
+
const TEMPLATE_RENAMES = { '_gitignore': '.gitignore' };
|
|
35
50
|
const C = {
|
|
36
51
|
reset: '\x1b[0m',
|
|
37
52
|
cyan: '\x1b[36m',
|
|
@@ -82,6 +97,12 @@ function templateFiles(type) {
|
|
|
82
97
|
return files;
|
|
83
98
|
}
|
|
84
99
|
|
|
100
|
+
// Path a template file is installed to (see TEMPLATE_RENAMES).
|
|
101
|
+
function installName(rel) {
|
|
102
|
+
const renamed = TEMPLATE_RENAMES[path.basename(rel)];
|
|
103
|
+
return renamed ? path.join(path.dirname(rel), renamed) : rel;
|
|
104
|
+
}
|
|
105
|
+
|
|
85
106
|
// Restrict the file set to the chosen environment (shared + that env's dirs).
|
|
86
107
|
function scopeFiles(files, env) {
|
|
87
108
|
if (!env || !ENV_DIRS[env]) return files;
|
|
@@ -102,7 +123,8 @@ function copyMissing(type, cwd, force, env) {
|
|
|
102
123
|
let skipped = 0;
|
|
103
124
|
for (const rel of files) {
|
|
104
125
|
const from = path.join(src, rel);
|
|
105
|
-
const
|
|
126
|
+
const dest = installName(rel);
|
|
127
|
+
const to = path.join(cwd, dest);
|
|
106
128
|
if (fs.existsSync(to) && !force) {
|
|
107
129
|
skipped++;
|
|
108
130
|
continue;
|
|
@@ -127,7 +149,8 @@ function conflicts(type, cwd, env) {
|
|
|
127
149
|
const files = scopeFiles(templateFiles(type), env);
|
|
128
150
|
const out = [];
|
|
129
151
|
for (const rel of files) {
|
|
130
|
-
|
|
152
|
+
const dest = installName(rel);
|
|
153
|
+
if (fs.existsSync(path.join(cwd, dest))) out.push(dest);
|
|
131
154
|
}
|
|
132
155
|
return out;
|
|
133
156
|
}
|
|
@@ -216,14 +239,25 @@ function cmdPatch(cwd, flags) {
|
|
|
216
239
|
return { copied, skipped };
|
|
217
240
|
}
|
|
218
241
|
|
|
242
|
+
// Placeholders the agent fills per task or feature at runtime, so they are not bootstrap leftovers.
|
|
243
|
+
const RUNTIME_PLACEHOLDERS = new Set(['ISSUE_ID', 'ISSUE_KEY', 'FEATURE_NAME', 'NAME']);
|
|
244
|
+
// `templates/` ships blank forms whose placeholders are meant to stay until a feature is written.
|
|
245
|
+
const PLACEHOLDER_EXEMPT_DIR = 'templates';
|
|
246
|
+
|
|
247
|
+
function hasUnresolvedPlaceholder(content) {
|
|
248
|
+
const names = content.match(/\{\{[A-Z][A-Z0-9_]*\}\}/g) || [];
|
|
249
|
+
return names.some((name) => !RUNTIME_PLACEHOLDERS.has(name.slice(2, -2)));
|
|
250
|
+
}
|
|
251
|
+
|
|
219
252
|
function scanPlaceholders(cwd, relFiles) {
|
|
220
253
|
const found = [];
|
|
221
254
|
for (const rel of relFiles) {
|
|
255
|
+
if (path.normalize(rel).split(path.sep)[0] === PLACEHOLDER_EXEMPT_DIR) continue;
|
|
222
256
|
const p = path.join(cwd, rel);
|
|
223
257
|
if (!fs.existsSync(p)) continue;
|
|
224
258
|
try {
|
|
225
259
|
const content = fs.readFileSync(p, 'utf8');
|
|
226
|
-
if (
|
|
260
|
+
if (hasUnresolvedPlaceholder(content)) found.push(rel);
|
|
227
261
|
} catch (_) { /* ignore */ }
|
|
228
262
|
}
|
|
229
263
|
return found;
|
|
@@ -231,7 +265,7 @@ function scanPlaceholders(cwd, relFiles) {
|
|
|
231
265
|
|
|
232
266
|
function cmdDoctor(cwd, flags) {
|
|
233
267
|
const type = detectType(cwd, flags);
|
|
234
|
-
const files = scopeFiles(templateFiles(type), flags.env);
|
|
268
|
+
const files = scopeFiles(templateFiles(type), flags.env).map(installName);
|
|
235
269
|
const missingFiles = [];
|
|
236
270
|
let present = 0;
|
|
237
271
|
for (const rel of files) {
|
|
@@ -258,6 +292,16 @@ function cmdDoctor(cwd, flags) {
|
|
|
258
292
|
return result;
|
|
259
293
|
}
|
|
260
294
|
|
|
295
|
+
// Upgrade runs the latest package in patch mode: missing files are added and existing
|
|
296
|
+
// (possibly customised) files are kept. Only an explicit --force reaches `install --force`.
|
|
297
|
+
function upgradeArgs(flags) {
|
|
298
|
+
const force = Boolean(flags && flags.force);
|
|
299
|
+
const args = ['--yes', 'nitm-ai-dev-toolkit@latest', force ? 'install' : 'patch'];
|
|
300
|
+
if (force) args.push('--force');
|
|
301
|
+
if (flags && flags.env) args.push('--env', flags.env);
|
|
302
|
+
return args;
|
|
303
|
+
}
|
|
304
|
+
|
|
261
305
|
function cmdUpgrade(cwd, flags) {
|
|
262
306
|
let latest;
|
|
263
307
|
try {
|
|
@@ -272,17 +316,17 @@ function cmdUpgrade(cwd, flags) {
|
|
|
272
316
|
} catch (_) {
|
|
273
317
|
cur = 'unknown';
|
|
274
318
|
}
|
|
275
|
-
if (latest === cur) {
|
|
276
|
-
|
|
277
|
-
|
|
319
|
+
if (latest === cur) info(`Already on latest version (${cur}); refreshing missing files and the handoff.`);
|
|
320
|
+
else info(`New version available: ${latest} (current ${cur}).`);
|
|
321
|
+
if (flags && flags.force) {
|
|
322
|
+
warn('--force: existing files will be overwritten with the latest templates. Back up your customisations first.');
|
|
323
|
+
} else {
|
|
324
|
+
info('Adding missing files only; your existing files are kept. Pass --force to overwrite them.');
|
|
278
325
|
}
|
|
279
|
-
info(`New version available: ${latest} (current ${cur}).`);
|
|
280
326
|
info('Upgrading via latest package...');
|
|
281
|
-
const
|
|
282
|
-
if (flags && flags.env) args.push('--env', flags.env);
|
|
283
|
-
const r = spawnSync('npx', args, { cwd, stdio: 'inherit', timeout: 120000 });
|
|
327
|
+
const r = spawnSync('npx', upgradeArgs(flags), { cwd, stdio: 'inherit', timeout: 120000 });
|
|
284
328
|
if (r.error) { err('Upgrade failed: ' + r.error.message); return; }
|
|
285
|
-
if (r.status === 0) ok('Upgrade complete.');
|
|
329
|
+
if (r.status === 0) ok('Upgrade complete. Hand off to your AI agent with .nitm/BOOTSTRAP.md to finish setup.');
|
|
286
330
|
else err('Upgrade failed.');
|
|
287
331
|
}
|
|
288
332
|
|
|
@@ -303,6 +347,38 @@ function cmdOmoStarter(cwd, flags) {
|
|
|
303
347
|
}
|
|
304
348
|
}
|
|
305
349
|
|
|
350
|
+
const FACTORY_USAGE = 'Usage: nitm-ai-dev-toolkit factory <status|watch|archive|prune> [--dir <path>] [--all] [--abandoned] [--interval <ms>] [--dry-run] [--yes]';
|
|
351
|
+
const FACTORY_SUB_USAGE = {
|
|
352
|
+
archive: 'Usage: nitm-ai-dev-toolkit factory archive [--dir <path>] [--all] [--dry-run]',
|
|
353
|
+
prune: 'Usage: nitm-ai-dev-toolkit factory prune [--dir <path>] [--all] [--abandoned] [--dry-run] [--yes]',
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
function cmdFactory(cwd, flags) {
|
|
357
|
+
const sub = flags._[1];
|
|
358
|
+
// --abandoned changes what prune deletes; elsewhere it would be a silent no-op, so refuse it.
|
|
359
|
+
if (flags.abandoned && sub !== 'prune') {
|
|
360
|
+
err('--abandoned is only for factory prune');
|
|
361
|
+
process.exitCode = 1;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (sub === 'status') return factory.cmdFactoryStatus(cwd, flags);
|
|
365
|
+
if (sub === 'watch') return factory.cmdFactoryWatch(cwd, flags);
|
|
366
|
+
if (sub === 'archive' || sub === 'prune') {
|
|
367
|
+
const extra = flags._.slice(2);
|
|
368
|
+
if (extra.length) {
|
|
369
|
+
err(`Unknown option for factory ${sub}: ${extra[0]}`);
|
|
370
|
+
err(FACTORY_SUB_USAGE[sub]);
|
|
371
|
+
process.exitCode = 1;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
return sub === 'archive'
|
|
375
|
+
? factoryArchive.cmdFactoryArchive(cwd, flags)
|
|
376
|
+
: factoryPrune.cmdFactoryPrune(cwd, flags);
|
|
377
|
+
}
|
|
378
|
+
err(FACTORY_USAGE);
|
|
379
|
+
process.exitCode = 1;
|
|
380
|
+
}
|
|
381
|
+
|
|
306
382
|
function parseFlags(argv) {
|
|
307
383
|
const flags = { _: [] };
|
|
308
384
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -310,7 +386,21 @@ function parseFlags(argv) {
|
|
|
310
386
|
if (a === '--monorepo') flags.monorepo = true;
|
|
311
387
|
else if (a === '--repo') flags.repo = true;
|
|
312
388
|
else if (a === '--force' || a === '-f') flags.force = true;
|
|
389
|
+
else if (a === '--all') flags.all = true;
|
|
390
|
+
else if (a === '--dry-run') flags.dryRun = true;
|
|
391
|
+
else if (a === '--yes') flags.yes = true;
|
|
392
|
+
else if (a === '--abandoned') flags.abandoned = true;
|
|
313
393
|
else if (a === '--help' || a === '-h') flags.help = true;
|
|
394
|
+
else if (a === '--dir' || a === '--interval') {
|
|
395
|
+
const v = argv[++i];
|
|
396
|
+
if (v === undefined || v.startsWith('--')) throw new Error(`${a} requires a value`);
|
|
397
|
+
flags[a.slice(2)] = v;
|
|
398
|
+
} else if (a.startsWith('--dir=') || a.startsWith('--interval=')) {
|
|
399
|
+
const eq = a.indexOf('=');
|
|
400
|
+
const v = a.slice(eq + 1);
|
|
401
|
+
if (!v) throw new Error(`${a.slice(0, eq)}= requires a value`);
|
|
402
|
+
flags[a.slice(2, eq)] = v;
|
|
403
|
+
}
|
|
314
404
|
else if (a === '--env') {
|
|
315
405
|
const v = argv[++i];
|
|
316
406
|
if (v === undefined || v.startsWith('--')) throw new Error('--env requires a value (e.g. --env claude)');
|
|
@@ -338,8 +428,10 @@ Usage:
|
|
|
338
428
|
Add only missing template files (never overwrites existing ones), then
|
|
339
429
|
re-emit the bootstrap handoff so your AI agent can finish configuration.
|
|
340
430
|
|
|
341
|
-
npx nitm-ai-dev-toolkit upgrade
|
|
342
|
-
Upgrade to the latest published version
|
|
431
|
+
npx nitm-ai-dev-toolkit upgrade [--env <env>] [--force]
|
|
432
|
+
Upgrade to the latest published version. Like \`patch\`, adds missing files and
|
|
433
|
+
keeps your existing ones, then re-emits the bootstrap handoff. --force also
|
|
434
|
+
overwrites existing files with the latest templates (back up customisations first).
|
|
343
435
|
|
|
344
436
|
npx nitm-ai-dev-toolkit doctor [--monorepo|--repo] [--env <env>]
|
|
345
437
|
Inspect the current install: missing files, unresolved {{PLACEHOLDER}}
|
|
@@ -349,6 +441,31 @@ Usage:
|
|
|
349
441
|
Run \`npx nitm-opencode-starter install\` to scaffold the oh-my-opencode-slim
|
|
350
442
|
starter (published to npm). Falls back to printing the command if unavailable.
|
|
351
443
|
|
|
444
|
+
npx nitm-ai-dev-toolkit factory status [--dir <path>] [--all]
|
|
445
|
+
Print one table of factory jobs (factory/jobs/<NNN-slug>/job.json), then exit.
|
|
446
|
+
Closed jobs (merged, abandoned) are hidden and counted; --all shows them,
|
|
447
|
+
plus archived jobs from factory/archive/ (marked [archived]).
|
|
448
|
+
Read-only. Run /factory <feature> in your agent to create jobs.
|
|
449
|
+
|
|
450
|
+
npx nitm-ai-dev-toolkit factory watch [--dir <path>] [--interval <ms>] [--all]
|
|
451
|
+
Live terminal view of factory jobs. ↑/↓ or j/k select, Enter opens a job's
|
|
452
|
+
markdown files, q quits. Closed jobs are hidden unless --all.
|
|
453
|
+
Not a TTY? Behaves like \`factory status\`.
|
|
454
|
+
|
|
455
|
+
npx nitm-ai-dev-toolkit factory archive [--dir <path>] [--all] [--dry-run]
|
|
456
|
+
Move closed jobs (merged, abandoned) from factory/jobs/ to factory/archive/.
|
|
457
|
+
Default: only jobs closed more than 7 days ago. --all: every closed job.
|
|
458
|
+
--dry-run: list what would move, move nothing. Open jobs are never touched.
|
|
459
|
+
Does not touch git or branches (/factory archive and /factory prune handle those).
|
|
460
|
+
|
|
461
|
+
npx nitm-ai-dev-toolkit factory prune [--dir <path>] [--all] [--abandoned] [--dry-run] [--yes]
|
|
462
|
+
PERMANENTLY delete closed jobs from factory/jobs/ and factory/archive/.
|
|
463
|
+
Default: only merged jobs closed more than 7 days ago. --all: every merged job
|
|
464
|
+
(no age limit). --abandoned: also delete abandoned jobs (same age rule).
|
|
465
|
+
Without --yes it only lists what would be deleted. --dry-run always only
|
|
466
|
+
lists, even with --yes. Open jobs are never touched. Deletes job folders only;
|
|
467
|
+
git, docs and branches are not touched.
|
|
468
|
+
|
|
352
469
|
Options:
|
|
353
470
|
--env <env> Optional. Limit the scaffold to ONE harness:
|
|
354
471
|
claude | codex | copilot | cursor | opencode
|
|
@@ -358,26 +475,36 @@ Options:
|
|
|
358
475
|
file directly (no native /bootstrap command is provided).
|
|
359
476
|
--monorepo Force monorepo template
|
|
360
477
|
--repo Force single-repo template
|
|
361
|
-
--force Overwrite existing files
|
|
478
|
+
--force Overwrite existing files (install, upgrade). patch never overwrites
|
|
479
|
+
--dir <path> factory: jobs directory (default: ./factory/jobs)
|
|
480
|
+
--interval <ms>
|
|
481
|
+
factory watch: refresh interval (default: 2000, minimum: 100)
|
|
482
|
+
--all factory status/watch: include closed and archived jobs
|
|
483
|
+
factory archive: include every closed job, not just those older than 7 days
|
|
484
|
+
factory prune: include every merged job, not just those older than 7 days
|
|
485
|
+
--abandoned factory prune: also delete abandoned jobs (default: merged only)
|
|
486
|
+
--dry-run factory archive/prune: list only, change nothing
|
|
487
|
+
--yes factory prune: actually delete (without it, prune only lists)
|
|
362
488
|
-h, --help Show this help
|
|
363
489
|
`);
|
|
364
490
|
}
|
|
365
491
|
|
|
366
492
|
function main() {
|
|
367
|
-
const flags = parseFlags(process.argv.slice(2));
|
|
368
|
-
if (flags.help) {
|
|
369
|
-
usage();
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const cmd = flags._[0];
|
|
373
493
|
const cwd = process.cwd();
|
|
374
494
|
try {
|
|
495
|
+
const flags = parseFlags(process.argv.slice(2));
|
|
496
|
+
if (flags.help) {
|
|
497
|
+
usage();
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
const cmd = flags._[0];
|
|
375
501
|
switch (cmd) {
|
|
376
502
|
case 'install': return cmdInstall(cwd, flags);
|
|
377
503
|
case 'patch': return cmdPatch(cwd, flags);
|
|
378
504
|
case 'upgrade': return cmdUpgrade(cwd, flags);
|
|
379
505
|
case 'doctor': return cmdDoctor(cwd, flags);
|
|
380
506
|
case 'omo-slim-starter': return cmdOmoStarter(cwd, flags);
|
|
507
|
+
case 'factory': return cmdFactory(cwd, flags);
|
|
381
508
|
default:
|
|
382
509
|
if (cmd) err(`Unknown command: ${cmd}`);
|
|
383
510
|
usage();
|
|
@@ -394,6 +521,7 @@ module.exports = {
|
|
|
394
521
|
detectType,
|
|
395
522
|
scopeFiles,
|
|
396
523
|
templateFiles,
|
|
524
|
+
installName,
|
|
397
525
|
copyMissing,
|
|
398
526
|
scanPlaceholders,
|
|
399
527
|
envHeader,
|
|
@@ -403,7 +531,9 @@ module.exports = {
|
|
|
403
531
|
cmdPatch,
|
|
404
532
|
cmdDoctor,
|
|
405
533
|
cmdUpgrade,
|
|
534
|
+
upgradeArgs,
|
|
406
535
|
cmdOmoStarter,
|
|
536
|
+
cmdFactory,
|
|
407
537
|
ENV_DIRS,
|
|
408
538
|
SHARED_ROOT,
|
|
409
539
|
SHARED_DIRS,
|