@aperant/framework 0.6.3 → 0.6.5

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.
Files changed (244) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +64 -10
  3. package/agents/apt-improver.md +99 -0
  4. package/agents/apt-planner.md +115 -10
  5. package/dist/__test-helpers/run-cmd.d.mts +4 -2
  6. package/dist/__test-helpers/run-cmd.d.mts.map +1 -1
  7. package/dist/__test-helpers/run-cmd.mjs +56 -15
  8. package/dist/__test-helpers/run-cmd.mjs.map +1 -1
  9. package/dist/cli/artifacts/classification.d.mts.map +1 -1
  10. package/dist/cli/artifacts/classification.mjs +10 -0
  11. package/dist/cli/artifacts/classification.mjs.map +1 -1
  12. package/dist/cli/ci-watch/lock.d.mts +53 -0
  13. package/dist/cli/ci-watch/lock.d.mts.map +1 -0
  14. package/dist/cli/ci-watch/lock.mjs +172 -0
  15. package/dist/cli/ci-watch/lock.mjs.map +1 -0
  16. package/dist/cli/ci-watch/state.d.mts +36 -0
  17. package/dist/cli/ci-watch/state.d.mts.map +1 -0
  18. package/dist/cli/ci-watch/state.mjs +103 -0
  19. package/dist/cli/ci-watch/state.mjs.map +1 -0
  20. package/dist/cli/ci-watch/stop-matrix.d.mts +58 -0
  21. package/dist/cli/ci-watch/stop-matrix.d.mts.map +1 -0
  22. package/dist/cli/ci-watch/stop-matrix.mjs +164 -0
  23. package/dist/cli/ci-watch/stop-matrix.mjs.map +1 -0
  24. package/dist/cli/cli-wrappers/ci-watch.d.mts +2 -0
  25. package/dist/cli/cli-wrappers/ci-watch.d.mts.map +1 -0
  26. package/dist/cli/cli-wrappers/ci-watch.mjs +9 -0
  27. package/dist/cli/cli-wrappers/ci-watch.mjs.map +1 -0
  28. package/dist/cli/commands/adr.d.mts +5 -0
  29. package/dist/cli/commands/adr.d.mts.map +1 -0
  30. package/dist/cli/commands/adr.mjs +228 -0
  31. package/dist/cli/commands/adr.mjs.map +1 -0
  32. package/dist/cli/commands/ci-watch.d.mts +7 -0
  33. package/dist/cli/commands/ci-watch.d.mts.map +1 -0
  34. package/dist/cli/commands/ci-watch.mjs +465 -0
  35. package/dist/cli/commands/ci-watch.mjs.map +1 -0
  36. package/dist/cli/commands/context.d.mts +7 -0
  37. package/dist/cli/commands/context.d.mts.map +1 -0
  38. package/dist/cli/commands/context.mjs +224 -0
  39. package/dist/cli/commands/context.mjs.map +1 -0
  40. package/dist/cli/commands/event.d.mts.map +1 -1
  41. package/dist/cli/commands/event.mjs +59 -24
  42. package/dist/cli/commands/event.mjs.map +1 -1
  43. package/dist/cli/commands/host-detect.d.mts +1 -1
  44. package/dist/cli/commands/host-detect.d.mts.map +1 -1
  45. package/dist/cli/commands/host-detect.mjs +30 -3
  46. package/dist/cli/commands/host-detect.mjs.map +1 -1
  47. package/dist/cli/commands/init.d.mts.map +1 -1
  48. package/dist/cli/commands/init.mjs +73 -5
  49. package/dist/cli/commands/init.mjs.map +1 -1
  50. package/dist/cli/commands/modes.d.mts +13 -0
  51. package/dist/cli/commands/modes.d.mts.map +1 -0
  52. package/dist/cli/commands/modes.mjs +220 -0
  53. package/dist/cli/commands/modes.mjs.map +1 -0
  54. package/dist/cli/commands/pr-review-audit-fixer.d.mts +41 -2
  55. package/dist/cli/commands/pr-review-audit-fixer.d.mts.map +1 -1
  56. package/dist/cli/commands/pr-review-audit-fixer.mjs +91 -14
  57. package/dist/cli/commands/pr-review-audit-fixer.mjs.map +1 -1
  58. package/dist/cli/commands/route.d.mts.map +1 -1
  59. package/dist/cli/commands/route.mjs +11 -2
  60. package/dist/cli/commands/route.mjs.map +1 -1
  61. package/dist/cli/commands/task.d.mts.map +1 -1
  62. package/dist/cli/commands/task.mjs +136 -6
  63. package/dist/cli/commands/task.mjs.map +1 -1
  64. package/dist/cli/commands/tokens.d.mts.map +1 -1
  65. package/dist/cli/commands/tokens.mjs +150 -6
  66. package/dist/cli/commands/tokens.mjs.map +1 -1
  67. package/dist/cli/commands/triage.d.mts +8 -0
  68. package/dist/cli/commands/triage.d.mts.map +1 -0
  69. package/dist/cli/commands/triage.mjs +259 -0
  70. package/dist/cli/commands/triage.mjs.map +1 -0
  71. package/dist/cli/config/post-merge-sweep.d.mts +18 -0
  72. package/dist/cli/config/post-merge-sweep.d.mts.map +1 -1
  73. package/dist/cli/config/post-merge-sweep.mjs +48 -3
  74. package/dist/cli/config/post-merge-sweep.mjs.map +1 -1
  75. package/dist/cli/consistency/registry.d.mts +11 -0
  76. package/dist/cli/consistency/registry.d.mts.map +1 -1
  77. package/dist/cli/consistency/registry.mjs +13 -0
  78. package/dist/cli/consistency/registry.mjs.map +1 -1
  79. package/dist/cli/coordination/agent-identity.d.mts +9 -0
  80. package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
  81. package/dist/cli/coordination/agent-identity.mjs +11 -0
  82. package/dist/cli/coordination/agent-identity.mjs.map +1 -1
  83. package/dist/cli/coordination/event-log.d.mts +27 -0
  84. package/dist/cli/coordination/event-log.d.mts.map +1 -1
  85. package/dist/cli/coordination/event-log.mjs +72 -2
  86. package/dist/cli/coordination/event-log.mjs.map +1 -1
  87. package/dist/cli/design/frontmatter-schema.d.mts +3 -3
  88. package/dist/cli/design/frontmatter-schema.d.mts.map +1 -1
  89. package/dist/cli/design/frontmatter-schema.mjs +3 -1
  90. package/dist/cli/design/frontmatter-schema.mjs.map +1 -1
  91. package/dist/cli/dispatch.d.mts.map +1 -1
  92. package/dist/cli/dispatch.mjs +14 -1
  93. package/dist/cli/dispatch.mjs.map +1 -1
  94. package/dist/cli/gate/registry.d.mts +11 -0
  95. package/dist/cli/gate/registry.d.mts.map +1 -1
  96. package/dist/cli/gate/registry.mjs +13 -0
  97. package/dist/cli/gate/registry.mjs.map +1 -1
  98. package/dist/cli/help.d.mts.map +1 -1
  99. package/dist/cli/help.mjs +1 -0
  100. package/dist/cli/help.mjs.map +1 -1
  101. package/dist/cli/host/detect.d.mts +1 -0
  102. package/dist/cli/host/detect.d.mts.map +1 -1
  103. package/dist/cli/host/detect.mjs +5 -0
  104. package/dist/cli/host/detect.mjs.map +1 -1
  105. package/dist/cli/route/envelope.d.mts +68 -4
  106. package/dist/cli/route/envelope.d.mts.map +1 -1
  107. package/dist/cli/route/envelope.mjs +140 -103
  108. package/dist/cli/route/envelope.mjs.map +1 -1
  109. package/dist/cli/route/skill-discover.d.mts +11 -0
  110. package/dist/cli/route/skill-discover.d.mts.map +1 -1
  111. package/dist/cli/route/skill-discover.mjs +46 -1
  112. package/dist/cli/route/skill-discover.mjs.map +1 -1
  113. package/dist/cli/skill-author/contract.d.mts +20 -0
  114. package/dist/cli/skill-author/contract.d.mts.map +1 -1
  115. package/dist/cli/skill-author/contract.mjs +27 -0
  116. package/dist/cli/skill-author/contract.mjs.map +1 -1
  117. package/dist/cli/skill-author/skill-template.d.mts.map +1 -1
  118. package/dist/cli/skill-author/skill-template.mjs +4 -3
  119. package/dist/cli/skill-author/skill-template.mjs.map +1 -1
  120. package/dist/cli/task/worktree-cleanup.d.mts +9 -1
  121. package/dist/cli/task/worktree-cleanup.d.mts.map +1 -1
  122. package/dist/cli/task/worktree-cleanup.mjs +190 -9
  123. package/dist/cli/task/worktree-cleanup.mjs.map +1 -1
  124. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  125. package/dist/plugin/agents/apt-planner.md +1 -1
  126. package/dist/plugin/skills/apt/SKILL.md +111 -5
  127. package/dist/plugin/skills/apt-author-skill/SKILL.md +11 -0
  128. package/dist/plugin/skills/apt-bootstrap/SKILL.md +1 -0
  129. package/dist/plugin/skills/apt-classify/SKILL.md +1 -0
  130. package/dist/plugin/skills/apt-close-task/SKILL.md +1 -0
  131. package/dist/plugin/skills/apt-create-docs/SKILL.md +1 -0
  132. package/dist/plugin/skills/apt-debug/SKILL.md +2 -0
  133. package/dist/plugin/skills/apt-design/SKILL.md +2 -0
  134. package/dist/plugin/skills/apt-discuss/SKILL.md +2 -0
  135. package/dist/plugin/skills/apt-docs/SKILL.md +2 -0
  136. package/dist/plugin/skills/apt-execute/SKILL.md +1 -0
  137. package/dist/plugin/skills/apt-mockup/SKILL.md +2 -0
  138. package/dist/plugin/skills/apt-pause/SKILL.md +1 -0
  139. package/dist/plugin/skills/apt-personas/SKILL.md +1 -0
  140. package/dist/plugin/skills/apt-plan/SKILL.md +2 -0
  141. package/dist/plugin/skills/apt-pr-review/SKILL.md +1 -0
  142. package/dist/plugin/skills/apt-quick/SKILL.md +2 -0
  143. package/dist/plugin/skills/apt-resume/SKILL.md +1 -0
  144. package/dist/plugin/skills/apt-review/SKILL.md +1 -0
  145. package/dist/plugin/skills/apt-roadmap/SKILL.md +1 -0
  146. package/dist/plugin/skills/apt-roundtable/SKILL.md +2 -0
  147. package/dist/plugin/skills/apt-run/SKILL.md +1 -0
  148. package/dist/plugin/skills/apt-scan/SKILL.md +1 -0
  149. package/dist/plugin/skills/apt-setup/SKILL.md +1 -0
  150. package/dist/plugin/skills/apt-ship/SKILL.md +6 -5
  151. package/dist/plugin/skills/apt-stress-test/SKILL.md +1 -0
  152. package/dist/plugin/skills/apt-terminal/SKILL.md +1 -0
  153. package/dist/plugin/skills/apt-update/SKILL.md +5 -0
  154. package/dist/plugin/skills/apt-verify/SKILL.md +1 -0
  155. package/dist/plugin/skills/apt-verify-proof/SKILL.md +1 -0
  156. package/dist/types/config.d.ts +85 -0
  157. package/dist/types/config.d.ts.map +1 -1
  158. package/package.json +125 -122
  159. package/prompts/coder.md +2 -0
  160. package/prompts/planner.md +12 -0
  161. package/prompts/spec_writer.md +9 -0
  162. package/skills/apt/SKILL.md +112 -5
  163. package/skills/apt-author-skill/SKILL.md +11 -0
  164. package/skills/apt-bootstrap/SKILL.md +1 -0
  165. package/skills/apt-classify/SKILL.md +1 -0
  166. package/skills/apt-close-task/SKILL.md +33 -1
  167. package/skills/apt-create-docs/SKILL.md +1 -0
  168. package/skills/apt-debug/SKILL.md +41 -6
  169. package/skills/apt-debug/appendices/diagnose-discipline.md +119 -0
  170. package/skills/apt-design/SKILL.md +2 -0
  171. package/skills/apt-diagram/SKILL.md +342 -0
  172. package/skills/apt-diagram/appendices/design-discipline.md +97 -0
  173. package/skills/apt-discuss/SKILL.md +27 -0
  174. package/skills/apt-discuss/appendices/grill-discipline.md +104 -0
  175. package/skills/apt-discuss/appendices/zoom-out-helper.md +79 -0
  176. package/skills/apt-docs/SKILL.md +2 -0
  177. package/skills/apt-execute/SKILL.md +49 -5
  178. package/skills/apt-execute/appendices/tdd-mode.md +107 -0
  179. package/skills/apt-improve/DEEPENING.md +84 -0
  180. package/skills/apt-improve/INTERFACE-DESIGN.md +97 -0
  181. package/skills/apt-improve/LANGUAGE.md +104 -0
  182. package/skills/apt-improve/SKILL.md +141 -0
  183. package/skills/apt-mockup/SKILL.md +2 -0
  184. package/skills/apt-pause/SKILL.md +1 -0
  185. package/skills/apt-personas/SKILL.md +1 -0
  186. package/skills/apt-plan/SKILL.md +149 -4
  187. package/skills/apt-planner.md +42 -1
  188. package/skills/apt-pr-review/SKILL.md +47 -16
  189. package/skills/apt-prototype/LOGIC.md +109 -0
  190. package/skills/apt-prototype/SKILL.md +143 -0
  191. package/skills/apt-prototype/UI.md +90 -0
  192. package/skills/apt-quick/SKILL.md +32 -0
  193. package/skills/apt-resume/SKILL.md +1 -0
  194. package/skills/apt-review/SKILL.md +3 -0
  195. package/skills/apt-roadmap/SKILL.md +1 -0
  196. package/skills/apt-roundtable/SKILL.md +2 -0
  197. package/skills/apt-run/SKILL.md +33 -4
  198. package/skills/apt-scan/SKILL.md +1 -0
  199. package/skills/apt-setup/SKILL.md +129 -2
  200. package/skills/apt-ship/SKILL.md +52 -4
  201. package/skills/apt-stress-test/SKILL.md +1 -0
  202. package/skills/apt-terminal/SKILL.md +1 -0
  203. package/skills/apt-triage/AGENT-BRIEF.md +84 -0
  204. package/skills/apt-triage/OUT-OF-SCOPE.md +75 -0
  205. package/skills/apt-triage/SKILL.md +169 -0
  206. package/skills/apt-update/SKILL.md +3 -0
  207. package/skills/apt-verify/SKILL.md +4 -0
  208. package/skills/apt-verify-proof/SKILL.md +4 -0
  209. package/skills/apt-watch-ci/SKILL.md +163 -0
  210. package/skills/apt-zoom-out/SKILL.md +130 -0
  211. package/src/cli/artifacts/classification.mjs +10 -0
  212. package/src/cli/ci-watch/lock.mjs +178 -0
  213. package/src/cli/ci-watch/state.mjs +103 -0
  214. package/src/cli/ci-watch/stop-matrix.mjs +181 -0
  215. package/src/cli/cli-wrappers/ci-watch.mjs +9 -0
  216. package/src/cli/commands/adr.mjs +243 -0
  217. package/src/cli/commands/ci-watch.mjs +503 -0
  218. package/src/cli/commands/context.mjs +244 -0
  219. package/src/cli/commands/event.mjs +63 -24
  220. package/src/cli/commands/host-detect.mjs +33 -7
  221. package/src/cli/commands/init.mjs +83 -5
  222. package/src/cli/commands/modes.mjs +215 -0
  223. package/src/cli/commands/pr-review-audit-fixer.mjs +95 -16
  224. package/src/cli/commands/route.mjs +11 -2
  225. package/src/cli/commands/task.mjs +152 -18
  226. package/src/cli/commands/tokens.mjs +157 -6
  227. package/src/cli/commands/triage.mjs +277 -0
  228. package/src/cli/config/post-merge-sweep.mjs +49 -3
  229. package/src/cli/consistency/registry.mjs +14 -0
  230. package/src/cli/coordination/agent-identity.mjs +12 -0
  231. package/src/cli/coordination/event-log.mjs +73 -2
  232. package/src/cli/design/frontmatter-schema.mjs +3 -1
  233. package/src/cli/dispatch.mjs +15 -1
  234. package/src/cli/gate/registry.mjs +14 -0
  235. package/src/cli/help.mjs +1 -0
  236. package/src/cli/host/detect.mjs +5 -0
  237. package/src/cli/route/envelope.mjs +140 -106
  238. package/src/cli/route/skill-discover.mjs +46 -1
  239. package/src/cli/skill-author/contract.mjs +29 -0
  240. package/src/cli/skill-author/skill-template.mjs +4 -3
  241. package/src/cli/task/worktree-cleanup.mjs +191 -9
  242. package/templates/adr-format.md +56 -0
  243. package/templates/config.json +4 -0
  244. package/templates/context-format.md +34 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,67 @@
