@webpresso/agent-kit 3.1.26 → 3.1.28
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/catalog/AGENTS.md.tpl +6 -10
- package/catalog/agent/commands/verify.md +2 -2
- package/catalog/agent/rules/changeset-release.md +4 -2
- package/catalog/agent/rules/workflow-skills-routing.md +6 -3
- package/catalog/agent/skills/autopilot/SKILL.md +48 -11
- package/catalog/agent/skills/claude/SKILL.md +7 -0
- package/catalog/agent/skills/codex/SKILL.md +7 -0
- package/catalog/agent/skills/fix/SKILL.md +33 -8
- package/catalog/agent/skills/grok/SKILL.md +7 -0
- package/catalog/agent/skills/investigate/SKILL.md +12 -1
- package/catalog/agent/skills/pll/SKILL.md +53 -48
- package/catalog/agent/skills/team/SKILL.md +26 -9
- package/catalog/agent/skills/ultragoal/SKILL.md +147 -19
- package/catalog/agent/skills/verify/SKILL.md +71 -51
- package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +8 -0
- package/dist/esm/audit/blueprint-lifecycle-sql.js +25 -1
- package/dist/esm/ci/native-session-memory-cache.d.ts +9 -1
- package/dist/esm/ci/native-session-memory-cache.js +9 -1
- package/dist/esm/ci/vitest-ci-shards.d.ts +6 -4
- package/dist/esm/ci/vitest-ci-shards.js +6 -4
- package/dist/esm/cli/auto-update/guard-tombstone.d.ts +25 -0
- package/dist/esm/cli/auto-update/guard-tombstone.js +67 -0
- package/dist/esm/cli/auto-update/installer.d.ts +4 -17
- package/dist/esm/cli/auto-update/installer.js +6 -57
- package/dist/esm/cli/auto-update/self-invocation.d.ts +37 -0
- package/dist/esm/cli/auto-update/self-invocation.js +62 -0
- package/dist/esm/cli/commands/audit.js +1 -0
- package/dist/esm/cli/commands/dash/index.js +3 -3
- package/dist/esm/cli/commands/dash/plan-once-attention.d.ts +32 -0
- package/dist/esm/cli/commands/dash/plan-once-attention.js +50 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.d.ts +73 -0
- package/dist/esm/cli/commands/dash/plan-once-schema.js +119 -0
- package/dist/esm/cli/commands/dash/plan-once.d.ts +122 -0
- package/dist/esm/cli/commands/dash/plan-once.js +224 -0
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.d.ts +87 -0
- package/dist/esm/cli/commands/dash/tui/ipc-protocol.js +128 -0
- package/dist/esm/cli/commands/dash/tui/native-host.d.ts +34 -0
- package/dist/esm/cli/commands/dash/tui/native-host.js +256 -0
- package/dist/esm/cli/commands/dash/tui/native-path.d.ts +11 -0
- package/dist/esm/cli/commands/dash/tui/native-path.js +41 -0
- package/dist/esm/cli/commands/dash/tui/runtime.js +72 -0
- package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +1 -1
- package/dist/esm/cli/commands/package-manager.js +2 -1
- package/dist/esm/cli/commands/self-install-guard.d.ts +14 -32
- package/dist/esm/cli/commands/self-install-guard.js +17 -63
- package/dist/esm/hooks/guard-switch/index.js +8 -4
- package/dist/esm/hooks/post-tool/lint-after-edit.js +6 -4
- package/dist/esm/hooks/precompact/index.js +5 -3
- package/dist/esm/hooks/sessionstart/index.d.ts +10 -0
- package/dist/esm/hooks/sessionstart/index.js +61 -4
- package/dist/esm/hooks/shared/types.d.ts +11 -0
- package/dist/esm/hooks/shared/types.js +21 -0
- package/dist/esm/paths/state-root.js +6 -0
- package/dist/esm/session-memory/current-session.js +2 -0
- package/dist/esm/session-memory/native-runtime.js +5 -3
- package/dist/esm/session-memory/native-warm-markers.d.ts +18 -0
- package/dist/esm/session-memory/native-warm-markers.js +22 -0
- package/dist/esm/session-memory/sync/types.d.ts +4 -0
- package/dist/esm/session-memory/types.d.ts +3 -1
- package/dist/esm/session-memory/types.js +2 -0
- package/dist/esm/ultragoal/runtime.js +44 -2
- package/package.json +15 -12
|
@@ -5,9 +5,9 @@ title: Ultragoal
|
|
|
5
5
|
status: active
|
|
6
6
|
scope: repo
|
|
7
7
|
applies_to: [agents]
|
|
8
|
-
related: [autopilot, plan-refine, verify]
|
|
8
|
+
related: [autopilot, plan-refine, verify, pll, fix, opencode-go]
|
|
9
9
|
created: "2026-07-10"
|
|
10
|
-
last_reviewed: "2026-07-
|
|
10
|
+
last_reviewed: "2026-07-21"
|
|
11
11
|
name: ultragoal
|
|
12
12
|
description: "Run durable multi-blueprint ultragoals through evidence-gated handoffs."
|
|
13
13
|
argument-hint: "<new|status|handoff|run|cancel> [brief]"
|
|
@@ -15,30 +15,158 @@ argument-hint: "<new|status|handoff|run|cancel> [brief]"
|
|
|
15
15
|
|
|
16
16
|
# Ultragoal
|
|
17
17
|
|
|
18
|
-
Use `wp ultragoal` as the durable controller for work spanning
|
|
18
|
+
Use `wp ultragoal` / MCP `wp_ultragoal_*` as the durable controller for work spanning
|
|
19
|
+
one or more blueprints. Prefer this spine over host-local mega-sessions or ad-hoc
|
|
20
|
+
multi-agent swarms.
|
|
21
|
+
|
|
22
|
+
## Default budgets (override only when the user sets them)
|
|
23
|
+
|
|
24
|
+
| Budget | Default | Meaning |
|
|
25
|
+
| --------------- | --------- | ---------------------------------------------------------- |
|
|
26
|
+
| `concurrency` | 4 (max 8) | Parallel ready tasks / implementer lanes |
|
|
27
|
+
| `fix_budget` | 1 | Pre-existing issues fixable via `/fix` this phase |
|
|
28
|
+
| `review_budget` | 1 | Outside-voice reviewers for merge-ready (0 for local work) |
|
|
29
|
+
| `loop` | off | Do not run `/loop` or unbounded stop-hooks |
|
|
30
|
+
|
|
31
|
+
Reject unbudgeted sleep-mode briefs (“complete all”, “full autopilot”, “go to sleep”)
|
|
32
|
+
unless they name a blueprint/slug, budgets, and a stop condition. Route vague briefs
|
|
33
|
+
through `plan-refine` first (or require `force:` only when the user explicitly opts out).
|
|
34
|
+
|
|
35
|
+
## Tooling map (use these; do not reimplement with Bash)
|
|
36
|
+
|
|
37
|
+
| Phase | Prefer MCP / CLI | Purpose |
|
|
38
|
+
| ---------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
|
39
|
+
| Create / resume | `wp_ultragoal_new`, `wp_ultragoal_status` | Durable controller state |
|
|
40
|
+
| Isolation | `wp_worktree` | Owner / lane worktrees; never primary as controller |
|
|
41
|
+
| Blueprint read | `wp_blueprint_list`, `wp_blueprint_get`, `wp_blueprint_context` | Ready-set and deps |
|
|
42
|
+
| Blueprint write | `wp_blueprint_put`, `wp_blueprint_transition` | Spec edits (MCP-only for blueprints) |
|
|
43
|
+
| Task done | `wp_blueprint_task_verify` only | Evidence-gated completion |
|
|
44
|
+
| Parallel execute | `/pll` or ready-queue + host subagents | Max parallel when deps allow |
|
|
45
|
+
| Context-light delegate | `wp_session_context` | Manifest for subagents (no history paste) |
|
|
46
|
+
| Continuity | `wp_session_capture`, `wp_session_search`, `wp_session_restore`, `wp_session_snapshot` | Decisions / resume |
|
|
47
|
+
| Large command / file | `wp_session_execute`, `wp_session_batch_execute`, `wp_session_execute_file` | Bounded output + index |
|
|
48
|
+
| QA | `wp_qa` (or `wp_lint` + `wp_typecheck` + `wp_test`) | Affected quality gates |
|
|
49
|
+
| PR / land | `wp_pr_upsert`, `wp_pr_status`, `wp_pr_wait` | Open early; wait on required checks |
|
|
50
|
+
| Fleet / workers | `wp_fleet_status`, `wp_worker_tail` | Multi-session visibility |
|
|
51
|
+
| Token gain | `wp_gain` | Optional efficiency check after heavy execute |
|
|
52
|
+
| Advance loop | `wp_ultragoal_run`, `wp_ultragoal_handoff`, `wp_ultragoal_cancel` | Controller steps only |
|
|
53
|
+
|
|
54
|
+
Fallback to `wp …` CLI only when the matching MCP tool is unavailable. Prefer `wp` >
|
|
55
|
+
`vp` > raw package managers. Never raise timeouts to hide hangs.
|
|
19
56
|
|
|
20
57
|
## Protocol
|
|
21
58
|
|
|
22
|
-
1. Create or resume the ultragoal in a managed blueprint owner worktree (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
59
|
+
1. Create or resume the ultragoal in a **managed blueprint owner worktree** (`wp_worktree` /
|
|
60
|
+
`wp blueprint start`). Never use `main` or the primary checkout as controller.
|
|
61
|
+
2. Print the **ready-set**: tasks whose dependencies are satisfied (from blueprint tools).
|
|
62
|
+
3. Launch up to `concurrency` independent ready tasks in parallel (worktree-isolated).
|
|
63
|
+
Serialize only when file ownership overlaps or deps require it.
|
|
64
|
+
4. Execute only the current phase handoff; call `wp_ultragoal_run` again after evidence.
|
|
65
|
+
5. Mark tasks done **only** via `wp_blueprint_task_verify` with passing evidence.
|
|
66
|
+
6. **Opportunistic `/fix`:** at most `fix_budget` pre-existing issues per phase, each with
|
|
67
|
+
named invariant + failing proof. Excess → handoff backlog (do not expand epic).
|
|
68
|
+
7. **Validate / land:** local proof with `wp_qa` / targeted tools; outside review only when
|
|
69
|
+
merge-ready and within `review_budget` (default **exactly 1** sequential outside voice).
|
|
70
|
+
Prefer `wp review gate` for lifecycle authority. Use `wp_pr_*` for PR babysit — no
|
|
71
|
+
multi-sleep poll loops; no parallel multi-reviewer stampede.
|
|
72
|
+
8. Stop on `complete`, `cancelled`, blocked guard exhaustion, or `WP_ULTRAGOAL_DISABLE=1`.
|
|
73
|
+
|
|
74
|
+
The blueprint engine owns task status and approval gates. The ultragoal controller must
|
|
75
|
+
never self-approve, directly mark a task done, bypass review provenance, or mutate the
|
|
76
|
+
primary checkout.
|
|
77
|
+
|
|
78
|
+
## Failure / cascade
|
|
79
|
+
|
|
80
|
+
- Hard fail on a task → mark blocked with reason; **cascade-skip** dependents that cannot
|
|
81
|
+
proceed; continue independent ready work.
|
|
82
|
+
- Lifecycle mutation failure → stop (do not continue on stale plan state).
|
|
83
|
+
- On block: call `wp_ultragoal_handoff` and emit a **≤40-line handoff**: goal, done, blockers,
|
|
84
|
+
evidence refs (`wp_session_*` ids if any), next 3 commands. Do not paste full transcripts.
|
|
85
|
+
|
|
86
|
+
## Outside-voice review (required for autopilot)
|
|
87
|
+
|
|
88
|
+
Autopilot and agent-driven ultragoal loops **must** request an **OpenCode Go** outside-voice review after each **goal/phase milestone**, and must pick the model by purpose. Direct `wp review run` output is advisory only. Lifecycle authority that can satisfy promotion/completion gates comes only from a converged **`wp review gate`** (content-addressed ledger + bound artifact).
|
|
89
|
+
|
|
90
|
+
Count each milestone review against `review_budget` for merge-ready claims: **exactly one sequential** reviewer path unless the user sets N. Prefer purpose-matched OpenCode Go first; do not fan out multi-host review swarms.
|
|
91
|
+
|
|
92
|
+
### Milestones that require a review
|
|
93
|
+
|
|
94
|
+
Run a distinct OpenCode Go review (via `wp review gate` when the milestone is a promotion/approval gate; otherwise `wp review gate` or a purpose-matched gate resume) after each of:
|
|
95
|
+
|
|
96
|
+
| Milestone | When |
|
|
97
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| Plan gate | Before `draft` → `planned` / when ultragoal phase is `plan` and promotion is required |
|
|
99
|
+
| Phase advance | After ultragoal advances `plan` → `execute`, `execute` → `qa`, `qa` → `validate`, `validate` → `land`, or lands `complete` |
|
|
100
|
+
| Task batch handoff | After a meaningful execute batch when the phase remains `execute` (at least once per blueprint before claiming execute-complete) |
|
|
101
|
+
|
|
102
|
+
Do **not** invent ledger approvals. If OpenCode Go is unavailable or hits a provider-wide usage limit, capture the failure evidence and stop; do not substitute a forged approval.
|
|
103
|
+
|
|
104
|
+
### Purpose → model routing (no hardcoding IDs)
|
|
105
|
+
|
|
106
|
+
Resolve models from the live catalog every time:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
opencode models opencode-go
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Pick by purpose (same intent as the committed OpenCode reviewer policy / `opencode-go` skill):
|
|
113
|
+
|
|
114
|
+
| Purpose | Preferred family (live catalog) | Why |
|
|
115
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------- |
|
|
116
|
+
| Plan / architecture critique | DeepSeek **Pro** (`opencode-go/deepseek…-pro`) | Deeper plan review depth |
|
|
117
|
+
| Coding / implementation quality | Kimi **Code** first (`…kimi…-code`) | Coding quality lane |
|
|
118
|
+
| Cheap recheck / high-availability follow-up | DeepSeek **Flash** (`…deepseek…-flash`) | Fast secondary pass |
|
|
119
|
+
| Aggregate / unspecified | Follow `opencode-go` skill order: Kimi Code → DeepSeek Pro → DeepSeek Flash → remaining families | Default outside-voice lane |
|
|
120
|
+
|
|
121
|
+
Resolve the actual model ID with catalog greps (never paste a fixed model string into agent instructions as the only option):
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
CATALOG=$(opencode models opencode-go)
|
|
125
|
+
# plan critique example:
|
|
126
|
+
MODEL=$(echo "$CATALOG" | grep '^opencode-go/deepseek' | grep -- '-pro$' | sort -V | tail -1)
|
|
127
|
+
# coding example:
|
|
128
|
+
# MODEL=$(echo "$CATALOG" | grep '^opencode-go/kimi' | grep -- '-code$' | sort -V | tail -1)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Treat a provider-wide usage limit as terminal for every OpenCode Go model in the current review window; do not hop families to evade a usage block on the same provider.
|
|
132
|
+
|
|
133
|
+
### Gate invocation shape
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
wp review gate <blueprint-slug> \
|
|
137
|
+
--purpose plan|delivery \
|
|
138
|
+
--provider opencode \
|
|
139
|
+
--model "$MODEL" \
|
|
140
|
+
--effort medium|high \
|
|
141
|
+
--target HEAD \
|
|
142
|
+
--json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Use `--purpose plan` for plan-phase promotion and `--purpose delivery` for implementation/delivery validation. Resume interrupted gates with `--resume <gate-id>` against the same immutable target.
|
|
146
|
+
|
|
147
|
+
### Honesty rules (non-negotiable)
|
|
26
148
|
|
|
27
|
-
|
|
149
|
+
- Never self-approve or hand-edit `reviews.md` / `review-events.jsonl` / frontmatter approvals to fake OpenCode Go authority.
|
|
150
|
+
- Never mark blueprint tasks done except through `wp_blueprint_task_verify` with real evidence.
|
|
151
|
+
- Never run ultragoal mutations on `main` or a primary checkout; use the managed blueprint owner worktree.
|
|
152
|
+
- Keep every loop bounded and never increase timeouts.
|
|
153
|
+
- When the controller returns `waiting` (`blueprint-promotion`, `approval-gate`, `blueprint-tasks`, …), fix the named gap; do not spin `wp ultragoal run` without progress.
|
|
28
154
|
|
|
29
155
|
## Tooling-aligned evidence (QA / land)
|
|
30
156
|
|
|
31
|
-
- **QA phase** prefers **GitHub required checks** for the worktree PR (`
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
- **Land** still requires a **MERGED** PR with green required checks bound to the projected source snapshot.
|
|
157
|
+
- **QA phase** prefers **GitHub required checks** for the worktree PR (`wp_pr_status` /
|
|
158
|
+
`wp_pr_wait` or `gh pr checks --required`) when PR is `OPEN`/`MERGED`, checks green, and
|
|
159
|
+
PR head matches clean worktree HEAD.
|
|
160
|
+
- If no PR-bound green CI is available, fall back to local **`wp_qa`**.
|
|
161
|
+
- Open a PR early so CI can satisfy QA. Do **not** raise timeouts.
|
|
162
|
+
- **Land** still requires a **MERGED** PR with green required checks bound to the projected
|
|
163
|
+
source snapshot. Use `/verify --merge-ready` (review_budget=1), not default local verify.
|
|
39
164
|
|
|
40
165
|
## Snapshot / dirty worktree
|
|
41
166
|
|
|
42
|
-
- Ultragoal ledger appends to blueprint `reviews.md` / `review-events.jsonl` /
|
|
43
|
-
|
|
44
|
-
-
|
|
167
|
+
- Ultragoal ledger appends to blueprint `reviews.md` / `review-events.jsonl` /
|
|
168
|
+
`review-artifacts/**`.
|
|
169
|
+
- These paths under both `blueprints/**` and monorepo `webpresso/blueprints/**` are
|
|
170
|
+
**evidence-only dirt** and must not fail `createCleanSourceSnapshot`.
|
|
171
|
+
- Dirty **source** paths (including `_overview.md` task status edits) still fail closed
|
|
172
|
+
until committed. Use `wp_session_snapshot` before risky branch switches.
|
|
@@ -7,10 +7,10 @@ scope: repo
|
|
|
7
7
|
applies_to: [agents]
|
|
8
8
|
related: [testing-philosophy, tph]
|
|
9
9
|
created: "2026-05-07"
|
|
10
|
-
last_reviewed: "2026-07-
|
|
10
|
+
last_reviewed: "2026-07-21"
|
|
11
11
|
name: verify
|
|
12
12
|
description: "Post-implementation quality gate: run checks, TPH audit, cleanup, docs, proof."
|
|
13
|
-
argument-hint: "<target> [--full] where target is: package|file|plan-slug|all"
|
|
13
|
+
argument-hint: "<target> [--full|--merge-ready] where target is: package|file|plan-slug|all"
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# Verify
|
|
@@ -21,6 +21,33 @@ Post-implementation quality gate. Run after implementation exists, before claimi
|
|
|
21
21
|
repair. `/verify` owns the broader question: **is this work actually complete,
|
|
22
22
|
integrated, and free of stale garbage?**
|
|
23
23
|
|
|
24
|
+
## Modes
|
|
25
|
+
|
|
26
|
+
| Invocation | Outside voice | When |
|
|
27
|
+
| -------------------------------- | ---------------------------------- | ------------------------------ |
|
|
28
|
+
| `/verify <target>` (default) | **0** | Local completeness / iteration |
|
|
29
|
+
| `/verify <target> --full` | **0** (broader local gates) | Full local QA bookend |
|
|
30
|
+
| `/verify <target> --merge-ready` | **exactly 1** (unless user sets N) | Claiming merge-ready / land |
|
|
31
|
+
|
|
32
|
+
Default `/verify` must **not** spawn outside reviewers. That stampede is a known
|
|
33
|
+
token/time failure mode. Merge-ready runs **one** sequential outside voice via
|
|
34
|
+
the preferred skill (`claude` / `codex` / `grok` / one OpenCode Go), then stops.
|
|
35
|
+
|
|
36
|
+
## Tooling map
|
|
37
|
+
|
|
38
|
+
| Gate | Prefer |
|
|
39
|
+
| ------------------------- | --------------------------------------------------------------- |
|
|
40
|
+
| Lint / types / tests / QA | `wp_lint`, `wp_typecheck`, `wp_test`, `wp_qa` |
|
|
41
|
+
| Format | `wp_format` |
|
|
42
|
+
| Audits | `wp_audit`, `wp_audits` |
|
|
43
|
+
| Blueprint | blueprint MCP tools + `wp audit blueprint-lifecycle` |
|
|
44
|
+
| PR / CI wait | `wp_pr_status`, `wp_pr_wait` (not multi-sleep loops) |
|
|
45
|
+
| Release | `wp_release_readiness` when shipping |
|
|
46
|
+
| Large output | `wp_session_execute` / `batch_execute` / `execute_file` |
|
|
47
|
+
| Continuity | `wp_session_capture` for verify summary; avoid paste-back walls |
|
|
48
|
+
| E2E / act | `wp_e2e`, `wp_ci_act` when the change requires them |
|
|
49
|
+
| Outside authority | `wp review gate` (not raw multi-agent review swarms) |
|
|
50
|
+
|
|
24
51
|
## Iron law — evidence before claims
|
|
25
52
|
|
|
26
53
|
No completion claim without fresh verification evidence.
|
|
@@ -40,15 +67,15 @@ Not sufficient: "should pass", "looks correct", lint-only evidence for runtime c
|
|
|
40
67
|
```bash
|
|
41
68
|
/verify <target>
|
|
42
69
|
/verify <target> --full
|
|
70
|
+
/verify <target> --merge-ready
|
|
43
71
|
```
|
|
44
72
|
|
|
45
73
|
`<target>` is a file path, package name, blueprint slug, or `all`.
|
|
46
74
|
|
|
47
75
|
Follow the repo's current routing and command surface:
|
|
48
76
|
|
|
49
|
-
- use repo-owned quality wrappers first
|
|
50
|
-
- use
|
|
51
|
-
- use bounded large-output tooling when the repo instructs it
|
|
77
|
+
- use MCP `wp_*` / repo-owned quality wrappers first
|
|
78
|
+
- use bounded session-memory tooling for large output
|
|
52
79
|
- reuse fresh logs instead of re-running broad commands just to inspect output
|
|
53
80
|
|
|
54
81
|
## Folded health dashboard
|
|
@@ -98,17 +125,17 @@ Hard stop on any failure.
|
|
|
98
125
|
|
|
99
126
|
Run the narrowest checks that prove the touched behavior:
|
|
100
127
|
|
|
101
|
-
- targeted lint
|
|
102
|
-
- targeted typecheck
|
|
103
|
-
- targeted tests
|
|
104
|
-
-
|
|
128
|
+
- `wp_lint` / targeted lint
|
|
129
|
+
- `wp_typecheck` / targeted typecheck
|
|
130
|
+
- `wp_test` / targeted tests
|
|
131
|
+
- `wp_qa`, `wp_e2e`, build / package checks only when the change requires them
|
|
105
132
|
|
|
106
133
|
Rules:
|
|
107
134
|
|
|
108
|
-
- Prefer
|
|
109
|
-
- Reuse fresh logs if the runner auto-saves them.
|
|
135
|
+
- Prefer MCP `wp_*` over raw underlying tools.
|
|
136
|
+
- Reuse fresh logs / session-memory indexed output if the runner auto-saves them.
|
|
110
137
|
- Never claim broader correctness than the commands actually proved.
|
|
111
|
-
- If the repo documents a "full QA" bookend, reserve
|
|
138
|
+
- If the repo documents a "full QA" bookend, reserve `wp_qa` / `--full` for the final broad pass rather than every iteration.
|
|
112
139
|
|
|
113
140
|
## Phase 3 — Cross-surface impact scan
|
|
114
141
|
|
|
@@ -161,59 +188,52 @@ cleanup, route that pass through `ai-deslop` first rather than broadening
|
|
|
161
188
|
|
|
162
189
|
This phase exists to catch the garbage that often slips in beside otherwise-correct work.
|
|
163
190
|
|
|
164
|
-
## Phase 6 — Outside-model approval gate
|
|
191
|
+
## Phase 6 — Outside-model approval gate (**`--merge-ready` only**)
|
|
192
|
+
|
|
193
|
+
**Skip this entire phase** for default `/verify` and `/verify --full`. Local
|
|
194
|
+
`done` claims do not require outside voice.
|
|
165
195
|
|
|
166
|
-
Before claiming merge-ready
|
|
167
|
-
user explicitly asked for a different approval count or reviewer mix.
|
|
196
|
+
Before claiming **merge-ready**, obtain outside-voice approvals only under this policy:
|
|
168
197
|
|
|
169
|
-
Default policy:
|
|
198
|
+
Default merge-ready policy:
|
|
170
199
|
|
|
171
|
-
- Require **one extra model approval
|
|
172
|
-
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
200
|
+
- Require **exactly one** extra model approval unless the user sets a different N.
|
|
201
|
+
- At most **one OpenCode Go reviewer** counts toward the requirement unless the user
|
|
202
|
+
explicitly asks for multiple OpenCode models.
|
|
203
|
+
- Run reviewers **sequentially** (try next only if current unavailable). Never fan out
|
|
204
|
+
parallel multi-host review swarms.
|
|
205
|
+
- If the user asks for more, fewer, zero, or specific reviewers, follow that instruction
|
|
206
|
+
and report the chosen requirement.
|
|
207
|
+
- These approvals are model outside-voice approvals, not a substitute for human GitHub
|
|
208
|
+
reviews or branch-protection approvals.
|
|
176
209
|
|
|
177
|
-
Reviewer preference:
|
|
210
|
+
Reviewer preference (pick **one** path):
|
|
178
211
|
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`$agent-kit:claude`, `$agent-kit:codex`, `$agent-kit:grok`, and one OpenCode Go reviewer
|
|
185
|
-
skills such as `$agent-kit:opencode-go`, `$agent-kit:qwen`,
|
|
186
|
-
`$agent-kit:deepseek`, `$agent-kit:glm`, `$agent-kit:kimi`,
|
|
187
|
-
`$agent-kit:minimax`, or `$agent-kit:mimo`.
|
|
212
|
+
- From Codex → Claude or Grok (else one OpenCode Go).
|
|
213
|
+
- From Claude → Codex or Grok (else one OpenCode Go).
|
|
214
|
+
- From Grok → Claude or Codex (else one OpenCode Go).
|
|
215
|
+
- Prefer skills: `claude`, `codex`, `grok`, or one of `opencode-go` / `qwen` /
|
|
216
|
+
`deepseek` / `glm` / `kimi` / `minimax` / `mimo`.
|
|
188
217
|
|
|
189
218
|
Approval evidence requirements:
|
|
190
219
|
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
196
|
-
|
|
197
|
-
- Record outside approval evidence as PR comments when a PR exists.
|
|
198
|
-
- Each PR comment must include the approving model/tool name, provider/family
|
|
199
|
-
when known, verdict, reviewed commit or branch, and any blockers or caveats.
|
|
200
|
-
- If there is no PR yet, record the same evidence in the final Verify report and
|
|
201
|
-
add the PR comments once the PR exists before calling the PR merge-ready.
|
|
202
|
-
- If an outside reviewer is unavailable (not installed, not logged in, missing
|
|
203
|
-
model, timeout after the reviewer skill's allowed retry path), do not silently
|
|
204
|
-
count it. Try the next preferred reviewer. If the required count still cannot
|
|
205
|
-
be met, report the exact approval gap and say the work is **not merge-ready**.
|
|
220
|
+
- Blueprint lifecycle: `wp review gate <blueprint-slug> --target HEAD --json` first.
|
|
221
|
+
Use `wp review log` / `wp review read` for inspection.
|
|
222
|
+
- Each reviewer must return clear `APPROVED`/`BLOCKED` with enough evidence.
|
|
223
|
+
- Record as PR comments when a PR exists (model/tool, verdict, reviewed commit).
|
|
224
|
+
- Unavailable reviewer → try next preferred; if still short, report gap and
|
|
225
|
+
**not merge-ready** (never invent approvals).
|
|
206
226
|
|
|
207
227
|
## Phase 7 — Final completion statement
|
|
208
228
|
|
|
209
229
|
Report:
|
|
210
230
|
|
|
211
|
-
-
|
|
212
|
-
- which commands/logs prove it
|
|
213
|
-
- which docs/help/instruction surfaces were refreshed when
|
|
214
|
-
-
|
|
231
|
+
- mode used (`local` / `full` / `merge-ready`)
|
|
232
|
+
- what was verified and which `wp_*` commands/logs prove it
|
|
233
|
+
- which docs/help/instruction surfaces were refreshed when guidance changed
|
|
234
|
+
- outside models only if merge-ready (with PR comment links when applicable)
|
|
215
235
|
- what remains intentionally out of scope
|
|
216
236
|
|
|
217
|
-
When catalog assets
|
|
237
|
+
When catalog assets or generated instruction surfaces changed, include public-package-safety or package-surface leak checks.
|
|
218
238
|
|
|
219
239
|
If any required check is missing, the correct result is **not done yet**, not a softer claim.
|
|
@@ -26,5 +26,13 @@ export interface BlueprintLifecycleAuditOptions {
|
|
|
26
26
|
readonly baseRef?: string;
|
|
27
27
|
/** Restrict expensive/error-producing checks to blueprints touched in git. */
|
|
28
28
|
readonly changedOnly?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* When set (from `wp audit --affected` / pre-commit staged files), restrict
|
|
31
|
+
* changed-only scope to blueprints that appear in this path set.
|
|
32
|
+
*
|
|
33
|
+
* Without this filter, porcelain includes untracked drafts and can fail an
|
|
34
|
+
* unrelated skill/docs commit that never staged any blueprint.
|
|
35
|
+
*/
|
|
36
|
+
readonly affectedFiles?: readonly string[];
|
|
29
37
|
}
|
|
30
38
|
export declare function auditBlueprintLifecycleSql(cwd?: string, options?: BlueprintLifecycleAuditOptions): Promise<RepoAuditResult>;
|
|
@@ -369,6 +369,27 @@ function changedBlueprintScope(candidates) {
|
|
|
369
369
|
}
|
|
370
370
|
return { slugs };
|
|
371
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* When `--affected` supplies an explicit file set (pre-commit staged files or
|
|
374
|
+
* branch ACMR list), only keep blueprint transition candidates that touch
|
|
375
|
+
* those paths. Untracked WIP drafts outside the set must not fail the commit.
|
|
376
|
+
*
|
|
377
|
+
* `affectedFiles === undefined` keeps the full porcelain candidate map (CLI
|
|
378
|
+
* `wp audit blueprint-lifecycle --changed-only` without a staged filter).
|
|
379
|
+
*/
|
|
380
|
+
function filterTransitionCandidatesByAffectedFiles(candidates, affectedFiles) {
|
|
381
|
+
if (affectedFiles === undefined)
|
|
382
|
+
return candidates;
|
|
383
|
+
const allowed = new Set(affectedFiles.map((file) => normalizeGitPath(file)));
|
|
384
|
+
const filtered = new Map();
|
|
385
|
+
for (const [currentPath, candidate] of candidates) {
|
|
386
|
+
const paths = [currentPath, ...candidate.previousPaths].map(normalizeGitPath);
|
|
387
|
+
if (paths.some((p) => allowed.has(p))) {
|
|
388
|
+
filtered.set(currentPath, candidate);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return filtered;
|
|
392
|
+
}
|
|
372
393
|
function violationTouchesBlueprintScope(violation, scope) {
|
|
373
394
|
if (!violation.file)
|
|
374
395
|
return false;
|
|
@@ -422,7 +443,10 @@ export async function auditBlueprintLifecycleSql(cwd = process.cwd(), options =
|
|
|
422
443
|
const changedCandidateMap = gitHistoryAvailable
|
|
423
444
|
? listChangedBlueprintCandidates(cwd, { baseRef: options.baseRef })
|
|
424
445
|
: null;
|
|
425
|
-
const
|
|
446
|
+
const scopedCandidateMap = changedCandidateMap === null
|
|
447
|
+
? null
|
|
448
|
+
: filterTransitionCandidatesByAffectedFiles(changedCandidateMap, options.affectedFiles);
|
|
449
|
+
const changedScope = scopedCandidateMap === null ? null : changedBlueprintScope(scopedCandidateMap);
|
|
426
450
|
// Review-evidence append-only enforcement (base-vs-head ledger prefix check).
|
|
427
451
|
// Runs BEFORE the changed-only early returns: a PR that only rewrites a
|
|
428
452
|
// review-events.jsonl touches zero blueprint documents, so changedScope is
|
|
@@ -26,7 +26,15 @@ export declare const NATIVE_SESSION_MEMORY_TRUST_CACHED_NODE_ENV = "WP_NATIVE_SE
|
|
|
26
26
|
* Absolute cache dir still comes from env-paths / CACHE_ROOT override at runtime.
|
|
27
27
|
*/
|
|
28
28
|
export declare const NATIVE_SESSION_MEMORY_CACHE_HASH_GLOBS: readonly ["native/session-memory-engine/Cargo.lock", "native/session-memory-engine/Cargo.toml", "native/session-memory-engine/crates/**/*.rs", "native/session-memory-engine/crates/**/Cargo.toml"];
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Default **env-paths** Linux cache location when `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT`
|
|
31
|
+
* is unset (`$HOME/.cache/webpresso-agent-kit/session-memory-engine`).
|
|
32
|
+
*
|
|
33
|
+
* Agent-kit self-CI does **not** use this path for the warm cache: it overrides via
|
|
34
|
+
* `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT` → `${{ runner.temp }}/sm-native-cache` (see
|
|
35
|
+
* the Test job warm cache step in `.github/workflows/ci.agent-kit.yml`). This helper
|
|
36
|
+
* documents the unset-override default only — not the workflow `path:`.
|
|
37
|
+
*/
|
|
30
38
|
export declare function defaultLinuxNativeSessionMemoryCachePath(home?: string): string;
|
|
31
39
|
/**
|
|
32
40
|
* Trust is only safe on an exact primary-key GHA cache hit (sources match the key).
|
|
@@ -31,7 +31,15 @@ export const NATIVE_SESSION_MEMORY_CACHE_HASH_GLOBS = [
|
|
|
31
31
|
"native/session-memory-engine/crates/**/*.rs",
|
|
32
32
|
"native/session-memory-engine/crates/**/Cargo.toml",
|
|
33
33
|
];
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Default **env-paths** Linux cache location when `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT`
|
|
36
|
+
* is unset (`$HOME/.cache/webpresso-agent-kit/session-memory-engine`).
|
|
37
|
+
*
|
|
38
|
+
* Agent-kit self-CI does **not** use this path for the warm cache: it overrides via
|
|
39
|
+
* `WP_NATIVE_SESSION_MEMORY_CACHE_ROOT` → `${{ runner.temp }}/sm-native-cache` (see
|
|
40
|
+
* the Test job warm cache step in `.github/workflows/ci.agent-kit.yml`). This helper
|
|
41
|
+
* documents the unset-override default only — not the workflow `path:`.
|
|
42
|
+
*/
|
|
35
43
|
export function defaultLinuxNativeSessionMemoryCachePath(home = "~") {
|
|
36
44
|
return `${home}/.cache/${NATIVE_SESSION_MEMORY_CACHE_ENV_NAME}/${NATIVE_SESSION_MEMORY_CACHE_SUBDIR}`;
|
|
37
45
|
}
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* All shards together still run every file discovered by vitest.config.ts
|
|
5
5
|
* projects; each shard is a slice via `vitest run --shard=i/n`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Three shards on ubicloud-standard-2 cut billed runner-minutes (fewer
|
|
8
|
+
* parallel installs × smaller class) while keeping full suite coverage.
|
|
9
|
+
* Wall-clock per shard may rise vs the prior 6×standard-4 layout; that is an
|
|
10
|
+
* intentional minutes-vs-wall tradeoff (see docs/ci-test-perf.md).
|
|
9
11
|
*/
|
|
10
|
-
export declare const VITEST_CI_SHARD_TOTAL =
|
|
11
|
-
export declare const VITEST_CI_SHARD_INDICES: readonly [1, 2, 3
|
|
12
|
+
export declare const VITEST_CI_SHARD_TOTAL = 3;
|
|
13
|
+
export declare const VITEST_CI_SHARD_INDICES: readonly [1, 2, 3];
|
|
12
14
|
/** CLI args for a single shard (excludes `vitest` binary). */
|
|
13
15
|
export declare function vitestCiShardArgs(shardIndex: number, shardTotal?: number): string[];
|
|
14
16
|
/** Matrix values for GitHub Actions strategy.matrix.shard */
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* All shards together still run every file discovered by vitest.config.ts
|
|
5
5
|
* projects; each shard is a slice via `vitest run --shard=i/n`.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Three shards on ubicloud-standard-2 cut billed runner-minutes (fewer
|
|
8
|
+
* parallel installs × smaller class) while keeping full suite coverage.
|
|
9
|
+
* Wall-clock per shard may rise vs the prior 6×standard-4 layout; that is an
|
|
10
|
+
* intentional minutes-vs-wall tradeoff (see docs/ci-test-perf.md).
|
|
9
11
|
*/
|
|
10
|
-
export const VITEST_CI_SHARD_TOTAL =
|
|
11
|
-
export const VITEST_CI_SHARD_INDICES = [1, 2, 3
|
|
12
|
+
export const VITEST_CI_SHARD_TOTAL = 3;
|
|
13
|
+
export const VITEST_CI_SHARD_INDICES = [1, 2, 3];
|
|
12
14
|
/** CLI args for a single shard (excludes `vitest` binary). */
|
|
13
15
|
export function vitestCiShardArgs(shardIndex, shardTotal = VITEST_CI_SHARD_TOTAL) {
|
|
14
16
|
if (!Number.isInteger(shardIndex) || shardIndex < 1 || shardIndex > shardTotal) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability tombstone for the self-install guard.
|
|
3
|
+
*
|
|
4
|
+
* Cycle-free leaf: no imports of the guard command or installer scheduler.
|
|
5
|
+
* Static-importable from the guard so mid-update installId package-tree
|
|
6
|
+
* deletion cannot race a package-local dynamic import.
|
|
7
|
+
*
|
|
8
|
+
* NOT a concurrency gate — the heartbeat lease in install-lock.ts owns
|
|
9
|
+
* mutual exclusion. Best-effort writes only.
|
|
10
|
+
*/
|
|
11
|
+
export interface Tombstone {
|
|
12
|
+
autoInstallInProgress: {
|
|
13
|
+
pid: number;
|
|
14
|
+
ts: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build the canonical tombstone shape. Exported for testability.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildTombstone(pid: number, ts: number): Tombstone;
|
|
21
|
+
/**
|
|
22
|
+
* Record the guard's pid + start time in the notifier cache for humans and
|
|
23
|
+
* `wp update`'s cache-reconcile step.
|
|
24
|
+
*/
|
|
25
|
+
export declare function writeGuardTombstone(): void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability tombstone for the self-install guard.
|
|
3
|
+
*
|
|
4
|
+
* Cycle-free leaf: no imports of the guard command or installer scheduler.
|
|
5
|
+
* Static-importable from the guard so mid-update installId package-tree
|
|
6
|
+
* deletion cannot race a package-local dynamic import.
|
|
7
|
+
*
|
|
8
|
+
* NOT a concurrency gate — the heartbeat lease in install-lock.ts owns
|
|
9
|
+
* mutual exclusion. Best-effort writes only.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
12
|
+
import { dirname } from "node:path";
|
|
13
|
+
import { getSurfacePath } from "#paths/state-root.js";
|
|
14
|
+
import { writeJsonFile } from "#shared-utils/write-json-file.js";
|
|
15
|
+
import { logUpdateError } from "./log.js";
|
|
16
|
+
/**
|
|
17
|
+
* Build the canonical tombstone shape. Exported for testability.
|
|
18
|
+
*/
|
|
19
|
+
export function buildTombstone(pid, ts) {
|
|
20
|
+
return { autoInstallInProgress: { pid, ts } };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Record the guard's pid + start time in the notifier cache for humans and
|
|
24
|
+
* `wp update`'s cache-reconcile step.
|
|
25
|
+
*/
|
|
26
|
+
export function writeGuardTombstone() {
|
|
27
|
+
try {
|
|
28
|
+
const configPath = resolveConfigPath();
|
|
29
|
+
if (configPath === null)
|
|
30
|
+
return;
|
|
31
|
+
writeTombstone(configPath, buildTombstone(process.pid, Date.now()));
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
logUpdateError(err);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function resolveConfigPath() {
|
|
38
|
+
try {
|
|
39
|
+
return getSurfacePath("update-notifier-cache.json", "user");
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function readRaw(configPath) {
|
|
46
|
+
if (!existsSync(configPath))
|
|
47
|
+
return {};
|
|
48
|
+
try {
|
|
49
|
+
const text = readFileSync(configPath, "utf-8");
|
|
50
|
+
if (text.trim().length === 0)
|
|
51
|
+
return {};
|
|
52
|
+
const parsed = JSON.parse(text);
|
|
53
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
54
|
+
return {};
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function writeTombstone(configPath, tombstone) {
|
|
62
|
+
const dir = dirname(configPath);
|
|
63
|
+
if (!existsSync(dir))
|
|
64
|
+
mkdirSync(dir, { recursive: true });
|
|
65
|
+
const merged = { ...readRaw(configPath), ...tombstone };
|
|
66
|
+
writeJsonFile(configPath, merged, { atomic: true, indent: 0, trailingNewline: false });
|
|
67
|
+
}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* releases the lease. Concurrency control, the observability tombstone,
|
|
14
14
|
* verification, and repair all live in the guard — this module only decides
|
|
15
15
|
* WHETHER to spawn and wires the detached stdio to auto-update.log.
|
|
16
|
+
* Guard argv uses the cycle-free self-invocation leaf (never a full import of
|
|
17
|
+
* the guard command module).
|
|
16
18
|
*
|
|
17
19
|
* Invariants:
|
|
18
20
|
* - Synchronous: returns before the install starts.
|
|
@@ -25,15 +27,11 @@
|
|
|
25
27
|
* from a successful CLI run.
|
|
26
28
|
*/
|
|
27
29
|
export { isProcessAlive } from "./install-lock.js";
|
|
30
|
+
/** Re-export for existing call sites and tests (implementation in guard-tombstone). */
|
|
31
|
+
export { buildTombstone, writeGuardTombstone, type Tombstone } from "./guard-tombstone.js";
|
|
28
32
|
export interface InstallPlan {
|
|
29
33
|
command: string[];
|
|
30
34
|
}
|
|
31
|
-
export interface Tombstone {
|
|
32
|
-
autoInstallInProgress: {
|
|
33
|
-
pid: number;
|
|
34
|
-
ts: number;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
35
|
export interface ScheduleResult {
|
|
38
36
|
/** Did we actually fork the guard child? */
|
|
39
37
|
spawned: boolean;
|
|
@@ -56,14 +54,3 @@ export interface ScheduleDeferredInstallOptions {
|
|
|
56
54
|
* holds the lease, the guard itself exits 12 without running anything.
|
|
57
55
|
*/
|
|
58
56
|
export declare function scheduleDeferredInstall(plan: InstallPlan, options?: ScheduleDeferredInstallOptions): ScheduleResult;
|
|
59
|
-
/**
|
|
60
|
-
* Observability tombstone written by the self-install guard when it takes
|
|
61
|
-
* the lease: records the guard's pid + start time in the notifier cache for
|
|
62
|
-
* humans and `wp update`'s cache-reconcile step. NOT a concurrency gate —
|
|
63
|
-
* the heartbeat lease in install-lock.ts owns mutual exclusion. Best-effort.
|
|
64
|
-
*/
|
|
65
|
-
export declare function writeGuardTombstone(): void;
|
|
66
|
-
/**
|
|
67
|
-
* Build the canonical tombstone shape. Exported for testability.
|
|
68
|
-
*/
|
|
69
|
-
export declare function buildTombstone(pid: number, ts: number): Tombstone;
|