@aperant/framework 0.7.0 → 0.7.4
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 +205 -0
- package/agents/apt-planner.md +12 -0
- package/agents/apt-pr-review-fixer.md +13 -9
- package/bin/apt-tools.mjs +7 -0
- package/dist/cli/ci-watch/stop-matrix.d.mts.map +1 -1
- package/dist/cli/ci-watch/stop-matrix.mjs +16 -0
- package/dist/cli/ci-watch/stop-matrix.mjs.map +1 -1
- package/dist/cli/commands/ci-watch.d.mts +11 -0
- package/dist/cli/commands/ci-watch.d.mts.map +1 -1
- package/dist/cli/commands/ci-watch.mjs +108 -2
- package/dist/cli/commands/ci-watch.mjs.map +1 -1
- package/dist/cli/commands/features-audit.d.mts +24 -0
- package/dist/cli/commands/features-audit.d.mts.map +1 -1
- package/dist/cli/commands/features-audit.mjs +159 -5
- package/dist/cli/commands/features-audit.mjs.map +1 -1
- package/dist/cli/commands/health-check.d.mts +16 -0
- package/dist/cli/commands/health-check.d.mts.map +1 -1
- package/dist/cli/commands/health-check.mjs +118 -2
- package/dist/cli/commands/health-check.mjs.map +1 -1
- package/dist/cli/commands/init.d.mts +9 -0
- package/dist/cli/commands/init.d.mts.map +1 -1
- package/dist/cli/commands/init.mjs +49 -4
- package/dist/cli/commands/init.mjs.map +1 -1
- package/dist/cli/commands/modes.d.mts.map +1 -1
- package/dist/cli/commands/modes.mjs +11 -0
- package/dist/cli/commands/modes.mjs.map +1 -1
- package/dist/cli/commands/pr-review-audit-fixer.d.mts +13 -0
- package/dist/cli/commands/pr-review-audit-fixer.d.mts.map +1 -1
- package/dist/cli/commands/pr-review-audit-fixer.mjs +18 -5
- package/dist/cli/commands/pr-review-audit-fixer.mjs.map +1 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +84 -5
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/commands/validate-evidence.d.mts +24 -2
- package/dist/cli/commands/validate-evidence.d.mts.map +1 -1
- package/dist/cli/commands/validate-evidence.mjs +154 -17
- package/dist/cli/commands/validate-evidence.mjs.map +1 -1
- package/dist/cli/commands/vitest-doctor.d.mts +2 -0
- package/dist/cli/commands/vitest-doctor.d.mts.map +1 -0
- package/dist/cli/commands/vitest-doctor.mjs +168 -0
- package/dist/cli/commands/vitest-doctor.mjs.map +1 -0
- package/dist/cli/config/gitignore-drift.d.mts +23 -1
- package/dist/cli/config/gitignore-drift.d.mts.map +1 -1
- package/dist/cli/config/gitignore-drift.mjs +81 -3
- package/dist/cli/config/gitignore-drift.mjs.map +1 -1
- package/dist/cli/config/load.d.mts +56 -2
- package/dist/cli/config/load.d.mts.map +1 -1
- package/dist/cli/config/load.mjs +192 -2
- package/dist/cli/config/load.mjs.map +1 -1
- package/dist/cli/consistency/parse-review.mjs +7 -0
- package/dist/cli/consistency/parse-review.mjs.map +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +24 -2
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/gate/gates/gitignore-in-sync.d.mts +1 -1
- package/dist/cli/gate/gates/gitignore-in-sync.d.mts.map +1 -1
- package/dist/cli/gate/gates/gitignore-in-sync.mjs +5 -2
- package/dist/cli/gate/gates/gitignore-in-sync.mjs.map +1 -1
- package/dist/cli/gate/gates/review-clean.d.mts +5 -1
- package/dist/cli/gate/gates/review-clean.d.mts.map +1 -1
- package/dist/cli/gate/gates/review-clean.mjs +23 -18
- package/dist/cli/gate/gates/review-clean.mjs.map +1 -1
- package/dist/cli/gate/gates/verify-approved.d.mts +49 -1
- package/dist/cli/gate/gates/verify-approved.d.mts.map +1 -1
- package/dist/cli/gate/gates/verify-approved.mjs +93 -14
- package/dist/cli/gate/gates/verify-approved.mjs.map +1 -1
- package/dist/cli/help.d.mts.map +1 -1
- package/dist/cli/help.mjs +7 -2
- package/dist/cli/help.mjs.map +1 -1
- package/dist/cli/install/runtime-detect.d.mts +13 -0
- package/dist/cli/install/runtime-detect.d.mts.map +1 -1
- package/dist/cli/install/runtime-detect.mjs +9 -0
- package/dist/cli/install/runtime-detect.mjs.map +1 -1
- package/dist/cli/task/index-md.d.mts.map +1 -1
- package/dist/cli/task/index-md.mjs +14 -2
- package/dist/cli/task/index-md.mjs.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +11 -2
- package/dist/plugin/agents/apt-improver.md +99 -0
- package/dist/plugin/agents/apt-planner.md +127 -10
- package/dist/plugin/agents/apt-pr-review-fixer.md +13 -9
- package/dist/plugin/skills/apt/SKILL.md +1 -0
- package/dist/plugin/skills/apt-close-task/SKILL.md +63 -1
- package/dist/plugin/skills/apt-debug/SKILL.md +39 -6
- package/dist/plugin/skills/apt-debug/appendices/diagnose-discipline.md +119 -0
- package/dist/plugin/skills/apt-diagram/SKILL.md +378 -0
- package/dist/plugin/skills/apt-diagram/appendices/design-discipline.md +97 -0
- package/dist/plugin/skills/apt-discuss/SKILL.md +72 -5
- package/dist/plugin/skills/apt-discuss/appendices/grill-discipline.md +104 -0
- package/dist/plugin/skills/apt-discuss/appendices/zoom-out-helper.md +79 -0
- package/dist/plugin/skills/apt-execute/SKILL.md +57 -5
- package/dist/plugin/skills/apt-execute/appendices/tdd-mode.md +107 -0
- package/dist/plugin/skills/apt-improve/DEEPENING.md +84 -0
- package/dist/plugin/skills/apt-improve/INTERFACE-DESIGN.md +97 -0
- package/dist/plugin/skills/apt-improve/LANGUAGE.md +104 -0
- package/dist/plugin/skills/apt-improve/SKILL.md +141 -0
- package/dist/plugin/skills/apt-plan/SKILL.md +171 -4
- package/dist/plugin/skills/apt-plan/adapters/conductor.md +98 -0
- package/dist/plugin/skills/apt-pr-review/SKILL.md +57 -18
- package/dist/plugin/skills/apt-prototype/LOGIC.md +109 -0
- package/dist/plugin/skills/apt-prototype/SKILL.md +143 -0
- package/dist/plugin/skills/apt-prototype/UI.md +90 -0
- package/dist/plugin/skills/apt-quick/SKILL.md +49 -8
- package/dist/plugin/skills/apt-release-notes/SKILL.md +193 -0
- package/dist/plugin/skills/apt-release-notes/appendices/persona-voice.md +59 -0
- package/dist/plugin/skills/apt-review/SKILL.md +2 -0
- package/dist/plugin/skills/apt-run/SKILL.md +32 -4
- package/dist/plugin/skills/apt-setup/SKILL.md +308 -6
- package/dist/plugin/skills/apt-ship/SKILL.md +122 -1
- package/dist/plugin/skills/apt-spar/SKILL.md +315 -0
- package/dist/plugin/skills/apt-triage/AGENT-BRIEF.md +84 -0
- package/dist/plugin/skills/apt-triage/OUT-OF-SCOPE.md +75 -0
- package/dist/plugin/skills/apt-triage/SKILL.md +169 -0
- package/dist/plugin/skills/apt-update/SKILL.md +77 -10
- package/dist/plugin/skills/apt-verify/SKILL.md +3 -0
- package/dist/plugin/skills/apt-verify-proof/SKILL.md +10 -5
- package/dist/plugin/skills/apt-watch-ci/SKILL.md +166 -0
- package/dist/plugin/skills/apt-zoom-out/SKILL.md +130 -0
- package/package.json +1 -1
- package/prompts/conductor-framework-context.md +63 -0
- package/prompts/conductor-system.md +11 -0
- package/skills/apt-close-task/SKILL.md +1 -0
- package/skills/apt-discuss/SKILL.md +47 -5
- package/skills/apt-execute/SKILL.md +9 -0
- package/skills/apt-plan/SKILL.md +12 -0
- package/skills/apt-pr-review/SKILL.md +19 -3
- package/skills/apt-quick/SKILL.md +19 -8
- package/skills/apt-researcher.md +1 -0
- package/skills/apt-setup/SKILL.md +33 -2
- package/skills/apt-verify-proof/SKILL.md +7 -5
- package/src/cli/ci-watch/stop-matrix.mjs +17 -0
- package/src/cli/commands/ci-watch.mjs +113 -2
- package/src/cli/commands/features-audit.mjs +164 -5
- package/src/cli/commands/health-check.mjs +115 -2
- package/src/cli/commands/init.mjs +52 -4
- package/src/cli/commands/modes.mjs +11 -0
- package/src/cli/commands/pr-review-audit-fixer.mjs +18 -5
- package/src/cli/commands/task.mjs +83 -5
- package/src/cli/commands/validate-evidence.mjs +158 -17
- package/src/cli/commands/vitest-doctor.mjs +173 -0
- package/src/cli/config/gitignore-drift.mjs +74 -3
- package/src/cli/config/load.mjs +188 -2
- package/src/cli/consistency/parse-review.mjs +6 -0
- package/src/cli/dispatch.mjs +23 -2
- package/src/cli/gate/gates/gitignore-in-sync.mjs +5 -2
- package/src/cli/gate/gates/review-clean.mjs +24 -19
- package/src/cli/gate/gates/verify-approved.mjs +97 -14
- package/src/cli/help.mjs +7 -2
- package/src/cli/install/runtime-detect.mjs +9 -0
- package/src/cli/task/index-md.mjs +15 -2
- package/templates/config.json +2 -7
- package/workflows/verify-proof.md +8 -3
|
@@ -257,7 +257,7 @@ When the result is `unknown`, treat it as `external` for safety and prompt the u
|
|
|
257
257
|
Authorship could not be auto-detected for PR #${PR_NUMBER}. Treat as [owned / external]? (default: external)
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
-
If `autonomy_level >= 3` (yolo), skip the prompt and lock in `external`. Persist the user's answer to
|
|
260
|
+
If `autonomy_level >= 3` (yolo), skip the prompt and lock in `external`. Persist the user's answer to `pr-state.json:authorship` so subsequent rounds don't re-ask. (Per C56 A3 — authorship overrides moved from `config.json:pr_review.authorship_overrides` to per-PR `pr-state.json` so they GC with the pr-review round. Legacy `config.json` entries are still read with a deprecation warning + auto-promoted to pr-state on next `init-pr`; do NOT write to `config.json` from new code.)
|
|
261
261
|
|
|
262
262
|
Store the result as `AUTHORSHIP_MODE` and use it as a gate at every later phase:
|
|
263
263
|
|
|
@@ -1195,6 +1195,12 @@ Take all confirmed, fixable findings and group them into up to 3 independent gro
|
|
|
1195
1195
|
|
|
1196
1196
|
#### Step 3: Spawn Fix Agents
|
|
1197
1197
|
|
|
1198
|
+
**Capture the iteration-start SHA BEFORE spawning fixers** (used by both the Step 4b audit gate AND the per-fixer Pre-Return Self-Audit added in BUG-016 — fixers now commit atomically per finding, and the audit window is scoped by this SHA):
|
|
1199
|
+
|
|
1200
|
+
```bash
|
|
1201
|
+
ITERATION_START_SHA=$(cd "${WORKTREE_PATH}" && git rev-parse HEAD)
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1198
1204
|
For each fix group, spawn a fix agent. Read the agent definition from `.claude/agents/apt-pr-review-fixer.md` and fill in:
|
|
1199
1205
|
|
|
1200
1206
|
| Placeholder | Value |
|
|
@@ -1207,6 +1213,7 @@ For each fix group, spawn a fix agent. Read the agent definition from `.claude/a
|
|
|
1207
1213
|
| `[CRITICAL_APPROVAL]` | `true` or `false` for each critical finding in this group |
|
|
1208
1214
|
| `[PARALLEL_FIXERS]` | `true` if more than 1 fixer is spawned this iteration |
|
|
1209
1215
|
| `[WORKTREE_PATH]` | The worktree path — fix agents edit files HERE, not in the user's working directory |
|
|
1216
|
+
| `[ITERATION_START_SHA]` | The SHA captured BEFORE spawning fixers (see Step 4b's `ITERATION_START_SHA=$(...)` capture). Required for BUG-016 commit-discipline Pre-Return Self-Audit. |
|
|
1210
1217
|
|
|
1211
1218
|
```
|
|
1212
1219
|
Agent(
|
|
@@ -1260,7 +1267,9 @@ If `--since-sha` is **omitted**, the CLI falls back to `git merge-base HEAD orig
|
|
|
1260
1267
|
|
|
1261
1268
|
Rule of thumb: pass `--since-sha "${ITERATION_START_SHA}"` on every audit invocation. The merge-base fallback exists only so a missing flag doesn't flip every standard-branch-workflow repo into a false-positive hallucination — it is NOT a replacement for the explicit flag.
|
|
1262
1269
|
|
|
1263
|
-
The CLI returns a JSON envelope with `verdict` ∈ `verified | hallucinated | skipped`, writes `iterations/${ITERATION}/audit.json` (append-only), and bumps `metadata.json.fixer_hallucinations_total` on every `hallucinated` outcome. The envelope's `observed.since_sha` + `observed.since_sha_source` fields record which SHA was used and where it came from (`flag` | `merge-base` | `null`). The same envelope is used for the fixer and the self-reviewer (Phase 7) — `--fixer self-reviewer` reads from `self-review.md
|
|
1270
|
+
The CLI returns a JSON envelope with `verdict` ∈ `verified | hallucinated | skipped`, writes `iterations/${ITERATION}/audit.json` (append-only), and bumps `metadata.json.fixer_hallucinations_total` on every `hallucinated` outcome. The envelope's `observed.since_sha` + `observed.since_sha_source` fields record which SHA was used and where it came from (`flag` | `merge-base` | `null`). The same envelope is used for the fixer and the self-reviewer (Phase 7) — `--fixer self-reviewer` reads from `self-review.md`.
|
|
1271
|
+
|
|
1272
|
+
**Canonical fix-report filename per fixer (BUG-030):** each fixer agent writes to `fixes-applied-${FIXER_NAME}.md` (e.g. `fixes-applied-fixer-1.md`). The audit CLI resolves candidates in strict order: `fixes-applied-group{N}.md` (legacy group-named, pre-BUG-030 reviews) → `fixes-applied-fixer-{N}.md` (NEW fixer-named) → `fixes-applied-${FIXER_NAME}.md` (exact match, preferred for non-numeric fixer names) → `fixes-applied.md` (legacy unscoped, single-fixer reviews only). Writing the canonical name eliminates the cross-fixer false-positive `hallucinated` verdict that fired when two parallel fixers shared `fixes-applied.md`.
|
|
1264
1273
|
|
|
1265
1274
|
| Verdict | Orchestrator Action |
|
|
1266
1275
|
|---------|---------------------|
|
|
@@ -1454,33 +1463,63 @@ node packages/framework/bin/apt-tools.mjs workflow advance . --id ${REVIEW_ID} -
|
|
|
1454
1463
|
|
|
1455
1464
|
If `WORKTREE_PATH != .` AND fixes were applied in Phase 6/7:
|
|
1456
1465
|
|
|
1466
|
+
Get the PR head ref (for branch reviews, use the branch name directly):
|
|
1457
1467
|
```bash
|
|
1458
|
-
|
|
1468
|
+
PR_HEAD_REF=$(gh pr view ${PR_NUMBER} --json headRefName -q .headRefName)
|
|
1469
|
+
```
|
|
1459
1470
|
|
|
1460
|
-
|
|
1461
|
-
git add -A
|
|
1462
|
-
git commit -m "fix: auto-fix review findings from /apt:pr-review (review ${REVIEW_ID})"
|
|
1471
|
+
#### Confirmation gate (BUG-009 fix)
|
|
1463
1472
|
|
|
1464
|
-
|
|
1465
|
-
# For PRs: push to the PR's head ref
|
|
1466
|
-
git push origin HEAD:${PR_HEAD_REF}
|
|
1473
|
+
Whether the push prompts for confirmation is controlled by `pr_review.confirm_before_push` in `.aperant/config.json` (tri-state: `ask` | `auto` | `never`; default when absent: `auto` at autonomy ≥ 2, `ask` at autonomy < 2). Mirrors the `pr_review.suggest_after_ship` precedent in `/apt:ship` Section 7.1 — `ask` is honest about the irreversible-ish nature of the push (re-triggers CI on origin, visible to teammates); `auto` honors yolo pipelines.
|
|
1467
1474
|
|
|
1468
|
-
|
|
1475
|
+
```bash
|
|
1476
|
+
confirm_mode=$(jq -r '.pr_review.confirm_before_push // empty' .aperant/config.json)
|
|
1477
|
+
autonomy=$(jq -r '.autonomy.default // 2' .aperant/config.json)
|
|
1478
|
+
if [ -z "$confirm_mode" ]; then
|
|
1479
|
+
if [ "${autonomy}" -ge 2 ]; then confirm_mode="auto"; else confirm_mode="ask"; fi
|
|
1480
|
+
fi
|
|
1469
1481
|
```
|
|
1470
1482
|
|
|
1471
|
-
|
|
1483
|
+
Branch on `confirm_mode`:
|
|
1484
|
+
|
|
1485
|
+
- **`never`** — Skip push entirely. Print "fixes left in worktree; push manually with `git -C ${WORKTREE_PATH} push origin HEAD:${PR_HEAD_REF}`". Proceed to Step 0b cleanup.
|
|
1486
|
+
- **`auto`** — Proceed silently to the catch-all + push below. No prompt.
|
|
1487
|
+
- **`ask`** — Emit the structured question: `Fixes are ready in the worktree. Push to ${PR_HEAD_REF}? (y/n)`. On `n` or any non-`y`: same skip behavior as `never`. On `y` (or empty enter): proceed.
|
|
1488
|
+
|
|
1489
|
+
`confirm_before_push` is purely additive — it does not affect `authorship_override`, `authorship_overrides`, `max_rounds`, or `suggest_after_ship` in the same `pr_review` block.
|
|
1490
|
+
|
|
1491
|
+
#### Catch-all + push (BUG-010 fix)
|
|
1492
|
+
|
|
1493
|
+
The fixer pipeline normally produces atomic per-finding commits, so the worktree is clean by the time Step 0 runs. The catch-all commit below exists ONLY to capture uncommitted residue (rare — e.g. a fixer's pre-return self-audit failed to detect a stray edit). Guard it before committing:
|
|
1494
|
+
|
|
1472
1495
|
```bash
|
|
1473
|
-
|
|
1474
|
-
```
|
|
1496
|
+
cd ${WORKTREE_PATH}
|
|
1475
1497
|
|
|
1476
|
-
|
|
1498
|
+
# Guard 1: skip the catch-all entirely if the tree is clean.
|
|
1499
|
+
# Per-finding commits with proper messages are strictly better history than a single catch-all.
|
|
1500
|
+
if ! git diff --quiet || ! git diff --cached --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
|
1501
|
+
# Guard 2: explicit allowlist instead of `git add -A`.
|
|
1502
|
+
# `git add -A` would sweep orchestrator-level Read/Write side-effects
|
|
1503
|
+
# (metadata.json, audit.json, validated.md, etc.) into the PR. Bad.
|
|
1504
|
+
# Stage ONLY files in the review's touched set, computed from the iteration diffs.
|
|
1505
|
+
REVIEW_TOUCHED=$(git diff --name-only ${ITERATION_START_SHA:-HEAD~4}..HEAD 2>/dev/null \
|
|
1506
|
+
| grep -v '^\.aperant/' \
|
|
1507
|
+
| tr '\n' ' ')
|
|
1508
|
+
if [ -n "$REVIEW_TOUCHED" ]; then
|
|
1509
|
+
# shellcheck disable=SC2086
|
|
1510
|
+
git add -- $REVIEW_TOUCHED
|
|
1511
|
+
fi
|
|
1512
|
+
# Only commit if `git add --` actually staged something.
|
|
1513
|
+
if ! git diff --cached --quiet; then
|
|
1514
|
+
git commit -m "fix: auto-fix review findings from /apt:pr-review (review ${REVIEW_ID})"
|
|
1515
|
+
fi
|
|
1516
|
+
fi
|
|
1477
1517
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
Fixes are ready in the worktree. Push to ${PR_HEAD_REF}? (y/n)
|
|
1518
|
+
git push origin HEAD:${PR_HEAD_REF}
|
|
1519
|
+
cd -
|
|
1481
1520
|
```
|
|
1482
1521
|
|
|
1483
|
-
|
|
1522
|
+
Two guards. The outer `if` skips the whole catch-all path when the tree is clean. The inner allowlist (filter to files in the iteration-diff scope, minus anything under `.aperant/`) prevents `git add` from sweeping arbitrary orchestrator side-effects into the PR. Both guards default to the safe no-op shape on the happy path (fixers committed atomically, clean tree).
|
|
1484
1523
|
|
|
1485
1524
|
### Step 0b: Cleanup Worktree
|
|
1486
1525
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Adapted from Matt Pocock's MIT-licensed skill suite:
|
|
3
|
+
https://github.com/mattpocock/skills/blob/main/skills/engineering/prototype/LOGIC.md
|
|
4
|
+
Licensed under MIT. Modifications: scoped to terminal-app prototypes
|
|
5
|
+
that validate state machines, protocols, and control flow. Aligned with
|
|
6
|
+
the 5 universal rules in apt-prototype/SKILL.md.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# LOGIC branch — Terminal app for state-machine validation
|
|
10
|
+
|
|
11
|
+
When the user's question is about **behavior**, the prototype is a
|
|
12
|
+
single terminal app that the user runs and watches. The output prints
|
|
13
|
+
every state transition so the user can FEEL whether the logic works,
|
|
14
|
+
not just reason about it.
|
|
15
|
+
|
|
16
|
+
## When this branch fires
|
|
17
|
+
|
|
18
|
+
Question types that route here:
|
|
19
|
+
|
|
20
|
+
- "Does this state machine work?"
|
|
21
|
+
- "Does this control flow handle edge case X?"
|
|
22
|
+
- "Can this protocol handle out-of-order messages?"
|
|
23
|
+
- "What does the worker pool do under back-pressure?"
|
|
24
|
+
- "Does this retry policy actually converge?"
|
|
25
|
+
|
|
26
|
+
Question types that DO NOT route here (use UI branch instead):
|
|
27
|
+
|
|
28
|
+
- "Does this UI shape feel right?"
|
|
29
|
+
- "Is this flow discoverable?"
|
|
30
|
+
- "Does this layout work on mobile?"
|
|
31
|
+
|
|
32
|
+
## File shape
|
|
33
|
+
|
|
34
|
+
ONE file. Pick the project's primary runtime (TypeScript via `tsx`,
|
|
35
|
+
JavaScript via `node`, Python via `python3`, etc.). The shape:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
// THROWAWAY PROTOTYPE — do not merge, do not extend, do not test.
|
|
39
|
+
// Question: "{verbatim question from user}"
|
|
40
|
+
// Decision criterion: "{what does 'yes' look like? what does 'no' look like?}"
|
|
41
|
+
|
|
42
|
+
// --- State machine model ---
|
|
43
|
+
// {Declare states, transitions, and any guards.}
|
|
44
|
+
|
|
45
|
+
// --- Transition driver ---
|
|
46
|
+
// {A function that takes (currentState, event) and returns nextState,
|
|
47
|
+
// PRINTING every transition so the user can see what's happening.}
|
|
48
|
+
|
|
49
|
+
// --- Scripted run ---
|
|
50
|
+
// {5-10 sequential transitions that exercise the interesting paths.}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Single-command invocation
|
|
54
|
+
|
|
55
|
+
The prototype runs with ONE command. Examples:
|
|
56
|
+
|
|
57
|
+
- `node prototype.mjs` — no transpile, no build, no install
|
|
58
|
+
- `pnpm dlx tsx prototype.ts` — uses dlx so no dependency added to the project
|
|
59
|
+
- `python3 prototype.py` — no virtualenv setup
|
|
60
|
+
|
|
61
|
+
If your prototype needs any of: webpack, vite, esbuild, a database
|
|
62
|
+
connection, an environment variable — you are prototyping the wrong
|
|
63
|
+
question. Re-scope to the BEHAVIOR question; the infrastructure is a
|
|
64
|
+
separate concern.
|
|
65
|
+
|
|
66
|
+
## Surface-state-transparently — concrete examples
|
|
67
|
+
|
|
68
|
+
A terminal app prints state transitions inline:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
[T+0] state=IDLE
|
|
72
|
+
[T+1] event=user.click.submit → state=SUBMITTING
|
|
73
|
+
[T+2] event=network.timeout → state=RETRYING (attempt 1)
|
|
74
|
+
[T+3] event=network.timeout → state=RETRYING (attempt 2)
|
|
75
|
+
[T+4] event=network.timeout → state=FAILED (exceeded retries)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The user reads this output and either says "yes that's what I wanted"
|
|
79
|
+
or "no, the retry policy needs jitter" — and the question is answered
|
|
80
|
+
in 30 seconds of looking, not 3 hours of staring at a flowchart.
|
|
81
|
+
|
|
82
|
+
If the state machine has parallel regions or hierarchical states, print
|
|
83
|
+
the full state vector at each transition, not just the leaf state.
|
|
84
|
+
|
|
85
|
+
## When the scripted run isn't enough
|
|
86
|
+
|
|
87
|
+
If the user needs to drive the state machine interactively (the
|
|
88
|
+
question is "what happens when I hit submit twice quickly?"), add a
|
|
89
|
+
tiny REPL loop:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
> submit
|
|
93
|
+
[T+1] event=user.click.submit → state=SUBMITTING
|
|
94
|
+
> submit
|
|
95
|
+
[T+2] event=user.click.submit (REJECTED — already submitting)
|
|
96
|
+
[T+2] state=SUBMITTING
|
|
97
|
+
> timeout
|
|
98
|
+
[T+3] event=network.timeout → state=RETRYING (attempt 1)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Keep the REPL parser dumb (split on space, no quoting, no escape
|
|
102
|
+
handling). The user isn't testing your parser; they're testing the
|
|
103
|
+
state machine.
|
|
104
|
+
|
|
105
|
+
## Throwaway discipline reminder
|
|
106
|
+
|
|
107
|
+
When the question is answered, delete the prototype file. Do not let it
|
|
108
|
+
linger as "documentation of the design decision" — that's what
|
|
109
|
+
`apt-tools adr write` or `.aperant/context/notes/` are for.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apt:prototype
|
|
3
|
+
description: "Question-driven throwaway prototyping with 5-rule discipline — LOGIC branch (terminal-app for state-machine validation) and UI branch (delegates to apt:mockup)"
|
|
4
|
+
apt-skill-version: {{APT_VERSION}}
|
|
5
|
+
stage: design
|
|
6
|
+
intent: design
|
|
7
|
+
when_to_use: "The user has a question that wants a runnable prototype rather than a plan — 'does this state machine work?' (LOGIC branch) or 'does this UI shape feel right?' (UI branch). Throwaway code by design; do NOT confuse this with apt:plan or apt:execute."
|
|
8
|
+
user_invocable: true
|
|
9
|
+
internal: false
|
|
10
|
+
spawns_agent: false
|
|
11
|
+
agent_name: null
|
|
12
|
+
task_context: create-new
|
|
13
|
+
default_track: STANDARD
|
|
14
|
+
default_execution_mode: step
|
|
15
|
+
execution_modes:
|
|
16
|
+
- auto
|
|
17
|
+
- step
|
|
18
|
+
allowed-tools: "Bash, Read, Write, Edit, Grep, Glob"
|
|
19
|
+
argument-hint: "apt:prototype [question]"
|
|
20
|
+
gates: []
|
|
21
|
+
config_keys:
|
|
22
|
+
- coding.prototype_discipline
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Prototype — Question-Driven Throwaway Code
|
|
26
|
+
|
|
27
|
+
This skill ships throwaway code that answers ONE question. It is NOT a
|
|
28
|
+
planning artifact, NOT a feature, and NOT something to merge. The output
|
|
29
|
+
is a single-command-runnable prototype that lets the user feel whether
|
|
30
|
+
the question's answer is "yes" or "no", then gets thrown away.
|
|
31
|
+
|
|
32
|
+
**Pocock adoption attribution.** Discipline ported from Matt Pocock's
|
|
33
|
+
MIT-licensed `prototype` skill. Routes between two branches by
|
|
34
|
+
question-type; the UI branch delegates to Aperant's existing
|
|
35
|
+
`/apt:mockup` skill for HTML+Tailwind variants. The LOGIC branch and
|
|
36
|
+
the 5-rule discipline are new for Aperant.
|
|
37
|
+
|
|
38
|
+
## When to Use
|
|
39
|
+
|
|
40
|
+
- The user asks a question (not a "build me X" request) — "does this
|
|
41
|
+
state machine work?", "does this UI shape feel right?", "would users
|
|
42
|
+
find this discoverable?"
|
|
43
|
+
- A throwaway prototype is the cheapest answer (cheaper than designing,
|
|
44
|
+
planning, building, then discovering the answer was "no")
|
|
45
|
+
- The answer can be felt by running the prototype, not just reasoning
|
|
46
|
+
about it
|
|
47
|
+
|
|
48
|
+
## When NOT to Use
|
|
49
|
+
|
|
50
|
+
- The user has a feature request — use `/apt:plan` + `/apt:execute`
|
|
51
|
+
- The user wants a polished mockup to share — use `/apt:mockup` directly
|
|
52
|
+
(the UI branch of this skill delegates there anyway)
|
|
53
|
+
- The user wants production code with tests — that's TDD-mode
|
|
54
|
+
`/apt:execute --tdd`, not a prototype
|
|
55
|
+
|
|
56
|
+
## Branch routing
|
|
57
|
+
|
|
58
|
+
Inspect the user's question:
|
|
59
|
+
|
|
60
|
+
- **LOGIC branch** — triggers: "does this state machine work?", "does
|
|
61
|
+
this control flow handle edge case X?", "can this protocol handle
|
|
62
|
+
out-of-order messages?". Answer: a single-file terminal app the user
|
|
63
|
+
can run with one command to feel the state transitions.
|
|
64
|
+
- **UI branch** — triggers: "does this UI shape feel right?", "is this
|
|
65
|
+
flow discoverable?", "does this layout work on mobile?". Answer:
|
|
66
|
+
delegate to `/apt:mockup --variants 3` for HTML+Tailwind parallel
|
|
67
|
+
variants.
|
|
68
|
+
|
|
69
|
+
If the question is genuinely ambiguous, ask ONE clarifying question
|
|
70
|
+
("are you asking about behavior or appearance?") — do NOT enter a long
|
|
71
|
+
interview.
|
|
72
|
+
|
|
73
|
+
## The 5 Universal Rules (Pocock discipline, applies to both branches)
|
|
74
|
+
|
|
75
|
+
These five rules apply to EVERY prototype this skill produces. They are
|
|
76
|
+
load-bearing — violating them collapses the prototype into ceremony
|
|
77
|
+
disguised as a question.
|
|
78
|
+
|
|
79
|
+
1. **Throwaway-marked.** Every prototype file MUST carry a top-of-file
|
|
80
|
+
comment: `// THROWAWAY PROTOTYPE — do not merge, do not extend, do
|
|
81
|
+
not test.` This is not optional. Files without this marker drift into
|
|
82
|
+
production code and the question never gets answered cleanly.
|
|
83
|
+
|
|
84
|
+
2. **Single-command-run.** The prototype runs with ONE command. No
|
|
85
|
+
build step. No dependency install. `node prototype.mjs` or `pnpm dlx
|
|
86
|
+
tsx prototype.ts` or `bash prototype.sh` — pick one and stop. If you
|
|
87
|
+
reach for webpack, you're prototyping a build, not the question.
|
|
88
|
+
|
|
89
|
+
3. **No-persistence-default.** The prototype does NOT touch any
|
|
90
|
+
persistent store (libSQL, Convex, localStorage, .aperant/state.json).
|
|
91
|
+
Everything is in-memory. If persistence is part of the question,
|
|
92
|
+
explicitly opt in via a tmpfile — never the project's actual stores.
|
|
93
|
+
|
|
94
|
+
4. **Skip-polish.** No error handling for impossible scenarios. No
|
|
95
|
+
accessibility audit. No mobile responsive breakpoints unless the
|
|
96
|
+
question is about mobile. No animation refinement. Polish is what
|
|
97
|
+
you do AFTER the prototype answered "yes"; doing it now obscures
|
|
98
|
+
whether the answer was actually "yes".
|
|
99
|
+
|
|
100
|
+
5. **Surface-state-transparently.** The prototype prints / renders its
|
|
101
|
+
internal state at every step the user might want to inspect. A
|
|
102
|
+
terminal app prints every state transition. A UI prototype shows
|
|
103
|
+
the data shape next to the rendered output. The user must be able
|
|
104
|
+
to SEE what's happening — they can't feel an answer to "does this
|
|
105
|
+
work" if the state is hidden.
|
|
106
|
+
|
|
107
|
+
## LOGIC branch — terminal app for state-machine validation
|
|
108
|
+
|
|
109
|
+
When the question is about behavior / control flow / state machines /
|
|
110
|
+
protocols:
|
|
111
|
+
|
|
112
|
+
1. Read `LOGIC.md` for the discipline (ported from Pocock's
|
|
113
|
+
`prototype/LOGIC.md` with MIT attribution).
|
|
114
|
+
2. Write ONE file (e.g., `prototype.mjs`, `prototype.ts`, or
|
|
115
|
+
`prototype.py`) that:
|
|
116
|
+
- Models the state machine in code
|
|
117
|
+
- Provides a command-line driver that fires transitions one at a
|
|
118
|
+
time, printing each state
|
|
119
|
+
- Includes a 5-10 turn scripted run at the bottom that exercises the
|
|
120
|
+
interesting paths
|
|
121
|
+
3. Write a one-line invocation: `node prototype.mjs` (or whatever).
|
|
122
|
+
4. Verify: run it. The user reads the output, gets their answer, and
|
|
123
|
+
the file is deleted.
|
|
124
|
+
|
|
125
|
+
## UI branch — delegates to apt:mockup
|
|
126
|
+
|
|
127
|
+
When the question is about layout / aesthetics / flow / discoverability:
|
|
128
|
+
|
|
129
|
+
1. Read `UI.md` for the discipline (ported from Pocock's
|
|
130
|
+
`prototype/UI.md` with MIT attribution).
|
|
131
|
+
2. Invoke `/apt:mockup --variants 3` as a sub-step. apt:mockup already
|
|
132
|
+
enforces the UI-specific universal rules (zero-dep Tailwind CDN, no
|
|
133
|
+
JS, throwaway HTML iterations preserved).
|
|
134
|
+
3. The 5 universal rules above still apply — verify each HTML file
|
|
135
|
+
carries the `<!-- THROWAWAY PROTOTYPE -->` marker.
|
|
136
|
+
|
|
137
|
+
## Output contract
|
|
138
|
+
|
|
139
|
+
- Single prototype file (LOGIC) OR 3 HTML variants via apt:mockup (UI).
|
|
140
|
+
- No commits. No tests. No docs. The skill emits a final note: "Delete
|
|
141
|
+
this when the question is answered."
|
|
142
|
+
- If the user wants to convert the prototype into real code, that's a
|
|
143
|
+
separate `/apt:plan` invocation.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Adapted from Matt Pocock's MIT-licensed skill suite:
|
|
3
|
+
https://github.com/mattpocock/skills/blob/main/skills/engineering/prototype/UI.md
|
|
4
|
+
Licensed under MIT. Modifications: routed through Aperant's existing
|
|
5
|
+
apt:mockup skill rather than a freestanding HTML+Tailwind generator;
|
|
6
|
+
aligned with the 5 universal rules in apt-prototype/SKILL.md.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# UI branch — Delegates to apt:mockup
|
|
10
|
+
|
|
11
|
+
When the user's question is about **appearance / layout / flow /
|
|
12
|
+
discoverability**, the prototype is one or more HTML files generated
|
|
13
|
+
by Aperant's existing `/apt:mockup` skill. apt:mockup already enforces
|
|
14
|
+
the UI-specific universal rules (zero-dep Tailwind CDN, no JS, throwaway
|
|
15
|
+
HTML iterations preserved).
|
|
16
|
+
|
|
17
|
+
## When this branch fires
|
|
18
|
+
|
|
19
|
+
Question types that route here:
|
|
20
|
+
|
|
21
|
+
- "Does this UI shape feel right?"
|
|
22
|
+
- "Is this flow discoverable?"
|
|
23
|
+
- "Does this layout work on mobile?"
|
|
24
|
+
- "Should the primary action be a button or a card?"
|
|
25
|
+
- "How does X scale to N items?"
|
|
26
|
+
|
|
27
|
+
Question types that DO NOT route here (use LOGIC branch):
|
|
28
|
+
|
|
29
|
+
- "Does this state machine work?"
|
|
30
|
+
- "Does this control flow handle edge case X?"
|
|
31
|
+
- "Can this protocol handle out-of-order messages?"
|
|
32
|
+
|
|
33
|
+
## How the delegation works
|
|
34
|
+
|
|
35
|
+
apt:prototype's UI branch is a thin wrapper that:
|
|
36
|
+
|
|
37
|
+
1. Parses the user's question to extract the UI element / flow being
|
|
38
|
+
asked about (e.g., "search results card with N items").
|
|
39
|
+
2. Invokes the existing skill: `/apt:mockup --variants 3 [extracted topic]`.
|
|
40
|
+
3. apt:mockup produces 3 parallel HTML+Tailwind variants under
|
|
41
|
+
`.aperant/mockups/{topic-slug}/` so the user can compare them
|
|
42
|
+
side-by-side.
|
|
43
|
+
|
|
44
|
+
apt:prototype does NOT re-implement HTML+Tailwind generation — the
|
|
45
|
+
discipline lives in apt:mockup's body. UI.md exists so the apt:prototype
|
|
46
|
+
skill body can branch on question-type without conflating "logic
|
|
47
|
+
prototype" and "UI mockup" code paths.
|
|
48
|
+
|
|
49
|
+
## The 5 universal rules still apply
|
|
50
|
+
|
|
51
|
+
apt:mockup already enforces:
|
|
52
|
+
|
|
53
|
+
- Throwaway-marked (each HTML file carries a comment marker)
|
|
54
|
+
- Single-command-run (`open mockup.html` — zero dependencies)
|
|
55
|
+
- No-persistence-default (static HTML, no localStorage usage by default)
|
|
56
|
+
- Skip-polish (CSS reset, no animation refinement, no responsive
|
|
57
|
+
breakpoints unless the question is about responsive)
|
|
58
|
+
|
|
59
|
+
The fifth rule — **surface-state-transparently** — is the one
|
|
60
|
+
apt:mockup doesn't fully cover by default. For UI prototypes where the
|
|
61
|
+
question is about data shape (e.g., "what does this look like with 0
|
|
62
|
+
items vs 100 items?"), instruct apt:mockup to render each variant with
|
|
63
|
+
a different data-fixture state, and put the fixture JSON in a
|
|
64
|
+
side-panel of each mockup so the user can see what's driving the
|
|
65
|
+
render.
|
|
66
|
+
|
|
67
|
+
## What apt:prototype's UI branch adds over running apt:mockup directly
|
|
68
|
+
|
|
69
|
+
Two things:
|
|
70
|
+
|
|
71
|
+
1. **Question framing.** apt:mockup is invocable as "build me a mockup
|
|
72
|
+
of X". apt:prototype's UI branch is invocable as "I have a question
|
|
73
|
+
about UI X — show me three answers." The framing shifts the
|
|
74
|
+
discipline from "deliver the mockup the user asked for" to "answer
|
|
75
|
+
the user's question with the cheapest possible visual artifact."
|
|
76
|
+
|
|
77
|
+
2. **5-rule cross-discipline reminder.** When the UI branch fires, the
|
|
78
|
+
skill body explicitly re-states all 5 universal rules (not just the
|
|
79
|
+
UI-specific ones). The user gets the apt:prototype mental model on
|
|
80
|
+
top of apt:mockup's mechanical output — which prevents the variant
|
|
81
|
+
from drifting into "polish this until it's production-ready."
|
|
82
|
+
|
|
83
|
+
## When the apt:mockup delegation is NOT enough
|
|
84
|
+
|
|
85
|
+
If the question requires interaction the user can drive (click through,
|
|
86
|
+
hover states, conditional rendering on input), the right call is
|
|
87
|
+
`/apt:prototype` LOGIC branch on top of `/apt:mockup` — a tiny
|
|
88
|
+
JS-driven terminal-ish runner that swaps between the 3 mockups based
|
|
89
|
+
on simulated state. This is rare; most UI questions are answered by
|
|
90
|
+
the side-by-side parallel variants apt:mockup already produces.
|
|
@@ -21,6 +21,8 @@ gates: []
|
|
|
21
21
|
---
|
|
22
22
|
<objective>
|
|
23
23
|
Execute a small task quickly without full pipeline overhead. For small fixes, doc updates, config changes, and ad-hoc tasks. Skip planning — go straight to implementation with atomic commits and lightweight state tracking.
|
|
24
|
+
|
|
25
|
+
**QUICK is sequential single-agent by contract.** Per roundtable 2026-05-14 (R1), QUICK = one agent doing intent → implementation in one context window. There are no phase sub-agents. This is a contract, not an optimization — the QUICK track exists precisely because phase isolation buys nothing on tasks small enough that the planner's mental model and the implementer's mental model would be identical.
|
|
24
26
|
</objective>
|
|
25
27
|
|
|
26
28
|
<your_environment>
|
|
@@ -99,6 +101,34 @@ If the task does NOT cross any obligation axes, proceed normally.
|
|
|
99
101
|
2. Use Glob/Grep to find the files that need changes
|
|
100
102
|
3. Read those files to understand current state
|
|
101
103
|
|
|
104
|
+
## 3.5. Risk Check (mandatory)
|
|
105
|
+
|
|
106
|
+
Before implementing, check the risk class of files this task will modify. QUICK shares the same Critical/Destructive hard stop as `/apt:execute` step 3b — the speed of QUICK does NOT waive the risk gate. Misclassified QUICK tasks touching `**/auth/**`, `**/schema*`, `**/convex/schema.*`, or other Critical paths must NOT commit without explicit human approval.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
node .aperant/deps/node_modules/@aperant/framework/bin/apt-tools.mjs risk-check . --paths {target files}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If the task description contains destructive keywords ("delete", "remove", "drop", "force-push"), pass `--operation delete` so glob matching covers the destructive intent.
|
|
113
|
+
|
|
114
|
+
Parse the JSON result and apply the gate:
|
|
115
|
+
|
|
116
|
+
**If `risk_class` is `"Critical"` or `"Destructive"`:**
|
|
117
|
+
Stop execution. Show the user:
|
|
118
|
+
```
|
|
119
|
+
RISK GATE: This QUICK task touches {risk_class} files.
|
|
120
|
+
Files: {matched_paths list}
|
|
121
|
+
Pattern: {matched_pattern}
|
|
122
|
+
|
|
123
|
+
Approve this change? (yes/no)
|
|
124
|
+
```
|
|
125
|
+
Wait for explicit approval. If denied, abort the task and record `verification.risk_gate = "denied"` in `task.json`. The gate is hardcoded at ALL autonomy levels — QUICK does not get to skip it.
|
|
126
|
+
|
|
127
|
+
**If `risk_class` is `"Elevated"` AND autonomy < 3:**
|
|
128
|
+
Show the affected files briefly before proceeding (5-second delay; user can interrupt). At YOLO autonomy, proceed without stopping.
|
|
129
|
+
|
|
130
|
+
**Why this exists:** roundtable 2026-05-14 R1 surfaced that `apt-quick` previously had no risk-check gate, meaning a misclassified QUICK task touching schema/auth could commit Critical-path changes with zero code-level safeguard. See `.aperant/roundtables/phase-mode-per-track-20260514/REPORT.md` (R1, Risk Assessment §1).
|
|
131
|
+
|
|
102
132
|
## 4. Implement
|
|
103
133
|
|
|
104
134
|
Make the changes directly:
|
|
@@ -249,18 +279,29 @@ skill MUST exit silently regardless of the config value, so spawned subagents
|
|
|
249
279
|
never block on a prompt that no human will answer.
|
|
250
280
|
|
|
251
281
|
```bash
|
|
252
|
-
# Pseudocode the model executes inline
|
|
282
|
+
# Pseudocode the model executes inline.
|
|
283
|
+
# AUDIT-001: `preferences.quick_task_post_verify` is per-device — read from
|
|
284
|
+
# the MERGED config (shared `.aperant/config.json` + local
|
|
285
|
+
# `.aperant/config.local.json`). Local wins on collision. Reading raw
|
|
286
|
+
# `config.json` only would miss per-device overrides.
|
|
253
287
|
node -e '
|
|
254
288
|
const fs = require("fs");
|
|
255
289
|
const path = require("path");
|
|
256
|
-
const
|
|
290
|
+
const readJsonOrEmpty = (p) => { try { return JSON.parse(fs.readFileSync(p, "utf-8")) ?? {} } catch { return {} } };
|
|
291
|
+
const shared = readJsonOrEmpty(path.join(process.cwd(), ".aperant/config.json"));
|
|
292
|
+
const local = readJsonOrEmpty(path.join(process.cwd(), ".aperant/config.local.json"));
|
|
293
|
+
function merge(a, b) {
|
|
294
|
+
if (a === null || typeof a !== "object" || Array.isArray(a)) return b;
|
|
295
|
+
if (b === null || typeof b !== "object" || Array.isArray(b)) return b;
|
|
296
|
+
const out = { ...a };
|
|
297
|
+
for (const k of Object.keys(b)) out[k] = (k in a) ? merge(a[k], b[k]) : b[k];
|
|
298
|
+
return out;
|
|
299
|
+
}
|
|
300
|
+
const cfg = merge(shared, local);
|
|
257
301
|
let mode = "ask";
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
mode = cfg.preferences.quick_task_post_verify;
|
|
262
|
-
}
|
|
263
|
-
} catch {}
|
|
302
|
+
if (cfg.preferences && cfg.preferences.quick_task_post_verify) {
|
|
303
|
+
mode = cfg.preferences.quick_task_post_verify;
|
|
304
|
+
}
|
|
264
305
|
if (mode === "never" || !process.stdin.isTTY) process.exit(0);
|
|
265
306
|
if (mode === "always") { /* invoke apt:verify {task-id} */ process.exit(0); }
|
|
266
307
|
// mode === "ask": readline prompt with 30s timeout, default = skip.
|