3
3
  All notable changes to `@aperant/framework` are documented here. See
4
4
  [`VERSIONING.md`](VERSIONING.md) for the per-tier contract.
5
5
 
6
+ ## 0.6.5 — 2026-05-14 — Drop aggregate envelope cap
7
+
8
+ Replaces the aggregate `ENVELOPE_MAX_BYTES` cap in
9
+ `src/cli/route/envelope.mjs` with a per-skill description budget. The
10
+ aggregate cap was bumped 9 times in 3 weeks (8192 → 11264) and was
11
+ theater on 1M-token hosts (30 skills × 256 bytes = 0.28 % of context).
12
+ It was a proxy for two unrelated constraints — classifier precision
13
+ (already measured by route-eval) and per-skill description quality
14
+ (never actually enforced) — and shouted at the wrong author each time
15
+ a new skill landed.
16
+
17
+ - **New constant.** `MAX_DESCRIPTION_BYTES = 256` is exported from
18
+ `envelope.mjs`. The budget binds visible AND internal skills, so an
19
+ internal SKILL.md cannot ship a 4 KB description through the
20
+ side-channel.
21
+ - **New helper.** `enforceDescriptionBudget(skills, budgetBytes)`
22
+ replaces `truncateLongestFirst`. It walks each skill once: passes
23
+ through if the wrapped description fits the budget; else tries
24
+ `truncateDescriptionToFirstSentence`; if the trim succeeds and now
25
+ fits, marks `truncated:true` and increments `truncated_count`; if the
26
+ trim still doesn't fit (or trim was a no-op), records the offender
27
+ (`{ name, bytes, description }`) and stops. The builder throws with
28
+ the offender named so the next fix lands on the right author the
29
+ first time.
30
+ - **Error code rename.** The `cmdRoute` catch branch now emits
31
+ `error_code: 'skill_description_too_long'` (was `'envelope_overflow'`).
32
+ - **Decision source.** Codex spar 2026-05-14.
33
+ - **Tests.** `envelope-budget.test.ts`, `envelope-truncation.test.ts`,
34
+ and `route-envelope-builder.test.ts` rewritten for the per-skill
35
+ pathway. Aggregate-cap pins and the 400-byte headroom invariant are
36
+ gone.
37
+
38
+ Schema unchanged (still v4). The router envelope JSON shape is
39
+ unchanged for consumers — the only externally observable difference is
40
+ the renamed error_code in the over-budget path.
41
+
42
+ `task: 14-05-26_drop-aggregate-envelope-max-bytes-cap-fr-03rb`
43
+
44
+ ## 0.6.4 — 2026-05-13 — Upgrade `--yes` infers visibility from git tracking
45
+
46
+ Patch on top of 0.6.3 closing the last surface of the 0.6.0/0.6.1
47
+ visibility-flip dogfood incident.
48
+
49
+ - **`init --yes` upgrade path now infers `share.visibility` from git
50
+ tracking** when the existing config is pre-visibility (v3 schema) and
51
+ no explicit `--solo`/`--team` was passed. Heuristic: if `git ls-files`
52
+ reports any tracked file under `.aperant/` or any runtime install root
53
+ (`.claude/`, `.codex/`, …), assume `team` — these repos were already
54
+ sharing framework state via git. Otherwise fall back to `solo`. The
55
+ recorded `applied_defaults` entry tags the inferred case with
56
+ `source: "--yes (inferred from git tracking)"` so unattended installs
57
+ remain auditable. Net effect: a team repo that runs `--yes` no longer
58
+ has `.gitignore` silently rewritten to solo allow-list rules.
59
+ - **`/apt:update` skill hardened.** Step 3 now explicitly forbids adding
60
+ `--yes` or any Class A flag. If `init` returns a `requires_input`
61
+ envelope, the skill surfaces it verbatim and stops — the user must
62
+ pick team vs solo themselves. The 0.6.4 framework inference is a
63
+ defense-in-depth backstop, not the primary boundary.
64
+
65
+ No schema bump (still v4). No breaking changes.
66
+
6
67
  ## 0.6.3 — 2026-05-12 — README license + tarball slim
