@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.
- package/CHANGELOG.md +61 -0
- package/README.md +64 -10
- package/agents/apt-improver.md +99 -0
- package/agents/apt-planner.md +115 -10
- package/dist/__test-helpers/run-cmd.d.mts +4 -2
- package/dist/__test-helpers/run-cmd.d.mts.map +1 -1
- package/dist/__test-helpers/run-cmd.mjs +56 -15
- package/dist/__test-helpers/run-cmd.mjs.map +1 -1
- package/dist/cli/artifacts/classification.d.mts.map +1 -1
- package/dist/cli/artifacts/classification.mjs +10 -0
- package/dist/cli/artifacts/classification.mjs.map +1 -1
- package/dist/cli/ci-watch/lock.d.mts +53 -0
- package/dist/cli/ci-watch/lock.d.mts.map +1 -0
- package/dist/cli/ci-watch/lock.mjs +172 -0
- package/dist/cli/ci-watch/lock.mjs.map +1 -0
- package/dist/cli/ci-watch/state.d.mts +36 -0
- package/dist/cli/ci-watch/state.d.mts.map +1 -0
- package/dist/cli/ci-watch/state.mjs +103 -0
- package/dist/cli/ci-watch/state.mjs.map +1 -0
- package/dist/cli/ci-watch/stop-matrix.d.mts +58 -0
- package/dist/cli/ci-watch/stop-matrix.d.mts.map +1 -0
- package/dist/cli/ci-watch/stop-matrix.mjs +164 -0
- package/dist/cli/ci-watch/stop-matrix.mjs.map +1 -0
- package/dist/cli/cli-wrappers/ci-watch.d.mts +2 -0
- package/dist/cli/cli-wrappers/ci-watch.d.mts.map +1 -0
- package/dist/cli/cli-wrappers/ci-watch.mjs +9 -0
- package/dist/cli/cli-wrappers/ci-watch.mjs.map +1 -0
- package/dist/cli/commands/adr.d.mts +5 -0
- package/dist/cli/commands/adr.d.mts.map +1 -0
- package/dist/cli/commands/adr.mjs +228 -0
- package/dist/cli/commands/adr.mjs.map +1 -0
- package/dist/cli/commands/ci-watch.d.mts +7 -0
- package/dist/cli/commands/ci-watch.d.mts.map +1 -0
- package/dist/cli/commands/ci-watch.mjs +465 -0
- package/dist/cli/commands/ci-watch.mjs.map +1 -0
- package/dist/cli/commands/context.d.mts +7 -0
- package/dist/cli/commands/context.d.mts.map +1 -0
- package/dist/cli/commands/context.mjs +224 -0
- package/dist/cli/commands/context.mjs.map +1 -0
- package/dist/cli/commands/event.d.mts.map +1 -1
- package/dist/cli/commands/event.mjs +59 -24
- package/dist/cli/commands/event.mjs.map +1 -1
- package/dist/cli/commands/host-detect.d.mts +1 -1
- package/dist/cli/commands/host-detect.d.mts.map +1 -1
- package/dist/cli/commands/host-detect.mjs +30 -3
- package/dist/cli/commands/host-detect.mjs.map +1 -1
- package/dist/cli/commands/init.d.mts.map +1 -1
- package/dist/cli/commands/init.mjs +73 -5
- package/dist/cli/commands/init.mjs.map +1 -1
- package/dist/cli/commands/modes.d.mts +13 -0
- package/dist/cli/commands/modes.d.mts.map +1 -0
- package/dist/cli/commands/modes.mjs +220 -0
- package/dist/cli/commands/modes.mjs.map +1 -0
- package/dist/cli/commands/pr-review-audit-fixer.d.mts +41 -2
- package/dist/cli/commands/pr-review-audit-fixer.d.mts.map +1 -1
- package/dist/cli/commands/pr-review-audit-fixer.mjs +91 -14
- package/dist/cli/commands/pr-review-audit-fixer.mjs.map +1 -1
- package/dist/cli/commands/route.d.mts.map +1 -1
- package/dist/cli/commands/route.mjs +11 -2
- package/dist/cli/commands/route.mjs.map +1 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +136 -6
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/commands/tokens.d.mts.map +1 -1
- package/dist/cli/commands/tokens.mjs +150 -6
- package/dist/cli/commands/tokens.mjs.map +1 -1
- package/dist/cli/commands/triage.d.mts +8 -0
- package/dist/cli/commands/triage.d.mts.map +1 -0
- package/dist/cli/commands/triage.mjs +259 -0
- package/dist/cli/commands/triage.mjs.map +1 -0
- package/dist/cli/config/post-merge-sweep.d.mts +18 -0
- package/dist/cli/config/post-merge-sweep.d.mts.map +1 -1
- package/dist/cli/config/post-merge-sweep.mjs +48 -3
- package/dist/cli/config/post-merge-sweep.mjs.map +1 -1
- package/dist/cli/consistency/registry.d.mts +11 -0
- package/dist/cli/consistency/registry.d.mts.map +1 -1
- package/dist/cli/consistency/registry.mjs +13 -0
- package/dist/cli/consistency/registry.mjs.map +1 -1
- package/dist/cli/coordination/agent-identity.d.mts +9 -0
- package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
- package/dist/cli/coordination/agent-identity.mjs +11 -0
- package/dist/cli/coordination/agent-identity.mjs.map +1 -1
- package/dist/cli/coordination/event-log.d.mts +27 -0
- package/dist/cli/coordination/event-log.d.mts.map +1 -1
- package/dist/cli/coordination/event-log.mjs +72 -2
- package/dist/cli/coordination/event-log.mjs.map +1 -1
- package/dist/cli/design/frontmatter-schema.d.mts +3 -3
- package/dist/cli/design/frontmatter-schema.d.mts.map +1 -1
- package/dist/cli/design/frontmatter-schema.mjs +3 -1
- package/dist/cli/design/frontmatter-schema.mjs.map +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +14 -1
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/gate/registry.d.mts +11 -0
- package/dist/cli/gate/registry.d.mts.map +1 -1
- package/dist/cli/gate/registry.mjs +13 -0
- package/dist/cli/gate/registry.mjs.map +1 -1
- package/dist/cli/help.d.mts.map +1 -1
- package/dist/cli/help.mjs +1 -0
- package/dist/cli/help.mjs.map +1 -1
- package/dist/cli/host/detect.d.mts +1 -0
- package/dist/cli/host/detect.d.mts.map +1 -1
- package/dist/cli/host/detect.mjs +5 -0
- package/dist/cli/host/detect.mjs.map +1 -1
- package/dist/cli/route/envelope.d.mts +68 -4
- package/dist/cli/route/envelope.d.mts.map +1 -1
- package/dist/cli/route/envelope.mjs +140 -103
- package/dist/cli/route/envelope.mjs.map +1 -1
- package/dist/cli/route/skill-discover.d.mts +11 -0
- package/dist/cli/route/skill-discover.d.mts.map +1 -1
- package/dist/cli/route/skill-discover.mjs +46 -1
- package/dist/cli/route/skill-discover.mjs.map +1 -1
- package/dist/cli/skill-author/contract.d.mts +20 -0
- package/dist/cli/skill-author/contract.d.mts.map +1 -1
- package/dist/cli/skill-author/contract.mjs +27 -0
- package/dist/cli/skill-author/contract.mjs.map +1 -1
- package/dist/cli/skill-author/skill-template.d.mts.map +1 -1
- package/dist/cli/skill-author/skill-template.mjs +4 -3
- package/dist/cli/skill-author/skill-template.mjs.map +1 -1
- package/dist/cli/task/worktree-cleanup.d.mts +9 -1
- package/dist/cli/task/worktree-cleanup.d.mts.map +1 -1
- package/dist/cli/task/worktree-cleanup.mjs +190 -9
- package/dist/cli/task/worktree-cleanup.mjs.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/agents/apt-planner.md +1 -1
- package/dist/plugin/skills/apt/SKILL.md +111 -5
- package/dist/plugin/skills/apt-author-skill/SKILL.md +11 -0
- package/dist/plugin/skills/apt-bootstrap/SKILL.md +1 -0
- package/dist/plugin/skills/apt-classify/SKILL.md +1 -0
- package/dist/plugin/skills/apt-close-task/SKILL.md +1 -0
- package/dist/plugin/skills/apt-create-docs/SKILL.md +1 -0
- package/dist/plugin/skills/apt-debug/SKILL.md +2 -0
- package/dist/plugin/skills/apt-design/SKILL.md +2 -0
- package/dist/plugin/skills/apt-discuss/SKILL.md +2 -0
- package/dist/plugin/skills/apt-docs/SKILL.md +2 -0
- package/dist/plugin/skills/apt-execute/SKILL.md +1 -0
- package/dist/plugin/skills/apt-mockup/SKILL.md +2 -0
- package/dist/plugin/skills/apt-pause/SKILL.md +1 -0
- package/dist/plugin/skills/apt-personas/SKILL.md +1 -0
- package/dist/plugin/skills/apt-plan/SKILL.md +2 -0
- package/dist/plugin/skills/apt-pr-review/SKILL.md +1 -0
- package/dist/plugin/skills/apt-quick/SKILL.md +2 -0
- package/dist/plugin/skills/apt-resume/SKILL.md +1 -0
- package/dist/plugin/skills/apt-review/SKILL.md +1 -0
- package/dist/plugin/skills/apt-roadmap/SKILL.md +1 -0
- package/dist/plugin/skills/apt-roundtable/SKILL.md +2 -0
- package/dist/plugin/skills/apt-run/SKILL.md +1 -0
- package/dist/plugin/skills/apt-scan/SKILL.md +1 -0
- package/dist/plugin/skills/apt-setup/SKILL.md +1 -0
- package/dist/plugin/skills/apt-ship/SKILL.md +6 -5
- package/dist/plugin/skills/apt-stress-test/SKILL.md +1 -0
- package/dist/plugin/skills/apt-terminal/SKILL.md +1 -0
- package/dist/plugin/skills/apt-update/SKILL.md +5 -0
- package/dist/plugin/skills/apt-verify/SKILL.md +1 -0
- package/dist/plugin/skills/apt-verify-proof/SKILL.md +1 -0
- package/dist/types/config.d.ts +85 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +125 -122
- package/prompts/coder.md +2 -0
- package/prompts/planner.md +12 -0
- package/prompts/spec_writer.md +9 -0
- package/skills/apt/SKILL.md +112 -5
- package/skills/apt-author-skill/SKILL.md +11 -0
- package/skills/apt-bootstrap/SKILL.md +1 -0
- package/skills/apt-classify/SKILL.md +1 -0
- package/skills/apt-close-task/SKILL.md +33 -1
- package/skills/apt-create-docs/SKILL.md +1 -0
- package/skills/apt-debug/SKILL.md +41 -6
- package/skills/apt-debug/appendices/diagnose-discipline.md +119 -0
- package/skills/apt-design/SKILL.md +2 -0
- package/skills/apt-diagram/SKILL.md +342 -0
- package/skills/apt-diagram/appendices/design-discipline.md +97 -0
- package/skills/apt-discuss/SKILL.md +27 -0
- package/skills/apt-discuss/appendices/grill-discipline.md +104 -0
- package/skills/apt-discuss/appendices/zoom-out-helper.md +79 -0
- package/skills/apt-docs/SKILL.md +2 -0
- package/skills/apt-execute/SKILL.md +49 -5
- package/skills/apt-execute/appendices/tdd-mode.md +107 -0
- package/skills/apt-improve/DEEPENING.md +84 -0
- package/skills/apt-improve/INTERFACE-DESIGN.md +97 -0
- package/skills/apt-improve/LANGUAGE.md +104 -0
- package/skills/apt-improve/SKILL.md +141 -0
- package/skills/apt-mockup/SKILL.md +2 -0
- package/skills/apt-pause/SKILL.md +1 -0
- package/skills/apt-personas/SKILL.md +1 -0
- package/skills/apt-plan/SKILL.md +149 -4
- package/skills/apt-planner.md +42 -1
- package/skills/apt-pr-review/SKILL.md +47 -16
- package/skills/apt-prototype/LOGIC.md +109 -0
- package/skills/apt-prototype/SKILL.md +143 -0
- package/skills/apt-prototype/UI.md +90 -0
- package/skills/apt-quick/SKILL.md +32 -0
- package/skills/apt-resume/SKILL.md +1 -0
- package/skills/apt-review/SKILL.md +3 -0
- package/skills/apt-roadmap/SKILL.md +1 -0
- package/skills/apt-roundtable/SKILL.md +2 -0
- package/skills/apt-run/SKILL.md +33 -4
- package/skills/apt-scan/SKILL.md +1 -0
- package/skills/apt-setup/SKILL.md +129 -2
- package/skills/apt-ship/SKILL.md +52 -4
- package/skills/apt-stress-test/SKILL.md +1 -0
- package/skills/apt-terminal/SKILL.md +1 -0
- package/skills/apt-triage/AGENT-BRIEF.md +84 -0
- package/skills/apt-triage/OUT-OF-SCOPE.md +75 -0
- package/skills/apt-triage/SKILL.md +169 -0
- package/skills/apt-update/SKILL.md +3 -0
- package/skills/apt-verify/SKILL.md +4 -0
- package/skills/apt-verify-proof/SKILL.md +4 -0
- package/skills/apt-watch-ci/SKILL.md +163 -0
- package/skills/apt-zoom-out/SKILL.md +130 -0
- package/src/cli/artifacts/classification.mjs +10 -0
- package/src/cli/ci-watch/lock.mjs +178 -0
- package/src/cli/ci-watch/state.mjs +103 -0
- package/src/cli/ci-watch/stop-matrix.mjs +181 -0
- package/src/cli/cli-wrappers/ci-watch.mjs +9 -0
- package/src/cli/commands/adr.mjs +243 -0
- package/src/cli/commands/ci-watch.mjs +503 -0
- package/src/cli/commands/context.mjs +244 -0
- package/src/cli/commands/event.mjs +63 -24
- package/src/cli/commands/host-detect.mjs +33 -7
- package/src/cli/commands/init.mjs +83 -5
- package/src/cli/commands/modes.mjs +215 -0
- package/src/cli/commands/pr-review-audit-fixer.mjs +95 -16
- package/src/cli/commands/route.mjs +11 -2
- package/src/cli/commands/task.mjs +152 -18
- package/src/cli/commands/tokens.mjs +157 -6
- package/src/cli/commands/triage.mjs +277 -0
- package/src/cli/config/post-merge-sweep.mjs +49 -3
- package/src/cli/consistency/registry.mjs +14 -0
- package/src/cli/coordination/agent-identity.mjs +12 -0
- package/src/cli/coordination/event-log.mjs +73 -2
- package/src/cli/design/frontmatter-schema.mjs +3 -1
- package/src/cli/dispatch.mjs +15 -1
- package/src/cli/gate/registry.mjs +14 -0
- package/src/cli/help.mjs +1 -0
- package/src/cli/host/detect.mjs +5 -0
- package/src/cli/route/envelope.mjs +140 -106
- package/src/cli/route/skill-discover.mjs +46 -1
- package/src/cli/skill-author/contract.mjs +29 -0
- package/src/cli/skill-author/skill-template.mjs +4 -3
- package/src/cli/task/worktree-cleanup.mjs +191 -9
- package/templates/adr-format.md +56 -0
- package/templates/config.json +4 -0
- 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
|
-
##
|
|
10
|
+
## Just type `/apt` — natural language routing
|
|
11
11
|
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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>
|
package/agents/apt-planner.md
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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": "
|
|
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
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
discouraged —
|
|
332
|
-
|
|
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":"
|
|
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
|
|
6
|
-
* try/finally restore),
|
|
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`
|
|
13
|
-
* effective exit code: the trapped exit code if process.exit was called,
|
|
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
|
|
23
|
-
*
|
|
24
|
-
*
|
|
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
|
|
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 {
|
|
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
|
|
1
|
+
{"version":3,"file":"run-cmd.mjs","sourceRoot":"","sources":["../../src/__test-helpers/run-cmd.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,aAAa,IAAI,0BAA0B,EAAE,MAAM,wCAAwC,CAAA;AACpG,OAAO,EAAE,aAAa,IAAI,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAE7F,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,WAAW,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IAEtD,IAAI,WAAW,EAAE,CAAC;QACjB,0BAA0B,EAAE,CAAA;QAC5B,0BAA0B,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI,WAAW,GAAG,IAAI,CAAA;IACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAA;IAC7B,2EAA2E;IAC3E,yEAAyE;IACzE,mEAAmE;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;IACtC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;IACzC,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAA;IAC1C,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;IAC5C,MAAM,SAAS,GAAG,EAAE,CAAA;IACpB,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,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,0EAA0E;IAC1E,4EAA4E;IAC5E,6EAA6E;IAC7E,uCAAuC;IACvC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAA;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;IAE5B,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,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAA;IACpF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACZ,IAAI,CAAC,YAAY,QAAQ,EAAE,CAAC;YAC3B,OAAO;gBACN,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,QAAQ,EAAE,CAAC,CAAC,IAAI;aAChB,CAAA;QACF,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;QAChC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,YAAY,CAAA;QACnC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,cAAc,CAAA;QACpC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,eAAe,CAAA;IACvC,CAAC;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classification.d.mts","sourceRoot":"","sources":["../../../src/cli/artifacts/classification.mjs"],"names":[],"mappings":"
|
|
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/**',
|