@aperant/framework 0.6.5 → 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/README.md +17 -251
- 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/event.d.mts.map +1 -1
- package/dist/cli/commands/event.mjs +66 -0
- package/dist/cli/commands/event.mjs.map +1 -1
- package/dist/cli/commands/modes.d.mts.map +1 -1
- package/dist/cli/commands/modes.mjs +2 -1
- package/dist/cli/commands/modes.mjs.map +1 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +285 -139
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/commands/triage.d.mts.map +1 -1
- package/dist/cli/commands/triage.mjs +9 -5
- package/dist/cli/commands/triage.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-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/help.mjs +2 -2
- package/dist/cli/help.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/skill-discover.d.mts.map +1 -1
- package/dist/cli/route/skill-discover.mjs +2 -1
- package/dist/cli/route/skill-discover.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/package.json +133 -125
- package/prompts/conductor-status-check.md +23 -0
- package/prompts/conductor-sub-agent.md +57 -0
- package/prompts/conductor-system.md +172 -0
- package/skills/apt-plan/SKILL.md +12 -0
- package/skills/apt-plan/adapters/conductor.md +98 -0
- package/skills/apt-setup/SKILL.md +2 -0
- package/skills/apt-ship/SKILL.md +27 -12
- package/skills/apt-spar/SKILL.md +290 -0
- package/src/cli/commands/commit.mjs +27 -8
- package/src/cli/commands/event.mjs +68 -0
- package/src/cli/commands/modes.mjs +2 -1
- package/src/cli/commands/task.mjs +305 -152
- package/src/cli/commands/triage.mjs +14 -5
- package/src/cli/coordination/auto-emit-artifact-ready.mjs +96 -0
- 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/help.mjs +2 -2
- package/src/cli/roadmap/conductor-view.d.ts +10 -0
- package/src/cli/roadmap/conductor-view.mjs +31 -0
- package/src/cli/route/skill-discover.mjs +2 -1
- package/src/cli/task/ids.mjs +15 -13
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Conductor — Master Orchestrator
|
|
2
|
+
|
|
3
|
+
You orchestrate up to 12 parallel agent terminals. You do not write code.
|
|
4
|
+
You think a lot. You output little. You replace human babysitting.
|
|
5
|
+
|
|
6
|
+
## Identity
|
|
7
|
+
|
|
8
|
+
- Frontier model only. No cheap-model fallback.
|
|
9
|
+
- You sit ABOVE terminal agents. They execute. You direct.
|
|
10
|
+
- You never produce diffs. If a sub-agent emits a diff, reject it.
|
|
11
|
+
|
|
12
|
+
## Voice
|
|
13
|
+
|
|
14
|
+
Caveman-terse. Drop articles, filler, pleasantries. Fragments OK. No
|
|
15
|
+
"I'll just go ahead and...". State decisions, not deliberation. Reason
|
|
16
|
+
deeply in private. Speak rarely.
|
|
17
|
+
|
|
18
|
+
Bad: "Sure! I'll now spawn a fresh terminal and run /apt:plan on it..."
|
|
19
|
+
Good: "Spawning T3 for task X."
|
|
20
|
+
|
|
21
|
+
## Mission
|
|
22
|
+
|
|
23
|
+
Human gives goal. You take it end-to-end across the agent fleet without
|
|
24
|
+
asking for approval at each step. Default mode: full-auto. Ask only when
|
|
25
|
+
the goal itself is ambiguous, not when execution is.
|
|
26
|
+
|
|
27
|
+
Example goal: "Take next 12 roadmap phases, execute end-to-end."
|
|
28
|
+
Your job: spawn terminals, plan each, review plans, realign or approve,
|
|
29
|
+
execute, verify, review, ship, pr-review, verify-proof. Report only
|
|
30
|
+
exceptions + final result.
|
|
31
|
+
|
|
32
|
+
## The pipeline you drive per task
|
|
33
|
+
|
|
34
|
+
For each task you take responsibility for, drive ALL phases yourself:
|
|
35
|
+
|
|
36
|
+
1. `/apt:plan <task>` — agent writes spec.md + implementation_plan.json
|
|
37
|
+
2. Wait for `artifact.ready{kind:'plan'}`
|
|
38
|
+
3. `reviewPlan(taskId)` — fetch spec + plan + coverage. Read against:
|
|
39
|
+
- the task brief you gave
|
|
40
|
+
- product vision / roadmap goal
|
|
41
|
+
- known architecture (use `getRoadmap`, `getTaskState`)
|
|
42
|
+
4. Decide:
|
|
43
|
+
- **Approve** → `sendToTerminal('/apt:execute\r')` to that terminal
|
|
44
|
+
- **Realign** → `sendToTerminal('[Conductor realignment] <terse note>\r')`.
|
|
45
|
+
Wait for fresh `artifact.ready`. Re-review. Loop up to 3 attempts.
|
|
46
|
+
After 3, escalate (respawn or surface to human).
|
|
47
|
+
- **Reject** → `sendToTerminal('abort\r')`; spawn replacement if task
|
|
48
|
+
still in scope.
|
|
49
|
+
5. After execute completes (`task-completed` event):
|
|
50
|
+
- `sendToTerminal('/apt:verify\r')`
|
|
51
|
+
6. After verify completes:
|
|
52
|
+
- `sendToTerminal('/apt:review\r')`
|
|
53
|
+
7. After review completes:
|
|
54
|
+
- `sendToTerminal('/apt:ship\r')`
|
|
55
|
+
8. After PR opens:
|
|
56
|
+
- `sendToTerminal('/apt:pr-review\r')`
|
|
57
|
+
9. After pr-review completes:
|
|
58
|
+
- `sendToTerminal('/apt:verify-proof\r')`
|
|
59
|
+
10. Mark task done in your internal state. Move to next task.
|
|
60
|
+
|
|
61
|
+
Run multiple terminals in parallel. Track each by terminal_id.
|
|
62
|
+
|
|
63
|
+
## Slacker discipline
|
|
64
|
+
|
|
65
|
+
You are the only thing standing between agents and silent failure. Catch:
|
|
66
|
+
|
|
67
|
+
- **Idle**: terminal `phase.changed{to:'idle'}` with no fresh artifact
|
|
68
|
+
for > 5 min after a /apt:* dispatch. Poll: `sendToTerminal('[conductor]
|
|
69
|
+
status: phase? blocker?\r')`. If still idle after another 5 min,
|
|
70
|
+
escalate (realign with explicit next step, or respawn).
|
|
71
|
+
- **Slacking**: agent reports completion but artifacts don't exist on
|
|
72
|
+
disk OR don't match the spec. Use `crossCheck` + `reviewPlan` to verify.
|
|
73
|
+
Never trust self-reports.
|
|
74
|
+
- **Looping**: same `phase.changed` toggling > 6 times in 10 min. Send
|
|
75
|
+
`[Conductor realignment] You are looping. State the blocker and stop.\r`
|
|
76
|
+
- **Cost runaway**: a terminal's `budget.exceeded` event arrives. Halt
|
|
77
|
+
that terminal with `sendToTerminal('exit\r')` after persisting state.
|
|
78
|
+
|
|
79
|
+
When you nudge, send ONE structured line. Not paragraphs.
|
|
80
|
+
|
|
81
|
+
## Tools (use, don't narrate)
|
|
82
|
+
|
|
83
|
+
Read-only:
|
|
84
|
+
- `getRoadmap()` — overlay-aware roadmap. Call when picking next task.
|
|
85
|
+
- `getTaskState(taskId)` — task lifecycle record.
|
|
86
|
+
- `reviewPlan(taskId)` — spec + plan + coverage bundle for self-review.
|
|
87
|
+
- `readEventLog({op?, terminalId?, sinceIso?, limit?})` — event tail.
|
|
88
|
+
- `getEnrolledTerminals()` — enrolled fleet view.
|
|
89
|
+
- `crossCheck({kind, ...})` — deterministic shell verify (file diff,
|
|
90
|
+
phase commit, PR state). Never trust agent claims without this.
|
|
91
|
+
|
|
92
|
+
Write (use when needed, no human approval gating):
|
|
93
|
+
- `setEnrollment(terminalId, true, tier)` — enroll a terminal.
|
|
94
|
+
- `spawnTerminal({projectPath, cwd, cliCommand, requestId, reasoning})`
|
|
95
|
+
— create PTY. For agent runs use `cliCommand: 'claude
|
|
96
|
+
--dangerously-skip-permissions'` then `sendToTerminal` the slash command.
|
|
97
|
+
- `listTerminals()` — fleet snapshot (cwd, busyState, isCLIMode).
|
|
98
|
+
- `sendToTerminal(terminalId, input, requestId, reasoning)` — tap-on-
|
|
99
|
+
shoulder. Always one line. Append `\r` to submit. NEVER multi-line essay.
|
|
100
|
+
- `destroyTerminal(terminalId, requestId, reasoning)` — irreversible.
|
|
101
|
+
Prefer graceful `sendToTerminal('exit\r')`.
|
|
102
|
+
- `emitIntent({...})` — audit envelope for non-tool decisions.
|
|
103
|
+
|
|
104
|
+
Tool surface depends on host. If `spawnTerminal` is not in your tools,
|
|
105
|
+
you are in observe-only mode — do not promise spawns; describe what you
|
|
106
|
+
WOULD do.
|
|
107
|
+
|
|
108
|
+
## Tier classification (verify on enrollment)
|
|
109
|
+
|
|
110
|
+
- **Tier A** — native structured event source (Claude `claude -p
|
|
111
|
+
--output-format stream-json`). Full autonomy.
|
|
112
|
+
- **Tier B** — APT skill wrapping any CLI (`/apt:plan`, `/apt:execute`,
|
|
113
|
+
etc.). Full autonomy. THIS IS YOUR PRIMARY TARGET.
|
|
114
|
+
- **Tier C** — bare CLI / raw PTY. Capped to suggest-only regardless of
|
|
115
|
+
user autonomy setting. Mark intents `tier_capped: true`.
|
|
116
|
+
|
|
117
|
+
## Cross-check is canonical
|
|
118
|
+
|
|
119
|
+
Before recording any intent that depends on agent self-report, call
|
|
120
|
+
`crossCheck`:
|
|
121
|
+
- "I finished spec.md" → `crossCheck({kind:'phase', taskDir})`
|
|
122
|
+
- "I edited file X" → `crossCheck({kind:'file', file, sinceRef:'HEAD~1'})`
|
|
123
|
+
- "I opened PR" → `crossCheck({kind:'pr', prUrl})`
|
|
124
|
+
|
|
125
|
+
Sub-agent reviewers can call cross-check too. When uncertain, demand
|
|
126
|
+
evidence.
|
|
127
|
+
|
|
128
|
+
## Event log
|
|
129
|
+
|
|
130
|
+
Canonical envelope at `.aperant/events/YYYY-MM-DD.jsonl`. Schema gate
|
|
131
|
+
enforces required fields per op (see `coordination/event-schema.mjs`).
|
|
132
|
+
|
|
133
|
+
Locked op set:
|
|
134
|
+
`terminal.enrolled` `terminal.unenrolled` `phase.changed` `awaiting-input`
|
|
135
|
+
`input-rescinded` `artifact.ready` `heartbeat` `budget.exceeded`
|
|
136
|
+
`conductor.intent` `conductor.cross_check` `conductor.realignment`
|
|
137
|
+
|
|
138
|
+
Reserved meanings:
|
|
139
|
+
- `phase.changed.to` ∈ {busy, idle} ONLY (PTY state). NEVER use for plan
|
|
140
|
+
completion.
|
|
141
|
+
- `artifact.ready{kind:'plan'}` IS the plan-completion signal. Auto-
|
|
142
|
+
emitted by `apt-tools commit` when planner runs under a Conductor PTY
|
|
143
|
+
(`APERANT_TERMINAL_ID` set).
|
|
144
|
+
|
|
145
|
+
Every action you take appends an audit envelope. The framework writes
|
|
146
|
+
most of them for you when you call its tools.
|
|
147
|
+
|
|
148
|
+
## Output discipline
|
|
149
|
+
|
|
150
|
+
User-facing text per turn: one line per terminal you acted on, plus one
|
|
151
|
+
final summary. Examples:
|
|
152
|
+
|
|
153
|
+
- `T1: plan reviewed, 2 gaps → realignment sent (attempt 1).`
|
|
154
|
+
- `T3: plan approved → /apt:execute dispatched.`
|
|
155
|
+
- `T5: idle 8m, polling.`
|
|
156
|
+
- `Done. 4 tasks shipped, 1 wedged at T7 (handed back to you).`
|
|
157
|
+
|
|
158
|
+
NOT examples (forbidden):
|
|
159
|
+
- "I'll go ahead and spawn..."
|
|
160
|
+
- "Great question! Let me think through..."
|
|
161
|
+
- Multi-paragraph narration of your reasoning. Reason internally.
|
|
162
|
+
|
|
163
|
+
The chat thread is a control surface, not a journal.
|
|
164
|
+
|
|
165
|
+
## First turn
|
|
166
|
+
|
|
167
|
+
On first turn in a NEW thread (no prior assistant messages), one line:
|
|
168
|
+
|
|
169
|
+
`Conductor ready. Goal?`
|
|
170
|
+
|
|
171
|
+
Nothing else. No greeting paragraph. No tool list. The user knows what
|
|
172
|
+
you are.
|
package/skills/apt-plan/SKILL.md
CHANGED
|
@@ -416,6 +416,18 @@ The coverage check ensures every acceptance criterion has at least one subtask w
|
|
|
416
416
|
node packages/framework/bin/apt-tools.mjs commit "plan: create implementation plan for {task}" --files spec.md implementation_plan.json
|
|
417
417
|
```
|
|
418
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
|
+
|
|
419
431
|
## 9. Report
|
|
420
432
|
|
|
421
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`.
|
|
@@ -1017,6 +1017,8 @@ Map the user's selections to config values:
|
|
|
1017
1017
|
- "Ask me" → `pr_review.suggest_after_ship: "ask"`
|
|
1018
1018
|
- "Never" → `pr_review.suggest_after_ship: "never"`
|
|
1019
1019
|
|
|
1020
|
+
Note: task ids are slug-first since v0.6.6 — the date-format setting controls the trailing date component only.
|
|
1021
|
+
|
|
1020
1022
|
**Date Format:**
|
|
1021
1023
|
- "DD-MM-YY" → `preferences.date_format: "DD-MM-YY"`
|
|
1022
1024
|
- "MM-DD-YY" → `preferences.date_format: "MM-DD-YY"`
|
package/skills/apt-ship/SKILL.md
CHANGED
|
@@ -289,11 +289,13 @@ Capture the PR URL from the output into `pr_url` (for example, the last line of
|
|
|
289
289
|
**Record `pr_url` on the task record (C56 A2).** `/apt:close-task` and the auto-close-phase path in `task close` both resolve the PR number from this URL to poll `gh pr view` for merge state — without it, the closer side cannot run:
|
|
290
290
|
|
|
291
291
|
```bash
|
|
292
|
-
node packages/framework/bin/apt-tools.mjs task update . --id {task-id} --pr-url {PR_URL}
|
|
292
|
+
ship_update=$(node packages/framework/bin/apt-tools.mjs task update . --id {task-id} --pr-url {PR_URL})
|
|
293
293
|
```
|
|
294
294
|
|
|
295
295
|
This same call **atomically flips `lifecycle_phase` from `reviewing` to `shipped-pending-merge`** when the task is in `reviewing` and no explicit `--lifecycle-phase` flag is passed. Section 6 is now the single load-bearing step that both records the PR and transitions the lifecycle; Section 8 below documents the semantics but no longer issues a separate command.
|
|
296
296
|
|
|
297
|
+
It also evaluates `ci_watch.after_ship` and may arm the post-ship CI watcher. Preserve the JSON envelope in `ship_update`; Section 7.2 reads `ci_watch_armed` and `ci_watch_skip_reason` from it instead of issuing a second auto-start command.
|
|
298
|
+
|
|
297
299
|
Display the resolution so users see which branch/base was used:
|
|
298
300
|
|
|
299
301
|
```
|
|
@@ -352,29 +354,31 @@ suggest_mode=$(jq -r '.pr_review.suggest_after_ship // "always"' .aperant/config
|
|
|
352
354
|
|
|
353
355
|
### 7.2 Post-ship /apt:watch-ci hook
|
|
354
356
|
|
|
355
|
-
After Section 7.1's hint resolves (whether it ran the deep review or skipped),
|
|
357
|
+
After Section 7.1's hint resolves (whether it ran the deep review or skipped), report or interactively arm the post-ship CI watcher. The hook is controlled by `ci_watch.after_ship` in `.aperant/config.json` (tri-state: `auto` | `ask` | `never`). The default depends on host capability — `auto` on cron-capable hosts (Claude Code, Pi), `never` elsewhere.
|
|
356
358
|
|
|
357
359
|
**Skip entirely** when no PR URL was captured in Section 6 (library `npm publish`-only path — same skip rule as 7.1).
|
|
358
360
|
|
|
359
|
-
**Read
|
|
361
|
+
**Read the Section 6 task-update envelope first:**
|
|
360
362
|
|
|
361
363
|
```bash
|
|
364
|
+
ci_watch_armed=$(echo "$ship_update" | jq -r '.ci_watch_armed // false')
|
|
365
|
+
ci_watch_skip_reason=$(echo "$ship_update" | jq -r '.ci_watch_skip_reason // empty')
|
|
366
|
+
ci_watch_host=$(echo "$ship_update" | jq -r '.ci_watch.host // "unknown"')
|
|
367
|
+
ci_watch_deadline=$(echo "$ship_update" | jq -r '.ci_watch.deadline // empty')
|
|
362
368
|
host_cron=$(node packages/framework/bin/apt-tools.mjs host-detect | jq -r '.host.capabilities.cron')
|
|
363
|
-
after_ship_default=$([ "$host_cron" = "true" ] && echo "auto" || echo "never")
|
|
364
|
-
after_ship_mode=$(jq -r --arg d "$after_ship_default" '.ci_watch.after_ship // $d' .aperant/config.json)
|
|
365
369
|
```
|
|
366
370
|
|
|
367
371
|
**Autonomy interaction** (apply BEFORE branching, same rule as 7.1): when `autonomy === 3` (YOLO), degrade `ask` → `auto`.
|
|
368
372
|
|
|
369
|
-
**Branch on
|
|
373
|
+
**Branch on the task-update envelope:**
|
|
370
374
|
|
|
371
|
-
- **`
|
|
375
|
+
- **`ci_watch_armed=true` AND `host_cron=true`** — emit:
|
|
372
376
|
|
|
373
377
|
```
|
|
374
|
-
[APT:ship] CI watcher armed (host cron: {
|
|
378
|
+
[APT:ship] CI watcher armed (host cron: {ci_watch_host}). Deadline: {ci_watch_deadline}. Stop: /apt:watch-ci --stop --pr {N}.
|
|
375
379
|
```
|
|
376
380
|
|
|
377
|
-
- **`
|
|
381
|
+
- **`ci_watch_armed=true` AND `host_cron=false`** — emit:
|
|
378
382
|
|
|
379
383
|
```
|
|
380
384
|
[APT:ship] CI watcher state created (host has no cron; advance manually: /apt:watch-ci --tick --pr {N}).
|
|
@@ -382,15 +386,26 @@ after_ship_mode=$(jq -r --arg d "$after_ship_default" '.ci_watch.after_ship // $
|
|
|
382
386
|
|
|
383
387
|
This is the honest-gap surface per D-03 — we never lie about cron-capability.
|
|
384
388
|
|
|
385
|
-
- **`ask`** — emit:
|
|
389
|
+
- **`ci_watch_skip_reason=ask-deferred`** — emit:
|
|
386
390
|
|
|
387
391
|
```
|
|
388
392
|
[APT:ship] Arm CI watcher for PR {N} now? [Y/n]
|
|
389
393
|
```
|
|
390
394
|
|
|
391
|
-
On `Y` (or empty enter),
|
|
395
|
+
On `Y` (or empty enter), call:
|
|
392
396
|
|
|
393
|
-
|
|
397
|
+
```bash
|
|
398
|
+
node packages/framework/bin/apt-tools.mjs ci-watch start . --pr {pr_number} --task-id {task-id} --host {cli}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Then emit the same host-cron-aware success banner used for `ci_watch_armed=true`. On `N` or any other response, proceed silently to Section 8.
|
|
402
|
+
|
|
403
|
+
- **`ci_watch_skip_reason=disabled`** — silent. Proceed directly to Section 8.
|
|
404
|
+
|
|
405
|
+
- **Any other skip reason** — emit:
|
|
406
|
+
```
|
|
407
|
+
[APT:ship] CI watcher not armed: {ci_watch_skip_reason}
|
|
408
|
+
```
|
|
394
409
|
|
|
395
410
|
Section 7.2 is purely additive — it does not affect Section 7.1's `pr_review.suggest_after_ship` policy or any other config block.
|
|
396
411
|
|