7
68
 
8
69
  Follow-up patch on top of the 0.6.2 first-public release. Three fixes:
package/README.md CHANGED
@@ -7,19 +7,73 @@ AI coding framework -- composable skills for planning, executing, verifying, and
7
7
 
8
8
  The Aperant Framework provides a structured methodology for AI-assisted software development. It works as slash commands in Claude Code, tasks in OpenAI Codex, or programmatically via the TypeScript API. One set of prompts, any AI tool.
9
9
 
10
- ## What It Does
10
+ ## Just type `/apt` — natural language routing
11
11
 
12
- Five composable skills that cover the full implementation lifecycle:
12
+ You don't need to memorize commands. The `/apt` router auto-classifies your input by intent and complexity, then dispatches to the right skill.
13
13
 
14
- | Skill | Command | Description |
15
- | ------- | -------------- | ----------------------------------------------------------------------------------- |
16
- | Plan | `/apt:plan` | Analyze a task, assess complexity, investigate codebase, produce spec + implementation plan |
17
- | Execute | `/apt:execute` | Implement subtasks from a plan with atomic commits and progress tracking |
18
- | Verify | `/apt:verify` | Score implementation against spec on 4 dimensions (correctness, completeness, quality, coverage) |
19
- | Review | `/apt:review` | Multi-pass AI code review with findings tree and severity classification |
20
- | Run | `/apt:run` | Full pipeline: plan -> execute -> verify -> review in one command |
14
+ ```
15
+ /apt add OAuth login with Google
16
+ /apt the chat scroll is jittery debug it
17
+ /apt help me think through the new pricing model
18
+ /apt typo in the footer wrong year
19
+ /apt review my PR
20
+ ```
21
21
 
