@ngockhoale/ukit 3.4.61 → 3.4.63
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 +15 -0
- package/manifests/documentation.yaml +11 -0
- package/package.json +1 -1
- package/template_project/.claude/commands/ukit/handoff-fullstack.md +2 -2
- package/template_project/.claude/commands/ukit/handoff-implement.md +1 -1
- package/template_project/.claude/commands/ukit/handoff-review.md +1 -1
- package/template_project/.claude/ukit/runtime/execution-ledger.mjs +12 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to UKit are documented here.
|
|
4
4
|
|
|
5
|
+
## 3.4.63 - 2026-10-22
|
|
6
|
+
|
|
7
|
+
**Completion recovery: background pending is not a pipeline.**
|
|
8
|
+
- Reproduced task `task-848c14831946f7c359cdf11faf45edd2` / `bk1n4wpks`: bare release verifier exited 0 in host notification; Bash/grep read did not ingest completion. Launch and masked-shell receipts share `exitStatusUnproven`; recovery falsely asserted pipeline and requested reruns.
|
|
9
|
+
- Diagnostic-only fix: background launch -> wait SAME job, no duplicate; host completion -> Read task output through footer, not rerun; masked shell -> wrapper status unproven, actual pipe only a possible cause. Receipt acceptance/freshness unchanged; unsupported hosts remain fail-closed.
|
|
10
|
+
- Regressions: pending, host completion+Bash vs Read, later launch not masking valid completion, failed runner, masked wrapper, analysis-doc freshness vs living STATUS; existing forged/mismatched/duplicate/foreign/stale controls retained.
|
|
11
|
+
- Release-gate fixture repair: TERM-ignoring grandchild now signals readiness after handler installation before the measured runner deadline starts (injected real child); retains ≥700ms grace/escalation and no-survivor assertions. Production hook-process unchanged.
|
|
12
|
+
- Independent four-task fixture pilot and whole-workflow budget proposal recorded; no paid pilot. OMP genuine-service live smoke remains unverified (deterministic RPC bash lacks name/ready); no claim of every-service coverage.
|
|
13
|
+
|
|
14
|
+
## 3.4.62 - 2026-10-22
|
|
15
|
+
|
|
16
|
+
**Handoff commands: state what `handoff.maxParallelAgents` counts (wording only).**
|
|
17
|
+
- The cap is child workers of ONE batch or review set, summed across roles (implementers and reviewers together); the main session is outside it; it is not a session-wide limit; it is prompt-level guidance (no hook counts children) and the host's own concurrency limit is separate. Added to `handoff-implement`, `handoff-fullstack` (implement batch + review set) and `handoff-review`.
|
|
18
|
+
- No default, config key, scope or behavior change. Basis: BAGuide field audit (peak 14 concurrent children while the cap text said 2, never refused), see `docs/analysis/CONCURRENCY-CHECKPOINT-2026-10-22.md`.
|
|
19
|
+
|
|
5
20
|
## 3.4.61 - 2026-10-22
|
|
6
21
|
|
|
7
22
|
**omp bash: stop sending the call shape the host rejects (`name` + `async`/`timeout`).**
|
|
@@ -462,6 +462,17 @@ entries:
|
|
|
462
462
|
validation: [manual]
|
|
463
463
|
archive_policy: replace-with-snapshot
|
|
464
464
|
notes: continuity checkpoint for the concurrency audit (R6 corrections, bash guard, prepared unpaid pilot)
|
|
465
|
+
- id: docs-analysis-concurrency-pilot
|
|
466
|
+
path: docs/analysis/concurrency-pilot/README.md
|
|
467
|
+
class: canonical
|
|
468
|
+
audience: [owner, maintainer]
|
|
469
|
+
owner: runtime
|
|
470
|
+
source_of_truth: docs/analysis/concurrency-pilot/README.md
|
|
471
|
+
merge_strategy: none
|
|
472
|
+
load_policy: on-demand
|
|
473
|
+
validation: [manual]
|
|
474
|
+
archive_policy: replace-with-snapshot
|
|
475
|
+
notes: independent frozen fixture pilot proposal; no paid run
|
|
465
476
|
- id: docs-analysis-subagent-cost-audit
|
|
466
477
|
path: docs/analysis/SUBAGENT-COST-AUDIT.md
|
|
467
478
|
class: archive
|
package/package.json
CHANGED
|
@@ -446,7 +446,7 @@ if it is missing required fields — never merely for sharing a file.
|
|
|
446
446
|
**Batch each wave — mandatory.** Read `handoff.maxParallelAgents` from
|
|
447
447
|
`.ukit/storage/config.json`. A wave with more tasks than that is split
|
|
448
448
|
into consecutive batches of at most that many; finish one batch completely (including 3c
|
|
449
|
-
copy-back and worktree deletion) before starting the next.
|
|
449
|
+
copy-back and worktree deletion) before starting the next. The cap counts child workers of ONE batch/review set, summed across roles (implementers and reviewers together); the main session is outside it, and it is not a session-wide limit. It is prompt-level guidance: no hook counts children, and the host's own concurrency limit is separate.
|
|
450
450
|
|
|
451
451
|
Never spawn a whole wide wave at once. Every background agent carries its own context
|
|
452
452
|
window, and each finished report is injected back into this session — a wave of 20+ is
|
|
@@ -659,7 +659,7 @@ Never make fake edits or fake tests to satisfy an empty diff, and never lower ac
|
|
|
659
659
|
|
|
660
660
|
### R2 — Model isolation check (strong model, always first)
|
|
661
661
|
|
|
662
|
-
**Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (R2–R4, appended to each task file) before starting the next.
|
|
662
|
+
**Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (R2–R4, appended to each task file) before starting the next. The cap counts child workers of ONE batch/review set, summed across roles (implementers and reviewers together); the main session is outside it, and it is not a session-wide limit. It is prompt-level guidance: no hook counts children, and the host's own concurrency limit is separate.
|
|
663
663
|
|
|
664
664
|
**Claude Code — MANDATORY, do this before anything else in R2–R4:** for each batch, call the Agent tool once per `pending_review` task **in parallel** (at most `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per task in the batch, not once per wave). Reviewer agents only read the diff and append a verdict to their own task file — no worktree, no shared write target — so running them in parallel carries none of Phase 3's file-conflict risk. Do NOT review the diff yourself in the current session — this step is contracted to the strong tier (opus/unic-smart) and MUST differ from the executor's model, which only the spawned agent's frontmatter model guarantees.
|
|
665
665
|
|
|
@@ -103,7 +103,7 @@ when it is missing required fields — never merely for sharing a file.
|
|
|
103
103
|
Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. A wave
|
|
104
104
|
with more tasks than that is split into consecutive batches of at most that many; finish
|
|
105
105
|
one batch completely (including 3c copy-back and worktree deletion) before starting the
|
|
106
|
-
next.
|
|
106
|
+
next. The cap counts child workers of ONE batch/review set, summed across roles (implementers and reviewers together); the main session is outside it, and it is not a session-wide limit. It is prompt-level guidance: no hook counts children, and the host's own concurrency limit is separate.
|
|
107
107
|
|
|
108
108
|
Never spawn a whole wide wave at once. Every background agent carries its own context
|
|
109
109
|
window, and each finished report is injected back into this session — a wave of 20+ is
|
|
@@ -53,7 +53,7 @@ Classify by what the diff can show. An empty diff is NOT automatically "implemen
|
|
|
53
53
|
|
|
54
54
|
## Step 2 — Review the diff
|
|
55
55
|
|
|
56
|
-
**Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (2a–2d, appended to each task file) before starting the next.
|
|
56
|
+
**Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (2a–2d, appended to each task file) before starting the next. The cap counts child workers of ONE batch/review set, summed across roles (implementers and reviewers together); the main session is outside it, and it is not a session-wide limit. It is prompt-level guidance: no hook counts children, and the host's own concurrency limit is separate.
|
|
57
57
|
|
|
58
58
|
**Spawn the review panel — MANDATORY, do this before anything else:** read `modelRoles['review-panel']` from `.ukit/storage/config.json` → `modelRoles` (default `['smart','code','lite']`; omp tier aliases `@smol`/`@default`/`@slow`). For each `pending_review` task in the batch, call the Agent tool **once per panel entry** (in parallel, bounded by `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per panel entry per task) — each member bound to its panel tier and setting `PANEL_MEMBER: <tier>` in its verdict. Reviewer agents only read the diff and append a verdict to their own task file — no worktree, no shared write target — so running them in parallel carries none of Phase 3's file-conflict risk. Do NOT review the diff yourself in the current session — this step is contracted to the panel tiers and MUST differ from the executor's model, which only the spawned agent's frontmatter model guarantees. Pass each agent: the task file path, the executor's report, and the diff.
|
|
59
59
|
|
|
@@ -3268,7 +3268,9 @@ export async function recordExecutionReceipt({
|
|
|
3268
3268
|
if (backgroundLaunchAck && receipt.success) {
|
|
3269
3269
|
receipt.success = false;
|
|
3270
3270
|
receipt.exitStatusUnproven = true;
|
|
3271
|
-
|
|
3271
|
+
if (ledgerMessageEmitter) {
|
|
3272
|
+
try { ledgerMessageEmitter(`${JSON.stringify({ systemMessage: `UKit execution-ledger: background verification ${receipt.backgroundTaskId || '(unknown id)'} is pending. Wait for the same job; do not launch a duplicate. After the host task-notification, Read its tasks/<id>.output through the final exit footer to ingest completion; Bash/grep does not ingest it.` })}\n`); } catch { /* advisory */ }
|
|
3273
|
+
}
|
|
3272
3274
|
} else if (maskedStage && receipt.success) {
|
|
3273
3275
|
receipt.success = false;
|
|
3274
3276
|
receipt.exitStatusUnproven = true;
|
|
@@ -3605,7 +3607,15 @@ function recoveryInstruction(missingEvidence, ledger = {}, routeSummary = {}, {
|
|
|
3605
3607
|
// Unproven never sets `verificationFailed`, so this must not key off that flag.
|
|
3606
3608
|
const lastVerification = [...(ledger.receipts || [])].reverse().find((r) => r?.kind === 'verification');
|
|
3607
3609
|
if (!instruction && lastVerification?.exitStatusUnproven === true) {
|
|
3608
|
-
|
|
3610
|
+
if (lastVerification.backgroundTaskId && !lastVerification.backgroundCompletion) {
|
|
3611
|
+
const id = lastVerification.backgroundTaskId;
|
|
3612
|
+
const hostExit = hostCompletionExit(ledger.transcriptPath, id);
|
|
3613
|
+
instruction = hostExit === null
|
|
3614
|
+
? `Background verification ${id} has no ingested completion (pending or unsupported host evidence). Wait for the same job and its host task-notification; do not launch a duplicate. Then use Read on its tasks/${id}.output through the final exit footer. Bash/grep does not ingest completion; a footer without a matching host notification is not proof.`
|
|
3615
|
+
: `Background verification ${id} has host completion exit ${hostExit}, but no ingested completion receipt. Use Read on its tasks/${id}.output through the final exit footer (Bash/grep does not ingest completion). Do not rerun the completed job just to create evidence. If Read is rejected, check the matching launch, host notification, footer and output-file freshness; never fabricate a receipt.`;
|
|
3616
|
+
} else {
|
|
3617
|
+
instruction = `The last verification (\`${String(lastVerification.command || '').slice(0, 80)}\`) exit status is unproven: its shell wrapper may mask or skip the runner (a pipeline is one possible cause). Run the bare verification command and inspect its exit code; for an actual pipeline, propagate the runner status with \`set -o pipefail\`.`;
|
|
3618
|
+
}
|
|
3609
3619
|
}
|
|
3610
3620
|
if (!instruction && ledger.verificationFailed) {
|
|
3611
3621
|
instruction = 'Use the latest failed verification output, fix the failure, and rerun targeted verification.';
|