@aperant/framework 0.6.4 → 0.6.6
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 +38 -0
- package/README.md +54 -234
- 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/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/commit.d.mts.map +1 -1
- package/dist/cli/commands/commit.mjs +25 -8
- package/dist/cli/commands/commit.mjs.map +1 -1
- 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 +125 -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/modes.d.mts +13 -0
- package/dist/cli/commands/modes.d.mts.map +1 -0
- package/dist/cli/commands/modes.mjs +221 -0
- package/dist/cli/commands/modes.mjs.map +1 -0
- package/dist/cli/commands/route.mjs +1 -1
- 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 +393 -145
- 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 +263 -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/auto-emit-artifact-ready.d.mts +16 -0
- package/dist/cli/coordination/auto-emit-artifact-ready.d.mts.map +1 -0
- package/dist/cli/coordination/auto-emit-artifact-ready.mjs +88 -0
- package/dist/cli/coordination/auto-emit-artifact-ready.mjs.map +1 -0
- 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/coordination/event-schema.d.mts +16 -0
- package/dist/cli/coordination/event-schema.d.mts.map +1 -0
- package/dist/cli/coordination/event-schema.mjs +161 -0
- package/dist/cli/coordination/event-schema.mjs.map +1 -0
- package/dist/cli/coordination/store.d.mts +6 -0
- package/dist/cli/coordination/store.d.mts.map +1 -1
- package/dist/cli/coordination/store.mjs +14 -0
- package/dist/cli/coordination/store.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 +3 -2
- 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/roadmap/conductor-view.d.mts +13 -0
- package/dist/cli/roadmap/conductor-view.d.mts.map +1 -0
- package/dist/cli/roadmap/conductor-view.mjs +31 -0
- package/dist/cli/roadmap/conductor-view.mjs.map +1 -0
- 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 +9 -0
- package/dist/cli/route/skill-discover.d.mts.map +1 -1
- package/dist/cli/route/skill-discover.mjs +13 -1
- package/dist/cli/route/skill-discover.mjs.map +1 -1
- package/dist/cli/skill-author/contract.d.mts +1 -0
- package/dist/cli/skill-author/contract.d.mts.map +1 -1
- package/dist/cli/skill-author/contract.mjs +7 -0
- package/dist/cli/skill-author/contract.mjs.map +1 -1
- package/dist/cli/task/ids.d.mts +7 -4
- package/dist/cli/task/ids.d.mts.map +1 -1
- package/dist/cli/task/ids.mjs +11 -10
- package/dist/cli/task/ids.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 +9 -1
- package/prompts/coder.md +2 -0
- package/prompts/conductor-status-check.md +23 -0
- package/prompts/conductor-sub-agent.md +57 -0
- package/prompts/conductor-system.md +172 -0
- package/prompts/planner.md +12 -0
- package/prompts/spec_writer.md +9 -0
- package/skills/apt/SKILL.md +1 -0
- package/skills/apt-close-task/SKILL.md +32 -1
- package/skills/apt-debug/SKILL.md +39 -6
- package/skills/apt-debug/appendices/diagnose-discipline.md +119 -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 +25 -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-execute/SKILL.md +48 -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-plan/SKILL.md +159 -4
- package/skills/apt-plan/adapters/conductor.md +98 -0
- package/skills/apt-planner.md +42 -1
- package/skills/apt-pr-review/SKILL.md +46 -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 +30 -0
- package/skills/apt-review/SKILL.md +2 -0
- package/skills/apt-run/SKILL.md +32 -4
- package/skills/apt-setup/SKILL.md +130 -2
- package/skills/apt-ship/SKILL.md +63 -1
- package/skills/apt-spar/SKILL.md +290 -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-verify/SKILL.md +3 -0
- package/skills/apt-verify-proof/SKILL.md +3 -0
- package/skills/apt-watch-ci/SKILL.md +163 -0
- package/skills/apt-zoom-out/SKILL.md +130 -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/commit.mjs +27 -8
- package/src/cli/commands/context.mjs +244 -0
- package/src/cli/commands/event.mjs +131 -24
- package/src/cli/commands/host-detect.mjs +33 -7
- package/src/cli/commands/modes.mjs +216 -0
- package/src/cli/commands/route.mjs +1 -1
- package/src/cli/commands/task.mjs +430 -170
- package/src/cli/commands/tokens.mjs +157 -6
- package/src/cli/commands/triage.mjs +286 -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/auto-emit-artifact-ready.mjs +96 -0
- package/src/cli/coordination/event-log.mjs +73 -2
- package/src/cli/coordination/event-schema.d.ts +13 -0
- package/src/cli/coordination/event-schema.mjs +174 -0
- package/src/cli/coordination/store.mjs +14 -0
- package/src/cli/dispatch.mjs +15 -1
- package/src/cli/gate/registry.mjs +14 -0
- package/src/cli/help.mjs +3 -2
- package/src/cli/host/detect.mjs +5 -0
- package/src/cli/roadmap/conductor-view.d.ts +10 -0
- package/src/cli/roadmap/conductor-view.mjs +31 -0
- package/src/cli/route/envelope.mjs +140 -106
- package/src/cli/route/skill-discover.mjs +14 -1
- package/src/cli/skill-author/contract.mjs +7 -0
- package/src/cli/task/ids.mjs +15 -13
- 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/skills/apt-plan/SKILL.md
CHANGED
|
@@ -110,7 +110,17 @@ If `{task_dir}/design.md` exists (emitted by a prior `/apt:design` run), load it
|
|
|
110
110
|
|
|
111
111
|
## 5. Write Specification
|
|
112
112
|
|
|
113
|
-
Create `spec.md` in the task directory (`{task_dir}` passed from the router, e.g. `.aperant/tasks/{task-id}/spec.md`)
|
|
113
|
+
Create `spec.md` in the task directory (`{task_dir}` passed from the router, e.g. `.aperant/tasks/{task-id}/spec.md`).
|
|
114
|
+
|
|
115
|
+
**Content format branches on track (Fast Path Guarantee — Pocock adoption ID-05):**
|
|
116
|
+
|
|
117
|
+
### 5.A. QUICK track — legacy 4-section format (hard-exempt from PRD upgrade)
|
|
118
|
+
|
|
119
|
+
When `track === "QUICK"` (the `apt:classify` rubric routed this as a one-shot
|
|
120
|
+
task) OR the complexity is `SIMPLE`, write the existing minimal 4-section
|
|
121
|
+
spec. Do NOT promote to PRD shape. The QUICK path is a constraint, not a
|
|
122
|
+
toggle — the user opted into one-shot speed; PRD ceremony would violate
|
|
123
|
+
that contract.
|
|
114
124
|
|
|
115
125
|
```markdown
|
|
116
126
|
# Task: {task description}
|
|
@@ -131,6 +141,79 @@ Create `spec.md` in the task directory (`{task_dir}` passed from the router, e.g
|
|
|
131
141
|
{What this task explicitly does NOT cover}
|
|
132
142
|
```
|
|
133
143
|
|
|
144
|
+
### 5.B. STANDARD / DEEP / COMPLEX tracks — PRD-shaped spec.md
|
|
145
|
+
|
|
146
|
+
When `track ∈ {"STANDARD", "DEEP"}` OR complexity is `STANDARD` or
|
|
147
|
+
`COMPLEX`, write a PRD-shaped spec.md so the artifact survives the task
|
|
148
|
+
and is committable as a second-consumer document. Section ordering is
|
|
149
|
+
**load-bearing** — downstream tooling (`apt-tools coverage-check`,
|
|
150
|
+
`apt-tools consistency check`) reads sections by header.
|
|
151
|
+
|
|
152
|
+
```markdown
|
|
153
|
+
# Spec: {task title}
|
|
154
|
+
|
|
155
|
+
**Task ID:** {task-id}
|
|
156
|
+
**Track:** {STANDARD | DEEP}
|
|
157
|
+
**Scope:** {framework | desktop | web | core | ui | backend | docs}
|
|
158
|
+
|
|
159
|
+
## Problem Statement
|
|
160
|
+
|
|
161
|
+
{What pain are we solving? Cite empirical evidence, prior decisions, or
|
|
162
|
+
codebase artifacts where possible. State what's broken or missing today.}
|
|
163
|
+
|
|
164
|
+
## Solution
|
|
165
|
+
|
|
166
|
+
{One paragraph: the chosen approach. Then a bulleted net delta of what
|
|
167
|
+
ships: new files, modified files, new flags, new config, new skills.}
|
|
168
|
+
|
|
169
|
+
## User Stories
|
|
170
|
+
|
|
171
|
+
{One story per user value slice. Format: "**US-NN (persona).** As a
|
|
172
|
+
{persona}, when I {trigger}, I want {behavior} so I can {outcome}."
|
|
173
|
+
Stories map 1:1 onto subtasks in implementation_plan.json.}
|
|
174
|
+
|
|
175
|
+
## Implementation Decisions
|
|
176
|
+
|
|
177
|
+
{Load-bearing principles carried forward into every subtask. Format:
|
|
178
|
+
"### ID-NN: {decision title}" + rationale + practical consequence. Each
|
|
179
|
+
ID-NN is referenced from subtask descriptions where relevant.}
|
|
180
|
+
|
|
181
|
+
## Testing Decisions
|
|
182
|
+
|
|
183
|
+
{One block per test family: "### TD-NN: {test family name}" + what's
|
|
184
|
+
covered + which subtask owns the test file. Critical: Fast Path Guarantee
|
|
185
|
+
regression tests (QUICK-exempt assertions) MUST be enumerated here.}
|
|
186
|
+
|
|
187
|
+
## Out of Scope
|
|
188
|
+
|
|
189
|
+
{Explicit non-goals. Each bullet names what is deferred + where it
|
|
190
|
+
belongs (parallel track, v2 follow-up, separate task).}
|
|
191
|
+
|
|
192
|
+
## Further Notes
|
|
193
|
+
|
|
194
|
+
{Sequencing rationale, risk surface, dependencies on other parts of the
|
|
195
|
+
codebase, files-affected preview, and any other context the executor
|
|
196
|
+
needs but that doesn't fit the seven primary sections.}
|
|
197
|
+
|
|
198
|
+
### Acceptance Criteria
|
|
199
|
+
|
|
200
|
+
{Cross-cutting AC1..ACN list — each acceptance criterion gets a stable
|
|
201
|
+
ID. Subtasks reference these IDs via their per-subtask
|
|
202
|
+
`acceptance_criteria` field (see Section 6). This list IS the
|
|
203
|
+
plan-coverage-check input.}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Constraint — do NOT interview the user.** The PRD is synthesized from
|
|
207
|
+
the task description + codebase investigation + AGENTS.md, not from a
|
|
208
|
+
clarifying interview. If a section truly cannot be filled, write
|
|
209
|
+
`{TBD — needs user input}` so the gap is visible; do NOT pause for
|
|
210
|
+
clarification (that's `apt:discuss`'s job, not the planner's).
|
|
211
|
+
|
|
212
|
+
**Section ordering is mandatory.** `apt-tools coverage-check validate`
|
|
213
|
+
greps `## Acceptance Criteria` for AC IDs; `apt-tools consistency check`
|
|
214
|
+
greps `## Solution` and `## User Stories`. Renaming or reordering these
|
|
215
|
+
breaks downstream tooling.
|
|
216
|
+
|
|
134
217
|
### 5.1. Design Reference section (C24 — when design.md exists)
|
|
135
218
|
|
|
136
219
|
When `{task_dir}/design.md` exists, `spec.md` MUST include a `## Design Reference` section **directly below `## Requirements`**. The section cites the design artifact by relative path and enumerates which screens and components the subtasks cover. Shape:
|
|
@@ -212,35 +295,95 @@ When `status: warn` (non-blocking enforcement) and the user is in **auto mode**
|
|
|
212
295
|
|
|
213
296
|
## 6. Create Implementation Plan
|
|
214
297
|
|
|
215
|
-
Create `implementation_plan.json` in the task directory (`{task_dir}/implementation_plan.json`)
|
|
298
|
+
Create `implementation_plan.json` in the task directory (`{task_dir}/implementation_plan.json`).
|
|
299
|
+
|
|
300
|
+
**Subtask schema branches on track (Pocock adoption ID-05 — Fast Path Guarantee).**
|
|
301
|
+
|
|
302
|
+
### 6.A. QUICK track / SIMPLE complexity — legacy flat subtask schema
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"task": "{task description}",
|
|
307
|
+
"complexity": "simple",
|
|
308
|
+
"spec": "spec.md",
|
|
309
|
+
"subtasks": [
|
|
310
|
+
{
|
|
311
|
+
"id": "1",
|
|
312
|
+
"title": "{subtask title}",
|
|
313
|
+
"description": "{what to do — concrete, not vague}",
|
|
314
|
+
"files": ["path/to/file1.ts", "path/to/file2.ts"],
|
|
315
|
+
"dependencies": [],
|
|
316
|
+
"status": "pending",
|
|
317
|
+
"verification": "{command or check to verify completion}"
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
QUICK subtasks omit `hitl`, `afk`, `acceptance_criteria`, and `user_value`
|
|
324
|
+
fields. The one-shot path doesn't need user-value framing or per-subtask
|
|
325
|
+
HITL gates.
|
|
326
|
+
|
|
327
|
+
### 6.B. STANDARD / DEEP / COMPLEX — vertical-slice subtask schema
|
|
216
328
|
|
|
217
329
|
```json
|
|
218
330
|
{
|
|
219
331
|
"task": "{task description}",
|
|
220
|
-
"complexity": "
|
|
332
|
+
"complexity": "standard|complex",
|
|
221
333
|
"spec": "spec.md",
|
|
334
|
+
"vertical_slice_schema_version": "1",
|
|
222
335
|
"declared_persona_tier": "primary",
|
|
223
336
|
"declared_personas": ["mobile-dev"],
|
|
224
337
|
"tier_confidence": "high",
|
|
225
338
|
"subtasks": [
|
|
226
339
|
{
|
|
227
340
|
"id": "1",
|
|
228
|
-
"title": "{subtask title}",
|
|
341
|
+
"title": "{subtask title — user-value framing, not 'add UI'}",
|
|
229
342
|
"description": "{what to do — concrete, not vague}",
|
|
230
343
|
"files": ["path/to/file1.ts", "path/to/file2.ts"],
|
|
344
|
+
"acceptance_criteria": ["AC1", "AC3"],
|
|
231
345
|
"dependencies": [],
|
|
232
346
|
"status": "pending",
|
|
347
|
+
"hitl": "required | review | none",
|
|
348
|
+
"afk": "safe | unsafe",
|
|
349
|
+
"user_value": "{one-line user-value framing — who benefits, how}",
|
|
233
350
|
"verification": "{command or check to verify completion}"
|
|
234
351
|
}
|
|
235
352
|
]
|
|
236
353
|
}
|
|
237
354
|
```
|
|
238
355
|
|
|
356
|
+
**Mandatory STANDARD/DEEP fields (per subtask):**
|
|
357
|
+
|
|
358
|
+
- `hitl` — `"required" | "review" | "none"`. `required` means a human MUST
|
|
359
|
+
approve the subtask before proceeding (autonomy 1 always pauses;
|
|
360
|
+
autonomy 2 batches recommendations; autonomy 3 escalates only on
|
|
361
|
+
conflict). `review` means the human reviews the diff after the agent
|
|
362
|
+
ships it (post-hoc, not blocking). `none` means agent-only.
|
|
363
|
+
- `afk` — `"safe" | "unsafe"`. `safe` means the agent may proceed
|
|
364
|
+
unattended without supervision. `unsafe` means the agent should pause
|
|
365
|
+
at the start of this subtask if no human is present (autonomy < 3).
|
|
366
|
+
- `acceptance_criteria` — `string[]` of id-refs (`"AC1"`, `"AC3"`, …)
|
|
367
|
+
into the spec.md `## Acceptance Criteria` section. Every AC in spec.md
|
|
368
|
+
MUST be referenced by at least one subtask (gate G8 consistency-check
|
|
369
|
+
enforces this on ship).
|
|
370
|
+
- `user_value` — one-line framing of WHO benefits and HOW. Prevents
|
|
371
|
+
horizontal slicing ("add UI" / "add backend") — every subtask must be
|
|
372
|
+
a vertical user-shippable slice with a defensible value framing.
|
|
373
|
+
|
|
374
|
+
**Plan-level fields for STANDARD/DEEP:**
|
|
375
|
+
|
|
376
|
+
- `vertical_slice_schema_version` — `"1"` (current). Stable across the
|
|
377
|
+
v1 schema window; bumped when the subtask shape changes incompatibly.
|
|
378
|
+
Plans without this field are treated as legacy flat schema.
|
|
379
|
+
|
|
239
380
|
Reference `prompts/planner.md` for subtask decomposition patterns:
|
|
240
381
|
- Each subtask should be completable in one focused session
|
|
241
382
|
- Dependencies must form a DAG (no circular deps)
|
|
242
383
|
- Verification must be automated (test command, grep check, type check)
|
|
243
384
|
- Files list must be exhaustive — every file the subtask touches
|
|
385
|
+
- Subtask title MUST frame user value, not file scope (e.g., "Solo
|
|
386
|
+
dogfooder gets PRD-shaped spec on STANDARD", NOT "edit apt-plan SKILL.md")
|
|
244
387
|
|
|
245
388
|
**Framework-scope doc-sync rule (C33).** When `task.scope === "framework"` AND any subtask's `files` intersect `packages/framework/src/cli/**`, the plan MUST end with a subtask whose title contains `Doc sync` (case-insensitive) and whose `files` list includes at least one of `packages/framework/skills/apt-*/SKILL.md`, `packages/framework/agents/apt-*.md`, `packages/framework/templates/agents-*.md`, or `CLAUDE.md`. The detailed rule and rationale live in `packages/framework/agents/apt-planner.md` §5.1; the planner agent appends this subtask automatically when it would otherwise be missing. Smoke-drain emits a warn-only signal for plans that violate the rule.
|
|
246
389
|
|
|
@@ -273,6 +416,18 @@ The coverage check ensures every acceptance criterion has at least one subtask w
|
|
|
273
416
|
node packages/framework/bin/apt-tools.mjs commit "plan: create implementation plan for {task}" --files spec.md implementation_plan.json
|
|
274
417
|
```
|
|
275
418
|
|
|
419
|
+
## 8a. Runtime-context adapters
|
|
420
|
+
|
|
421
|
+
If `APERANT_TERMINAL_ID` is set (you are running under the Aperant
|
|
422
|
+
Conductor — a master-orchestrator agent inside the Aperant app), see
|
|
423
|
+
`adapters/conductor.md` for the plan-review handshake convention
|
|
424
|
+
(`proceed` / `abort` / `[Conductor realignment]` stdin strings) the
|
|
425
|
+
Conductor's drawer uses post-commit. The `artifact.ready{kind:'plan'}`
|
|
426
|
+
signal itself is now emitted automatically by the `apt-tools commit`
|
|
427
|
+
postcondition — no manual emit step required. Native invocations
|
|
428
|
+
(Claude Code, Gemini, OpenCode, Codex with no Conductor context) can
|
|
429
|
+
skip the adapter entirely and proceed to Section 9.
|
|
430
|
+
|
|
276
431
|
## 9. Report
|
|
277
432
|
|
|
278
433
|
Output a summary:
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# apt-plan adapter — Aperant Conductor
|
|
2
|
+
|
|
3
|
+
This adapter is **only loaded** when the planner runs under the Aperant
|
|
4
|
+
Conductor (a master-orchestrator agent inside the Aperant desktop / web
|
|
5
|
+
app). Native invocations of `/apt:plan` (from plain Claude Code, Gemini
|
|
6
|
+
CLI, OpenCode, or Codex) IGNORE this file entirely — the framework
|
|
7
|
+
behavior in `SKILL.md` is the source of truth for them.
|
|
8
|
+
|
|
9
|
+
## When to load this adapter
|
|
10
|
+
|
|
11
|
+
Detect Conductor context by env var:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
[ -n "$APERANT_TERMINAL_ID" ]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The Conductor injects `APERANT_TERMINAL_ID` into every PTY it spawns.
|
|
18
|
+
If the var is unset, you are NOT under the Conductor — stop reading.
|
|
19
|
+
|
|
20
|
+
## What changes under the Conductor
|
|
21
|
+
|
|
22
|
+
The planner's filesystem outputs (`spec.md`, `implementation_plan.json`)
|
|
23
|
+
are unchanged. The ADDITION is one extra step after Section 8 (Persist
|
|
24
|
+
State) of `SKILL.md`:
|
|
25
|
+
|
|
26
|
+
### Plan-Ready Signal (framework-owned, no action required)
|
|
27
|
+
|
|
28
|
+
The `artifact.ready{kind:'plan'}` signal is emitted **automatically** by
|
|
29
|
+
the framework's `apt-tools commit` postcondition. When the planner
|
|
30
|
+
commits `spec.md` + `implementation_plan.json` via the standard:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
node packages/framework/bin/apt-tools.mjs commit "plan: ..." \
|
|
34
|
+
--files spec.md implementation_plan.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
…and the process is running under a Conductor PTY (env
|
|
38
|
+
`APERANT_TERMINAL_ID` is set), `apt-tools commit` auto-emits a fully-
|
|
39
|
+
formed `artifact.ready` envelope to `.aperant/events/{today}.jsonl`.
|
|
40
|
+
The envelope carries the `task_id`, plan path, sha256 hash, and the
|
|
41
|
+
auto-stamped `terminal_id`.
|
|
42
|
+
|
|
43
|
+
This replaces the earlier markdown-discipline emit step. The earlier
|
|
44
|
+
step was correctly skipped on QUICK / SIMPLE classified tasks (Fast
|
|
45
|
+
Path Guarantee, Pocock adoption ID-05) — moving the emit to a
|
|
46
|
+
framework postcondition makes it work uniformly across QUICK, STANDARD,
|
|
47
|
+
DEEP, and COMPLEX without violating the Fast Path Guarantee.
|
|
48
|
+
|
|
49
|
+
**Planner authors don't need to do anything.** As long as you call
|
|
50
|
+
`apt-tools commit` to land your plan artifacts, the Conductor will
|
|
51
|
+
see `artifact.ready` and the drawer's PlanReadyCard will auto-promote.
|
|
52
|
+
|
|
53
|
+
If the planner does NOT use `apt-tools commit` (it lands the plan via
|
|
54
|
+
raw `git commit` or `git add`), the auto-emit will not fire. In that
|
|
55
|
+
case the Conductor falls back to filesystem polling of the task dir
|
|
56
|
+
(slightly higher latency, same outcome).
|
|
57
|
+
|
|
58
|
+
### Plan-review handshake (Step 6 + 7 of Conductor v2)
|
|
59
|
+
|
|
60
|
+
After emitting `artifact.ready{kind:'plan'}` the planner SHOULD pause at
|
|
61
|
+
an idle prompt and listen for ONE of three Conductor-driven inputs:
|
|
62
|
+
|
|
63
|
+
- `proceed\r` — the human (via the PlanReadyCard's **Approve** button)
|
|
64
|
+
approves the plan. Continue to `/apt:execute` as you would in the
|
|
65
|
+
normal flow.
|
|
66
|
+
- `abort\r` — the human rejected. Abandon this plan; do not start
|
|
67
|
+
execution. Optionally exit the session cleanly.
|
|
68
|
+
- `[Conductor realignment] <note>\r` — the human pressed **Realign**.
|
|
69
|
+
Treat the `<note>` as additional planning context: re-open spec.md /
|
|
70
|
+
implementation_plan.json, address the note's gaps, commit a new
|
|
71
|
+
revision, and emit a fresh `artifact.ready{kind:'plan'}` (with the
|
|
72
|
+
same task_id but a NEW request_id — the drawer keys cards on
|
|
73
|
+
request_id, so re-using it would suppress the new card). The
|
|
74
|
+
realignment loop can repeat; after attempt_n >= 3 the Conductor may
|
|
75
|
+
decide to respawn the terminal entirely.
|
|
76
|
+
|
|
77
|
+
These exact strings are pinned by the Conductor's `ConductorContextHost`
|
|
78
|
+
handlers (`packages/ui/src/sections/conductor/ConductorContextHost.tsx`).
|
|
79
|
+
Native CLI invocations of `/apt:plan` (no `APERANT_TERMINAL_ID`) skip
|
|
80
|
+
this handshake and follow the normal report → `/apt:execute` flow.
|
|
81
|
+
|
|
82
|
+
## Why this lives in an adapter (not in SKILL.md)
|
|
83
|
+
|
|
84
|
+
The Aperant Framework is consumed by multiple CLIs (Claude Code, Gemini,
|
|
85
|
+
OpenCode, Codex) and by the Aperant app itself. The vast majority of
|
|
86
|
+
`/apt:plan` invocations come from native CLIs — those should not see
|
|
87
|
+
or execute Conductor-specific machinery. By isolating the Conductor's
|
|
88
|
+
event-emit obligations to this adapter, the public skill stays minimal
|
|
89
|
+
and the framework remains CLI-agnostic. The pattern mirrors
|
|
90
|
+
`appendices/` (reasoning-stance loaders) but with a different semantic:
|
|
91
|
+
**runtime-context loader** — load when the runtime environment matches.
|
|
92
|
+
|
|
93
|
+
## Adding more adapters
|
|
94
|
+
|
|
95
|
+
Future runtime contexts (e.g. a hypothetical CI runner, another
|
|
96
|
+
orchestrator) can add `adapters/{context}.md` files using the same
|
|
97
|
+
pattern: detect via env or filesystem signal, document the additional
|
|
98
|
+
obligations, and add a one-line conditional reference in `SKILL.md`.
|
package/skills/apt-planner.md
CHANGED
|
@@ -59,7 +59,10 @@ For STANDARD and COMPLEX tasks:
|
|
|
59
59
|
|
|
60
60
|
## 4. Write Specification
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Content format branches on track (Pocock adoption ID-05, Fast Path Guarantee).
|
|
63
|
+
|
|
64
|
+
### 4.A. QUICK track / SIMPLE complexity — legacy 4-section spec
|
|
65
|
+
|
|
63
66
|
```markdown
|
|
64
67
|
# Task: {task description}
|
|
65
68
|
|
|
@@ -79,6 +82,44 @@ Create `{task_dir}/spec.md`:
|
|
|
79
82
|
{What this task explicitly does NOT cover}
|
|
80
83
|
```
|
|
81
84
|
|
|
85
|
+
### 4.B. STANDARD / DEEP / COMPLEX — PRD-shaped spec.md
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
# Spec: {task title}
|
|
89
|
+
|
|
90
|
+
**Task ID:** {task-id}
|
|
91
|
+
**Track:** {STANDARD | DEEP}
|
|
92
|
+
**Scope:** {framework | desktop | web | core | ui | backend | docs}
|
|
93
|
+
|
|
94
|
+
## Problem Statement
|
|
95
|
+
{What pain are we solving?}
|
|
96
|
+
|
|
97
|
+
## Solution
|
|
98
|
+
{Chosen approach + bulleted net delta.}
|
|
99
|
+
|
|
100
|
+
## User Stories
|
|
101
|
+
{**US-NN (persona).** stories, 1:1 onto subtasks.}
|
|
102
|
+
|
|
103
|
+
## Implementation Decisions
|
|
104
|
+
{### ID-NN load-bearing principles.}
|
|
105
|
+
|
|
106
|
+
## Testing Decisions
|
|
107
|
+
{### TD-NN test families. Fast Path regressions enumerated here.}
|
|
108
|
+
|
|
109
|
+
## Out of Scope
|
|
110
|
+
{Non-goals with deferral target.}
|
|
111
|
+
|
|
112
|
+
## Further Notes
|
|
113
|
+
{Sequencing, risk surface, dependencies, files-affected preview.}
|
|
114
|
+
|
|
115
|
+
### Acceptance Criteria
|
|
116
|
+
{**AC1..ACN** stable IDs referenced by subtasks.}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
PRD section ordering is load-bearing — downstream tooling greps by header.
|
|
120
|
+
Do NOT interview the user; synthesize from task description + codebase +
|
|
121
|
+
AGENTS.md.
|
|
122
|
+
|
|
82
123
|
## 5. Create Implementation Plan
|
|
83
124
|
|
|
84
125
|
Create `{task_dir}/implementation_plan.json`:
|
|
@@ -1454,33 +1454,63 @@ node packages/framework/bin/apt-tools.mjs workflow advance . --id ${REVIEW_ID} -
|
|
|
1454
1454
|
|
|
1455
1455
|
If `WORKTREE_PATH != .` AND fixes were applied in Phase 6/7:
|
|
1456
1456
|
|
|
1457
|
+
Get the PR head ref (for branch reviews, use the branch name directly):
|
|
1457
1458
|
```bash
|
|
1458
|
-
|
|
1459
|
+
PR_HEAD_REF=$(gh pr view ${PR_NUMBER} --json headRefName -q .headRefName)
|
|
1460
|
+
```
|
|
1459
1461
|
|
|
1460
|
-
|
|
1461
|
-
git add -A
|
|
1462
|
-
git commit -m "fix: auto-fix review findings from /apt:pr-review (review ${REVIEW_ID})"
|
|
1462
|
+
#### Confirmation gate (BUG-009 fix)
|
|
1463
1463
|
|
|
1464
|
-
|
|
1465
|
-
# For PRs: push to the PR's head ref
|
|
1466
|
-
git push origin HEAD:${PR_HEAD_REF}
|
|
1464
|
+
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
1465
|
|
|
1468
|
-
|
|
1466
|
+
```bash
|
|
1467
|
+
confirm_mode=$(jq -r '.pr_review.confirm_before_push // empty' .aperant/config.json)
|
|
1468
|
+
autonomy=$(jq -r '.autonomy.default // 2' .aperant/config.json)
|
|
1469
|
+
if [ -z "$confirm_mode" ]; then
|
|
1470
|
+
if [ "${autonomy}" -ge 2 ]; then confirm_mode="auto"; else confirm_mode="ask"; fi
|
|
1471
|
+
fi
|
|
1469
1472
|
```
|
|
1470
1473
|
|
|
1471
|
-
|
|
1474
|
+
Branch on `confirm_mode`:
|
|
1475
|
+
|
|
1476
|
+
- **`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.
|
|
1477
|
+
- **`auto`** — Proceed silently to the catch-all + push below. No prompt.
|
|
1478
|
+
- **`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.
|
|
1479
|
+
|
|
1480
|
+
`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.
|
|
1481
|
+
|
|
1482
|
+
#### Catch-all + push (BUG-010 fix)
|
|
1483
|
+
|
|
1484
|
+
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:
|
|
1485
|
+
|
|
1472
1486
|
```bash
|
|
1473
|
-
|
|
1474
|
-
```
|
|
1487
|
+
cd ${WORKTREE_PATH}
|
|
1475
1488
|
|
|
1476
|
-
|
|
1489
|
+
# Guard 1: skip the catch-all entirely if the tree is clean.
|
|
1490
|
+
# Per-finding commits with proper messages are strictly better history than a single catch-all.
|
|
1491
|
+
if ! git diff --quiet || ! git diff --cached --quiet || [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
|
1492
|
+
# Guard 2: explicit allowlist instead of `git add -A`.
|
|
1493
|
+
# `git add -A` would sweep orchestrator-level Read/Write side-effects
|
|
1494
|
+
# (metadata.json, audit.json, validated.md, etc.) into the PR. Bad.
|
|
1495
|
+
# Stage ONLY files in the review's touched set, computed from the iteration diffs.
|
|
1496
|
+
REVIEW_TOUCHED=$(git diff --name-only ${ITERATION_START_SHA:-HEAD~4}..HEAD 2>/dev/null \
|
|
1497
|
+
| grep -v '^\.aperant/' \
|
|
1498
|
+
| tr '\n' ' ')
|
|
1499
|
+
if [ -n "$REVIEW_TOUCHED" ]; then
|
|
1500
|
+
# shellcheck disable=SC2086
|
|
1501
|
+
git add -- $REVIEW_TOUCHED
|
|
1502
|
+
fi
|
|
1503
|
+
# Only commit if `git add --` actually staged something.
|
|
1504
|
+
if ! git diff --cached --quiet; then
|
|
1505
|
+
git commit -m "fix: auto-fix review findings from /apt:pr-review (review ${REVIEW_ID})"
|
|
1506
|
+
fi
|
|
1507
|
+
fi
|
|
1477
1508
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
Fixes are ready in the worktree. Push to ${PR_HEAD_REF}? (y/n)
|
|
1509
|
+
git push origin HEAD:${PR_HEAD_REF}
|
|
1510
|
+
cd -
|
|
1481
1511
|
```
|
|
1482
1512
|
|
|
1483
|
-
|
|
1513
|
+
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
1514
|
|
|
1485
1515
|
### Step 0b: Cleanup Worktree
|
|
1486
1516
|
|
|
@@ -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.
|