22
- Each skill is self-contained. Use `/apt:plan` alone for planning, `/apt:verify` alone for QA, or `/apt:run` for the full pipeline.
22
+ Behind the scenes:
23
+
24
+ | You type | Router picks | Why |
25
+ |---|---|---|
26
+ | `add OAuth login with Google` | `/apt:plan` | multi-file feature, STANDARD track |
27
+ | `chat scroll is jittery — debug it` | `/apt:debug` | investigation-first language |
28
+ | `help me think through the new pricing model` | `/apt:discuss --brainstorm` | exploratory framing, no concrete deliverable |
29
+ | `typo in the footer — wrong year` | `/apt:quick` | trivial single-file fix |
30
+ | `review my PR` | `/apt:pr-review` | PR reference triggers multi-agent review |
31
+
32
+ If the router isn't sure, it shows the top candidates and lets you pick. You can always be explicit (`/apt:plan ...`, `/apt:debug ...`) — the router is a shortcut, not the only path. Track classification (QUICK / STANDARD / DEEP / DEBUG) happens inline; no recursive LLM call.
33
+
34
+ Works identically under Claude Code (`/apt`), Codex (`$apt`), Gemini (`/apt`), and other supported CLIs — see [Host Support](#host-support) below.
35
+
36
+ ## Command reference
37
+
38
+ All 30+ skills below are also addressable directly. Listed by lifecycle stage.
39
+
40
+ | Stage | Command | Purpose |
41
+ |---|---|---|
42
+ | **Route** | `/apt` | Smart router — natural-language dispatch to any skill |
43
+ | **Discovery** | `/apt:scan` | Build/refresh `.aperant/features/` registry — recommended after install on brownfield projects |
44
+ | **Discovery** | `/apt:zoom-out` | One-page architectural orientation for an unfamiliar area |
45
+ | **Discovery** | `/apt:improve` | 3-lens scan for refactor opportunities (DEEPENING / INTERFACE-DESIGN / LANGUAGE) |
46
+ | **Discovery** | `/apt:debug` | Systematic debugging with persistent state across context resets |
47
+ | **Planning** | `/apt:discuss` | Brainstorm a vision or lock ambiguous decisions before planning |
48
+ | **Planning** | `/apt:design` | Pre-coding wireframe → critique → handoff to `/apt:plan` |
49
+ | **Planning** | `/apt:mockup` | Visual HTML+Tailwind mockup loop with parallel variants |
50
+ | **Planning** | `/apt:plan` | Investigate codebase, produce `spec.md` + `implementation_plan.json` |
51
+ | **Planning** | `/apt:roundtable` | 10-agent structured debate with supermajority voting for complex decisions |
52
+ | **Planning** | `/apt:stress-test` | Scenario simulation to catch operational gaps in plans before execution |
53
+ | **Planning** | `/apt:prototype` | Question-driven throwaway prototyping (LOGIC + UI branches) |
54
+ | **Build** | `/apt:quick` | Fast single-shot task — skip planning, go straight to implementation |
55
+ | **Build** | `/apt:execute` | Build code from a plan with atomic commits and progress tracking |
56
+ | **Build** | `/apt:run` | Full pipeline: plan → execute → verify → review in one command |
57
+ | **Verify** | `/apt:verify` | 4-dimension QA scoring (correctness / completeness / quality / coverage) |
58
+ | **Verify** | `/apt:verify-proof` | Visual proof verification — screenshots, video, HTML report |
59
+ | **Verify** | `/apt:review` | 6-pass inline code review (logic / security / quality / architecture / performance / docs-coherence) with fix-all pipeline |
60
+ | **Verify** | `/apt:pr-review` | Multi-agent PR review — 6 parallel specialists + validator + fixer + self-reviewer (owned + external authorship modes) |
61
+ | **Ship** | `/apt:ship` | Create PR with QA scores, decision traceability, commit-to-subtask mapping |
62
+ | **Ship** | `/apt:watch-ci` | Post-ship CI watcher — polls PR checks, auto-fixes red, pushes, reschedules |
63
+ | **Ship** | `/apt:close-task` | Post-merge closer — confirm merged, flip phase, GC state |
64
+ | **Session** | `/apt:pause` | Human-initiated handoff — save CONTINUE artifacts when you need to stop |
65
+ | **Session** | `/apt:resume` | Restore context from paused session and route to next action |
66
+ | **Docs** | `/apt:docs` | Generate/update documentation verified against the actual codebase |
67
+ | **Docs** | `/apt:create-docs` | Persona-first product docs from PROJECT.md + personas.json + features registry |
68
+ | **Docs** | `/apt:diagram` | Render a DiagramScene to `.excalidraw` file or live Excalidraw MCP canvas |
69
+ | **Project** | `/apt:bootstrap` | Generate/refresh PROJECT.md (product-context source of truth) |
70
+ | **Project** | `/apt:personas` | Discover 3–5 product personas grounded in code + PROJECT.md |
71
+ | **Project** | `/apt:roadmap` | Manage per-scope milestones, phases, owners, ROADMAP.md rendering |
72
+ | **Project** | `/apt:triage` | Move a task through the 5-state machine (needs-triage / needs-info / ready-for-agent / ready-for-human / wontfix) |
73
+ | **Framework** | `/apt:setup` | Change preferences (verification style, multi-model, parallelization, branching) |
74
+ | **Framework** | `/apt:update` | Refresh installed skills / agents / hooks across every runtime |
75
+
76
+ Each skill is self-contained — use `/apt:plan` alone for planning, `/apt:verify` alone for QA, or `/apt:run` for the full pipeline.
23
77
 
24
78
  ### Declarative YAML Workflows (C17)
25
79
 
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: apt-improver
3
+ description: Proactive refactor discovery agent — runs apt:improve Phase 1 (explore a named area through DEEPENING / INTERFACE-DESIGN / LANGUAGE lenses) and outputs a candidate refactor inventory. Read-only, no code changes.
4
+ apt-skill-version: {{APT_VERSION}}
5
+ tools: Read, Bash, Grep, Glob
6
+ color: orange
7
+ ---
8
+
9
+ <role>
10
+ You are an Aperant Framework proactive-refactor agent. You scan a named
11
+ area of the codebase through three lenses (DEEPENING, INTERFACE-DESIGN,
12
+ LANGUAGE) and produce a candidate refactor inventory.
13
+
14
+ Spawned by `/apt:improve` for Phase 1 (Explore). Phases 2 (Present
15
+ candidates) and 3 (Deepen via grill loop) run in the parent agent
16
+ context because they require user interaction.
17
+
18
+ Your job: read the area, apply the three lenses, output a candidate
19
+ inventory. You are READ-ONLY — no code changes, no decisions locked.
20
+
21
+ **CRITICAL: Mandatory Initial Read**
22
+ If the prompt contains a `<files_to_read>` block, you MUST use the `Read`
23
+ tool to load every file listed there before performing any other actions.
24
+ </role>
25
+
26
+ <project_context>
27
+ **Project instructions:** Read `./CLAUDE.md` if it exists for project structure and conventions.
28
+ **Constitution:** Read `AGENTS.md` if it exists for architecture overview.
29
+ **Glossary:** Read `CONTEXT.md` if it exists — its term-blocks (especially `Aliases to avoid` fields) are direct inputs to the LANGUAGE lens.
30
+
31
+ **Rationalizations (R4):** Read `.aperant/rationalizations/claude-opus-4-6.md` once at session start. Pay particular attention to R-2 (skipping pre-read investigation) and R-5 ("I already verified this implicitly"). As an improver, you only have value if your candidate inventory is grounded in actually-read code — drift here ships hallucinated refactor candidates.
32
+ </project_context>
33
+
34
+ <environment>
35
+ - **Working directory:** The project root
36
+ - **Note:** You have NO write/edit tools. You investigate and report findings only. Phase 2 (filter + present) and Phase 3 (deepen + lock) run in the parent agent's context.
37
+ </environment>
38
+
39
+ <process>
40
+
41
+ ## 1. Parse the area name
42
+
43
+ Extract the area from the spawn prompt. Areas are noun phrases ("sparring engine", "feature registry", "auth flow") — not file paths.
44
+
45
+ If the area is ambiguous, ask the parent ONE clarifying question via your report — do NOT enter a multi-turn interview.
46
+
47
+ ## 2. Load CONTEXT.md (if present)
48
+
49
+ If `CONTEXT.md` exists at the project root, read it and extract:
50
+
51
+ - Term-blocks whose canonical term, definition, or aliases-to-avoid match keywords in the area
52
+ - The full alias list (LANGUAGE lens grep source)
53
+
54
+ If CONTEXT.md does not exist, skip silently — the LANGUAGE lens runs without the alias grep but still catches in-file conflations.
55
+
56
+ ## 3. Apply the three lenses
57
+
58
+ Read the lens descriptions (the parent has them in context; if you don't, read them from disk).
59
+ Paths below are relative to the project root (monorepo: `<repo>/packages/framework/` is the
60
+ framework root; standalone install: the project root IS the framework root, so use
61
+ `skills/apt-improve/` directly):
62
+
63
+ - `packages/framework/skills/apt-improve/DEEPENING.md` (monorepo) or `skills/apt-improve/DEEPENING.md` (standalone)
64
+ - `packages/framework/skills/apt-improve/INTERFACE-DESIGN.md` (monorepo) or `skills/apt-improve/INTERFACE-DESIGN.md` (standalone)
65
+ - `packages/framework/skills/apt-improve/LANGUAGE.md` (monorepo) or `skills/apt-improve/LANGUAGE.md` (standalone)
66
+
67
+ For each lens, walk the area's files and flag candidates per the lens's red-flag list.
68
+
69
+ ## 4. Output the candidate inventory
70
+
71
+ Produce a structured report:
72
+
73
+ ```markdown
74
+ # apt:improve Phase-1 inventory — {area}
75
+
76
+ ## DEEPENING candidates
77
+ - `{File}:{Symbol}` — shallow ({reason}); deletion-test target.
78
+ - ...
79
+
80
+ ## INTERFACE-DESIGN candidates
81
+ - `{Module A}` ↔ `{Module B}` — {red-flag name} ({one-line evidence}).
82
+ - ...
83
+
84
+ ## LANGUAGE candidates
85
+ - `{File}:{Line}` — uses `{wrong-term}` for `{canonical}` ({CONTEXT.md reference if applicable}).
86
+ - ...
87
+
88
+ ## Files read
89
+ - {file1}
90
+ - ...
91
+ ```
92
+
93
+ Keep the inventory grounded — every candidate must cite a file + symbol the user can grep for. No speculation; no candidates inferred from filenames alone.
94
+
95
+ ## 5. Hand back to parent for Phase 2/3
96
+
97
+ Your output is the input to Phase 2 (the parent agent's filter step). Do NOT enter Phase 2 yourself — your role ends here.
98
+
99
+ </process>
@@ -199,7 +199,13 @@ If unable to enumerate (network unavailable, action docs unclear), flag it expli
199
199
 
200
200
  ## 4. Write Specification
201
201
 
202
- Create `{task_dir}/spec.md`:
202
+ The spec.md content format **branches on track** (Pocock adoption ID-05,
203
+ Fast Path Guarantee). QUICK-routed tasks keep the existing 4-section
204
+ shape; STANDARD/DEEP/COMPLEX tasks get a PRD-shaped artifact that
205
+ survives the task as a second-consumer document.
206
+
207
+ ### 4.A. QUICK track / SIMPLE complexity — legacy 4-section spec
208
+
203
209
  ```markdown
204
210
  # Task: {task description}
205
211
 
@@ -219,6 +225,57 @@ Create `{task_dir}/spec.md`:
219
225
  {What this task explicitly does NOT cover}
220
226
  ```
221
227
 
228
+ ### 4.B. STANDARD / DEEP / COMPLEX — PRD-shaped spec.md
229
+
230
+ ```markdown
231
+ # Spec: {task title}
232
+
233
+ **Task ID:** {task-id}
234
+ **Track:** {STANDARD | DEEP}
235
+ **Scope:** {framework | desktop | web | core | ui | backend | docs}
236
+
237
+ ## Problem Statement
238
+ {What pain are we solving? Cite empirical evidence where possible.}
239
+
240
+ ## Solution
241
+ {Chosen approach + bulleted net delta of files / flags / config / skills.}
242
+
243
+ ## User Stories
244
+ {One **US-NN (persona).** story per user-value slice. Stories map 1:1
245
+ onto subtasks in implementation_plan.json.}
246
+
247
+ ## Implementation Decisions
248
+ {Load-bearing principles carried into every subtask. Format:
249
+ "### ID-NN: {title}" + rationale + practical consequence.}
250
+
251
+ ## Testing Decisions
252
+ {One block per test family: "### TD-NN: {family}" + what's covered +
253
+ which subtask owns the test file. Fast Path regression tests MUST be
254
+ enumerated here.}
255
+
256
+ ## Out of Scope
257
+ {Non-goals. Each bullet names what is deferred + where it belongs.}
258
+
259
+ ## Further Notes
260
+ {Sequencing rationale, risk surface, dependencies, files-affected
261
+ preview, and any other executor-load-bearing context.}
262
+
263
+ ### Acceptance Criteria
264
+ {Cross-cutting **AC1..ACN** list — each AC gets a stable ID. Subtasks
265
+ reference these IDs via the per-subtask `acceptance_criteria` field.}
266
+ ```
267
+
268
+ **PRD section ordering is load-bearing.** `apt-tools coverage-check
269
+ validate` greps `## Acceptance Criteria`; `apt-tools consistency check`
270
+ greps `## Solution` and `## User Stories`. Renaming or reordering these
271
+ sections breaks downstream tooling and the C15 consistency rules.
272
+
273
+ **Do NOT interview the user.** The PRD is synthesized from the task
274
+ description + codebase investigation + AGENTS.md, not from a clarifying
275
+ back-and-forth. If a section truly cannot be filled, write
276
+ `{TBD — needs user input}`; do NOT pause for clarification (that is
277
+ `apt:discuss`'s surface, not the planner's).
278
+
222
279
  ### 4.05. Design Reference section (C24 — when design.md exists)
223
280
 
224
281
  When `{task_dir}/design.md` exists, `spec.md` MUST include a `## Design Reference` section directly below `## Requirements`. Shape:
@@ -275,12 +332,41 @@ fix it now, not later.
275
332
 
276
333
  ## 5. Create Implementation Plan
277
334
 
278
- Create `{task_dir}/implementation_plan.json`:
335
+ Subtask schema branches on track (Pocock adoption ID-05 — Fast Path Guarantee).
336
+
337
+ ### 5.A. QUICK track / SIMPLE complexity — legacy flat subtask schema
338
+
339
+ ```json
340
+ {
341
+ "task": "{task description}",
342
+ "complexity": "simple",
343
+ "spec": "spec.md",
344
+ "subtasks": [
345
+ {
346
+ "id": "1",
347
+ "title": "{subtask title}",
348
+ "description": "{what to do — concrete, not vague}",
349
+ "files": ["path/to/file1.ts", "path/to/file2.ts"],
350
+ "dependencies": [],
351
+ "status": "pending",
352
+ "verification": "{command or check to verify completion}"
353
+ }
354
+ ]
355
+ }
356
+ ```
357
+
358
+ QUICK subtasks omit `hitl`, `afk`, `acceptance_criteria`, and `user_value`
359
+ fields. The one-shot path doesn't need user-value framing or per-subtask
360
+ HITL gates.
361
+
362
+ ### 5.B. STANDARD / DEEP / COMPLEX — vertical-slice subtask schema
363
+
279
364
  ```json
280
365
  {
281
366
  "task": "{task description}",
282
- "complexity": "simple|standard|complex",
367
+ "complexity": "standard|complex",
283
368
  "spec": "spec.md",
369
+ "vertical_slice_schema_version": "1",
284
370
  "declared_persona_tier": "primary",
285
371
  "declared_personas": ["mobile-dev"],
286
372
  "tier_confidence": "high",
@@ -308,29 +394,48 @@ Create `{task_dir}/implementation_plan.json`:
308
394
  "subtasks": [
309
395
  {
310
396
  "id": "1",
311
- "title": "{subtask title}",
397
+ "title": "{subtask title — user-value framing, not 'add UI'}",
312
398
  "description": "{what to do — concrete, not vague}",
313
399
  "files": ["path/to/file1.ts", "path/to/file2.ts"],
314
400
  "acceptance_criteria": ["AC1", "AC3"],
315
401
  "dependencies": [],
316
402
  "status": "pending",
403
+ "hitl": "required | review | none",
404
+ "afk": "safe | unsafe",
405
+ "user_value": "{one-line user-value framing — who benefits, how}",
317
406
  "verification": "{command or check to verify completion}"
318
407
  }
319
408
  ]
320
409
  }
321
410
  ```
322
411
 
412
+ Mandatory STANDARD/DEEP fields per subtask:
413
+
414
+ - `hitl` — `"required" | "review" | "none"`. `required` blocks the
415
+ executor pending human approval (autonomy 1 always pauses; autonomy 2
416
+ batches; autonomy 3 escalates only on conflict). `review` means the
417
+ human reviews the diff post-hoc, not blocking. `none` is agent-only.
418
+ - `afk` — `"safe" | "unsafe"`. `safe` means proceed unattended. `unsafe`
419
+ means pause at the start of this subtask if no human is present
420
+ (autonomy < 3).
421
+ - `acceptance_criteria` — `string[]` of id-refs (`"AC1"`, …) into spec.md's
422
+ `## Acceptance Criteria` section.
423
+ - `user_value` — one-line framing of WHO benefits and HOW. Prevents
424
+ horizontal slicing — every subtask is a vertical user-shippable slice.
425
+
426
+ Plan-level: `vertical_slice_schema_version: "1"` declares the schema
427
+ version so future migrations can detect this plan as v1.
428
+
323
429
  Rules:
324
430
  - Each subtask completable in one focused session
325
431
  - Dependencies form a DAG (no circular deps)
326
432
  - Verification must be automated (test command, grep check, type check)
327
433
  - Files list must be exhaustive — every file the subtask touches
328
- - `acceptance_criteria` is mandatory: list the canonical AC id-refs
329
- (`"AC1"`, `"AC3"`, ...) from the `## Acceptance Criteria` section of
330
- spec.md that this subtask satisfies. Verbatim AC text is accepted but
331
- discouraged — the id-ref form is stable across spec edits. Every AC in
332
- spec.md must be referenced by at least one subtask; gate G8
333
- (`consistency-check`) enforces this on ship.
434
+ - `acceptance_criteria` is mandatory on STANDARD/DEEP: every AC in spec.md
435
+ must be referenced by at least one subtask; gate G8
436
+ (`consistency-check`) enforces this on ship. Verbatim AC text is
437
+ accepted but discouraged — id-refs are stable across spec edits.
438
+ - Subtask title MUST frame user value, not file scope.
334
439
 
335
440
  ### 5.1 Framework-scope doc-sync rule
336
441
 
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * @param {Function} cmdFn — the Layer 1 cmd function (sync or async).
3
3
  * @param {unknown[]} [args=[]] — argv-shaped positional args.
4
- * @param {{ strictExit?: boolean, env?: Record<string, string> }} [opts]
5
- * @returns {Promise<{ result: unknown, stdout: string, exitCode: number }>}
4
+ * @param {{ strictExit?: boolean, resetCaches?: boolean, env?: Record<string, string> }} [opts]
5
+ * @returns {Promise<{ result: unknown, stdout: string, stderr: string, exitCode: number }>}
6
6
  */
7
7
  export function runCmd(cmdFn: Function, args?: unknown[], opts?: {
8
8
  strictExit?: boolean;
9
+ resetCaches?: boolean;
9
10
  env?: Record<string, string>;
10
11
  }): Promise<{
11
12
  result: unknown;
12
13
  stdout: string;
14
+ stderr: string;
13
15
  exitCode: number;
14
16
  }>;
15
17
  //# sourceMappingURL=run-cmd.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd.d.mts","sourceRoot":"","sources":["../../src/__test-helpers/run-cmd.mjs"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,+CAJW,OAAO,EAAE,SACT;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACpD,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD1E"}
1
+ {"version":3,"file":"run-cmd.d.mts","sourceRoot":"","sources":["../../src/__test-helpers/run-cmd.mjs"],"names":[],"mappings":"AAiDA;;;;;GAKG;AACH,+CAJW,OAAO,EAAE,SACT;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAiF1F"}
@@ -2,16 +2,18 @@
2
2
  * run-cmd.mjs — D-05 in-process command harness.
3
3
  *
4
4
  * `runCmd(cmdFn, args, opts)` invokes a Layer 1 command function in-process
5
- * (no subprocess), captures stdout, traps any process.exit calls (via a
6
- * try/finally restore), and returns:
5
+ * (no subprocess), captures stdout + stderr, traps any process.exit calls
6
+ * (via a try/finally restore), stubs `process.stdin.isTTY` /
7
+ * `process.stdout.isTTY` to `false` for the trapped invocation duration, and
8
+ * returns:
7
9
  *
8
- * { result, stdout, exitCode }
10
+ * { result, stdout, stderr, exitCode }
9
11
  *
10
12
  * `result` is the cmd function's return value (typically `{envelope, exitCode}`
11
13
  * after the migration; `null` if the cmd called process.exit before returning).
12
- * `stdout` is the captured stdout.write payload (string). `exitCode` is the
13
- * effective exit code: the trapped exit code if process.exit was called, else
14
- * `result.exitCode`, else 0.
14
+ * `stdout` / `stderr` are the captured `*.write` payloads (string). `exitCode`
15
+ * is the effective exit code: the trapped exit code if process.exit was called,
16
+ * else `result.exitCode`, else 0.
15
17
  *
16
18
  * D-05 (d) decision: strictExit DEFAULTS TO TRUE — the harness throws a
17
19
  * strict-mode-violation Error any time a Layer 1 cmd calls process.exit.
@@ -19,10 +21,23 @@
19
21
  * `{ strictExit: false }` until the underlying cmd is rewritten. After Wave 5
20
22
  * (subtask 25) zero `strictExit: false` opt-outs remain in __tests__/.
21
23
  *
22
- * Restoration: process.exit and process.stdout.write are saved at entry and
23
- * restored unconditionally in a try/finally. A test that crashes mid-call
24
- * still leaves the global state byte-identical for the next test in the file.
24
+ * Restoration: process.exit, process.stdout.write, process.stderr.write, and
25
+ * the two `isTTY` bits are saved at entry and restored unconditionally in a
26
+ * try/finally. A test that crashes mid-call still leaves the global state
27
+ * byte-identical for the next test in the file.
28
+ *
29
+ * Cache resets (F3 subtask 1): by default the harness clears the two
30
+ * path-keyed module-graph caches that can leak across cmd invocations within
31
+ * a single vitest worker — `skill-discover._discoverCache` and the
32
+ * `agent-identity` identity cache. The `gate/registry` and
33
+ * `consistency/registry` registries are NOT cleared by default because their
34
+ * built-in entries are populated by barrel imports that ESM evaluates exactly
35
+ * ONCE per process — clearing them would leave subsequent cmd invocations
36
+ * looking at an empty registry. Tests that specifically need an empty
37
+ * registry import `__resetCaches()` from those modules directly.
25
38
  */
39
+ import { __resetCaches as __resetAgentIdentityCaches } from '../cli/coordination/agent-identity.mjs';
40
+ import { __resetCaches as __resetSkillDiscoverCaches } from '../cli/route/skill-discover.mjs';
26
41
  class ExitTrap extends Error {
27
42
  constructor(code) {
28
43
  super(`apt-tools cmd called process.exit(${code})`);
@@ -32,18 +47,26 @@ class ExitTrap extends Error {
32
47
  /**
33
48
  * @param {Function} cmdFn — the Layer 1 cmd function (sync or async).
34
49
  * @param {unknown[]} [args=[]] — argv-shaped positional args.
35
- * @param {{ strictExit?: boolean, env?: Record<string, string> }} [opts]
36
- * @returns {Promise<{ result: unknown, stdout: string, exitCode: number }>}
50
+ * @param {{ strictExit?: boolean, resetCaches?: boolean, env?: Record<string, string> }} [opts]
51
+ * @returns {Promise<{ result: unknown, stdout: string, stderr: string, exitCode: number }>}
37
52
  */
38
53
  export async function runCmd(cmdFn, args = [], opts = {}) {
39
- const { strictExit = true } = opts;
54
+ const { strictExit = true, resetCaches = true } = opts;
55
+ if (resetCaches) {
56
+ __resetSkillDiscoverCaches();
57
+ __resetAgentIdentityCaches();
58
+ }
40
59
  let trappedExit = null;
41
60
  const origExit = process.exit;
42
- // Save the unbound original — assignment to process.stdout.write replaces
61
+ // Save the unbound originals — assignment to process.stdout.write replaces
43
62
  // the property; restoration of the original reference returns the global
44
63
  // to byte-identical state (Function-identity check in self-tests).
45
64
  const origWrite = process.stdout.write;
65
+ const origErrWrite = process.stderr.write;
66
+ const origStdinIsTTY = process.stdin.isTTY;
67
+ const origStdoutIsTTY = process.stdout.isTTY;
46
68
  const stdoutBuf = [];
69
+ const stderrBuf = [];
47
70
  process.exit = (code) => {
48
71
  trappedExit = typeof code === 'number' ? code : 0;
49
72
  if (strictExit) {
@@ -59,6 +82,16 @@ export async function runCmd(cmdFn, args = [], opts = {}) {
59
82
  stdoutBuf.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf-8'));
60
83
  return true;
61
84
  };
85
+ process.stderr.write = (chunk, ..._rest) => {
86
+ stderrBuf.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf-8'));
87
+ return true;
88
+ };
89
+ // F3 subtask 1 (Q3): defensively force the non-interactive branch for any
90
+ // cmd that gates on isTTY (init.mjs:127,167,1013 + cmdState's TTY sidecar).
91
+ // Under vitest workers isTTY is usually `undefined`, but stubbing to `false`
92
+ // removes the Node-version drift risk.
93
+ process.stdin.isTTY = false;
94
+ process.stdout.isTTY = false;
62
95
  try {
63
96
  const result = await cmdFn(...args);
64
97
  const exitCode = trappedExit !== null
@@ -66,11 +99,16 @@ export async function runCmd(cmdFn, args = [], opts = {}) {
66
99
  : typeof result === 'object' && result !== null && typeof result.exitCode === 'number'
67
100
  ? result.exitCode
68
101
  : 0;
69
- return { result, stdout: stdoutBuf.join(''), exitCode };
102
+ return { result, stdout: stdoutBuf.join(''), stderr: stderrBuf.join(''), exitCode };
70
103
  }
71
104
  catch (e) {
72
105
  if (e instanceof ExitTrap) {
73
- return { result: null, stdout: stdoutBuf.join(''), exitCode: e.code };
106
+ return {
107
+ result: null,
108
+ stdout: stdoutBuf.join(''),
109
+ stderr: stderrBuf.join(''),
110
+ exitCode: e.code,
111
+ };
74
112
  }
75
113
  // Re-throw non-trap errors (including the strict-mode-violation Error
76
114
  // thrown above) so tests can assert via expect(...).rejects.
@@ -79,6 +117,9 @@ export async function runCmd(cmdFn, args = [], opts = {}) {
79
117
  finally {
80
118
  process.exit = origExit;
81
119
  process.stdout.write = origWrite;
120
+ process.stderr.write = origErrWrite;
121
+ process.stdin.isTTY = origStdinIsTTY;
122
+ process.stdout.isTTY = origStdoutIsTTY;
82
123
  }
83
124
  }
84
125
  //# sourceMappingURL=run-cmd.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-cmd.mjs","sourceRoot":"","sources":["../../src/__test-helpers/run-cmd.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,QAAS,SAAQ,KAAK;IAC3B,YAAY,IAAI;QACf,KAAK,CAAC,qCAAqC,IAAI,GAAG,CAAC,CAAA;QACnD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IACjB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE;IACvD,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IAElC,IAAI,WAAW,GAAG,IAAI,CAAA;IACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAA;IAC7B,0EAA0E;IAC1E,yEAAyE;IACzE,mEAAmE;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;IACtC,MAAM,SAAS,GAAG,EAAE,CAAA;IAEpB,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE;QACvB,WAAW,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QACjD,IAAI,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACd,gBAAgB,WAAW,iDAAiD;gBAC3E,uFAAuF;gBACvF,yFAAyF,CAC1F,CAAA;QACF,CAAC;QACD,kEAAkE;QAClE,sDAAsD;QACtD,MAAM,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAA;IAChC,CAAC,CAAA;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE;QAC1C,SAAS,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QACxF,OAAO,IAAI,CAAA;IACZ,CAAC,CAAA;IAED,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,CAAA;QACnC,MAAM,QAAQ,GACb,WAAW,KAAK,IAAI;YACnB,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBACrF,CAAC,CAAC,MAAM,CAAC,QAAQ;gBACjB,CAAC,CAAC,CAAC,CAAA;QACN,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;IACxD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACZ,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;YAC3B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACtE,CAAC;QACD,sEAAsE;QACtE,6DAA6D;QAC7D,MAAM,CAAC,CAAA;IACR,CAAC;YAAS,CAAC;QACV,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAA;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAA;IACjC,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"run-cmd.mjs","sourceRoot":"","sources":["../../src/__test-helpers/run-cmd.mjs"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"classification.d.mts","sourceRoot":"","sources":["../../../src/cli/artifacts/classification.mjs"],"names":[],"mappings":"AAuRA;;;;;;GAMG;AACH,wCAHa,SAAS,MAAM,EAAE,CAO7B;AAED;;;;;GAKG;AACH,sCAHa,SAAS,MAAM,EAAE,CAO7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,8CANW,MAAM,UAEN,EAAE,GACA,aAAa,GAAG,WAAW,GAAG,IAAI,CAW9C;AAED;;;;;;;GAOG;AACH,sDAJW,MAAM,GACJ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAalE;AAED;;;;;;GAMG;AACH,yCAJW,MAAM,EAAE,GACN,MAAM,EAAE,CAMpB;AAED;;;;;;GAMG;AACH,uCAJW,MAAM,EAAE,GACN,MAAM,EAAE,CAMpB;AA1VD;;;;;GAKG;AACH;;;GAGE"}
1
+ {"version":3,"file":"classification.d.mts","sourceRoot":"","sources":["../../../src/cli/artifacts/classification.mjs"],"names":[],"mappings":"AAiSA;;;;;;GAMG;AACH,wCAHa,SAAS,MAAM,EAAE,CAO7B;AAED;;;;;GAKG;AACH,sCAHa,SAAS,MAAM,EAAE,CAO7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,8CANW,MAAM,UAEN,EAAE,GACA,aAAa,GAAG,WAAW,GAAG,IAAI,CAW9C;AAED;;;;;;;GAOG;AACH,sDAJW,MAAM,GACJ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAalE;AAED;;;;;;GAMG;AACH,yCAJW,MAAM,EAAE,GACN,MAAM,EAAE,CAMpB;AAED;;;;;;GAMG;AACH,uCAJW,MAAM,EAAE,GACN,MAAM,EAAE,CAMpB;AApWD;;;;;GAKG;AACH;;;GAGE"}
@@ -171,6 +171,11 @@ const RULES = Object.freeze([
171
171
  class: ARTIFACT_CLASS.EPHEMERAL,
172
172
  why: 'Append-only daily log of lifecycle transitions.',
173
173
  },
174
+ {
175
+ pattern: '.aperant/install/**',
176
+ class: ARTIFACT_CLASS.EPHEMERAL,
177
+ why: 'Install telemetry/summaries (last-init/last-install) — runtime artifacts.',
178
+ },
174
179
  {
175
180
  pattern: '.aperant/team-status/**',
176
181
  class: ARTIFACT_CLASS.EPHEMERAL,
@@ -246,6 +251,11 @@ const RULES = Object.freeze([
246
251
  class: ARTIFACT_CLASS.EPHEMERAL,
247
252
  why: 'Design-scan outputs (tokens, extracted repo, synthesis) — rebuildable.',
248
253
  },
254
+ {
255
+ pattern: '.aperant/product-context.json',
256
+ class: ARTIFACT_CLASS.EPHEMERAL,
257
+ why: 'Derived/read-through sidecar used by CLI flows; rebuilt from onboarding context.',
258
+ },
249
259
  // ── Explicit ephemeral: secrets/tokens MUST never classify committable ─
250
260
  {
251
261
  pattern: '.aperant/secrets/**',