session-orchestrator 3.19.0 → 3.21.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/030-wave-execution.mdc +10 -8
- package/CHANGELOG.md +494 -0
- package/README.md +16 -11
- package/agents/analyst.md +1 -1
- package/agents/architect-reviewer.md +1 -1
- package/agents/code-implementer.md +4 -2
- package/agents/db-specialist.md +1 -1
- package/agents/dialectic-deriver.md +1 -1
- package/agents/docs-writer.md +1 -1
- package/agents/memory-proposal-collector.md +1 -1
- package/agents/qa-strategist.md +1 -1
- package/agents/security-reviewer.md +1 -1
- package/agents/session-reviewer.md +42 -1
- package/agents/skill-applied-judge.md +1 -1
- package/agents/test-writer.md +1 -1
- package/agents/ui-developer.md +1 -1
- package/agents/ux-evaluator.md +1 -1
- package/commands/release.md +60 -0
- package/commands/session.md +6 -2
- package/docs/USER-GUIDE.md +1 -1
- package/docs/instruction-delivery.md +350 -0
- package/docs/migration-v3.md +9 -6
- package/docs/persona-panel.md +3 -1
- package/docs/scope-collision-guard.md +167 -0
- package/docs/session-config-reference.md +1 -41
- package/docs/session-config-template.md +0 -23
- package/hooks/_lib/guard-source-loader.mjs +304 -91
- package/hooks/enforce-commands.mjs +216 -17
- package/hooks/enforce-scope.mjs +236 -12
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +11 -1
- package/hooks/on-session-end.mjs +52 -5
- package/hooks/on-session-start.mjs +7 -4
- package/hooks/on-stop.mjs +127 -12
- package/hooks/post-bash-write-verify.mjs +8 -32
- package/hooks/pre-bash-destructive-guard.mjs +146 -59
- package/hooks/pre-bash-sessions-ledger-guard.mjs +493 -66
- package/hooks/pre-task-scope-disjoint.mjs +1042 -0
- package/package.json +2 -2
- package/pi/prompts/release.md +12 -0
- package/scripts/autopilot.mjs +3 -1
- package/scripts/backfill-learnings-from-vault.mjs +967 -0
- package/scripts/emit-session.mjs +45 -40
- package/scripts/export-hw-learnings.mjs +61 -2
- package/scripts/lib/autopilot/worktree-pipeline.mjs +5 -5
- package/scripts/lib/backlog-scan.mjs +106 -15
- package/scripts/lib/build-live-signals.mjs +7 -3
- package/scripts/lib/ci-status-banner.mjs +207 -23
- package/scripts/lib/command-blocker.mjs +322 -62
- package/scripts/lib/git-config-drift.mjs +471 -0
- package/scripts/lib/hardening.mjs +9 -9
- package/scripts/lib/harness-audit/categories/category6.mjs +65 -12
- package/scripts/lib/io.mjs +193 -7
- package/scripts/lib/learnings/affinity.mjs +434 -0
- package/scripts/lib/learnings/candidates.mjs +736 -0
- package/scripts/lib/learnings/expiry-sweep.mjs +408 -53
- package/scripts/lib/learnings/judgment.mjs +782 -0
- package/scripts/lib/learnings/kebab.mjs +128 -0
- package/scripts/lib/learnings/select.mjs +704 -0
- package/scripts/lib/memory-cleanup-stamp.mjs +132 -8
- package/scripts/lib/mirror-issues-banner.mjs +266 -0
- package/scripts/lib/named-vault-resolver.mjs +105 -16
- package/scripts/lib/peer-cards/schema.mjs +6 -2
- package/scripts/lib/reconcile/emitter.mjs +107 -22
- package/scripts/lib/reconcile/engine.mjs +9 -15
- package/scripts/lib/reconcile/renderer.mjs +141 -25
- package/scripts/lib/reconcile/sanitize.mjs +518 -0
- package/scripts/lib/reconcile/writer.mjs +134 -1
- package/scripts/lib/redact-spans.mjs +89 -0
- package/scripts/lib/scope-baseline.mjs +77 -17
- package/scripts/lib/scope-gate.mjs +852 -72
- package/scripts/lib/secret-masker.mjs +262 -0
- package/scripts/lib/session-close-backfill.mjs +2 -2
- package/scripts/lib/session-lock.mjs +34 -10
- package/scripts/lib/session-record-repair.mjs +551 -0
- package/scripts/lib/session-registry.mjs +9 -1
- package/scripts/lib/session-schema/serializer.mjs +54 -0
- package/scripts/lib/session-schema.mjs +1 -0
- package/scripts/lib/session-token-rollup.mjs +68 -6
- package/scripts/lib/soul-resolve.mjs +12 -0
- package/scripts/lib/state-md/mission-status.mjs +21 -12
- package/scripts/lib/tmux-layout/telemetry.mjs +43 -10
- package/scripts/lib/tmux-layout/vcs-detector.mjs +108 -4
- package/scripts/lib/validate/check-agents.mjs +77 -5
- package/scripts/lib/validate/check-banner-parity.mjs +376 -0
- package/scripts/lib/validate/check-commands.mjs +2 -20
- package/scripts/lib/validate/check-doc-cli-commands.mjs +514 -0
- package/scripts/lib/validate/check-guard-requires-parity.mjs +1148 -0
- package/scripts/lib/validate/check-hooks-symmetry.mjs +18 -0
- package/scripts/lib/validate/check-learning-provenance.mjs +511 -0
- package/scripts/lib/validate/check-owner-leakage.mjs +188 -20
- package/scripts/lib/validate/check-rules.mjs +31 -5
- package/scripts/lib/validate/check-skills.mjs +191 -0
- package/scripts/lib/validate/check-test-git-config-target.mjs +665 -0
- package/scripts/lib/validate/check-unicode-safety.mjs +22 -2
- package/scripts/lib/validate/check-untracked-test-deps.mjs +925 -0
- package/scripts/lib/validate/check-unwired-features.mjs +757 -0
- package/scripts/lib/validate/check-vcs-repo-flag.mjs +965 -0
- package/scripts/lib/validate/frontmatter-block.mjs +61 -0
- package/scripts/lib/validate/tier-inference.mjs +46 -8
- package/scripts/lib/vault-mirror/namespace.mjs +146 -1
- package/scripts/lib/vault-mirror/process.mjs +264 -31
- package/scripts/lib/vault-mirror/render-sessions.mjs +115 -4
- package/scripts/lib/vault-status/board-writer.mjs +300 -56
- package/scripts/lib/vault-status/narrative-mirror.mjs +119 -5
- package/scripts/lib/vcs-repo-spec.mjs +500 -19
- package/scripts/print-applicable-rules.mjs +170 -7
- package/scripts/print-learnings-index.mjs +501 -0
- package/scripts/release.mjs +616 -61
- package/scripts/repair-invalid-sessions.mjs +209 -0
- package/scripts/site-numbers.mjs +1049 -0
- package/scripts/sweep-expired-learnings.mjs +192 -32
- package/scripts/validate-plugin.mjs +82 -0
- package/scripts/validate-wave-scope.mjs +281 -12
- package/scripts/vault-mirror.mjs +26 -1
- package/skills/_shared/monitor-patterns.md +24 -4
- package/skills/_shared/state-ownership.md +17 -0
- package/skills/brainstorm/soul.md +47 -1
- package/skills/claude-md-drift-check/SKILL.md +9 -1
- package/skills/debug/SKILL.md +4 -1
- package/skills/discovery/issue-templates.md +4 -4
- package/skills/discovery/probes-code.md +2 -2
- package/skills/discovery/probes-feature.md +6 -6
- package/skills/discovery/probes-infra.md +2 -2
- package/skills/discovery/probes-session.md +5 -5
- package/skills/dispatcher/SKILL.md +10 -1
- package/skills/evolve/SKILL.md +116 -18
- package/skills/frontmatter-guard/SKILL.md +9 -1
- package/skills/gitlab-ops/SKILL.md +54 -39
- package/skills/gitlab-portfolio/SKILL.md +10 -1
- package/skills/grill/soul.md +44 -1
- package/skills/memory-cleanup/SKILL.md +18 -5
- package/skills/npm-publish/SKILL.md +22 -50
- package/skills/persona-panel/SKILL.md +3 -1
- package/skills/plan/mode-new.md +23 -5
- package/skills/plan/soul.md +46 -3
- package/skills/repo-audit/SKILL.md +10 -1
- package/skills/session-end/SKILL.md +45 -26
- package/skills/session-end/metrics-collection.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +30 -1
- package/skills/session-end/plan-verification.md +1 -5
- package/skills/session-end/session-metrics-write.md +6 -10
- package/skills/session-plan/SKILL.md +2 -2
- package/skills/session-plan/wave-template.md +1 -1
- package/skills/session-start/SKILL.md +15 -1
- package/skills/session-start/soul.md +41 -1
- package/skills/spinout/SKILL.md +5 -1
- package/skills/sunset-review/SKILL.md +11 -1
- package/skills/tmux-layout/SKILL.md +7 -2
- package/skills/vault-mirror/SKILL.md +10 -1
- package/skills/vault-sync/SKILL.md +10 -1
- package/skills/vault-sync/validator.mjs +55 -6
- package/skills/wave-executor/SKILL.md +1 -5
- package/skills/wave-executor/wave-loop.md +77 -82
- package/scripts/lib/mission-status-schema.mjs +0 -114
|
@@ -69,6 +69,50 @@ function renderDuration(durationSeconds, durationMinutes) {
|
|
|
69
69
|
return minutes === undefined || minutes === null ? MISSING_VALUE : `${minutes}m`;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Coerce ONE wave-object count field to a renderable number (#1074).
|
|
74
|
+
*
|
|
75
|
+
* ── WHY A TYPE GUARD AND NOT A BARE `??` CHAIN ─────────────────────────────
|
|
76
|
+
*
|
|
77
|
+
* The wave-object count fields are POLYMORPHIC across producer generations.
|
|
78
|
+
* Census over the live ledger (253 records / 599 wave objects, 2026-08-19):
|
|
79
|
+
*
|
|
80
|
+
* agent_count number 359
|
|
81
|
+
* agents number 210, **ARRAY 14** ← array-of-agent-descriptors
|
|
82
|
+
* agents_dispatched number 20
|
|
83
|
+
* dispatched number 5
|
|
84
|
+
* files_changed number 366, **ARRAY 1** ← array-of-file-paths
|
|
85
|
+
* files number 5
|
|
86
|
+
*
|
|
87
|
+
* A naive `w.agent_count ?? w.agents` therefore interpolates an array of
|
|
88
|
+
* objects into a Markdown table cell — `[object Object],[object Object],…` for
|
|
89
|
+
* the 4 waves of `main-2026-04-27-2231`. That is STRICTLY WORSE than the `?` it
|
|
90
|
+
* replaces: `?` reads as "unknown", `[object Object]` reads as content. The
|
|
91
|
+
* array-of-paths half of the same defect is already in production —
|
|
92
|
+
* `main-2026-05-26-housekeeping-1` renders its whole file list into the Files
|
|
93
|
+
* cell today, via the plain `w.files_changed` read that predates this helper.
|
|
94
|
+
*
|
|
95
|
+
* An array IS a measurement (its length is the count), so it is converted, not
|
|
96
|
+
* dropped. Any OTHER shape returns `undefined` so the caller's `??` chain keeps
|
|
97
|
+
* walking to the next alias and ultimately to `MISSING_CELL` — an unrecognised
|
|
98
|
+
* shape must degrade to "unknown", never to a coerced string. `NaN` is out of
|
|
99
|
+
* reach here by construction: JSON cannot encode it, and every caller feeds
|
|
100
|
+
* this JSONL-parsed values.
|
|
101
|
+
*
|
|
102
|
+
* ABSENT IS NOT ZERO applies unchanged (see the banner above `MISSING_CELL`):
|
|
103
|
+
* this returns `0` for a measured `0` and `0` for an empty array, and only
|
|
104
|
+
* `undefined` for a field the producer never wrote. Callers MUST chain with
|
|
105
|
+
* `??`, never `||` — `agents_dispatched: 0` occurs 20× in the live ledger.
|
|
106
|
+
*
|
|
107
|
+
* @param {unknown} value — one raw wave-object field.
|
|
108
|
+
* @returns {number|undefined} the count, or `undefined` to continue the chain.
|
|
109
|
+
*/
|
|
110
|
+
function waveCount(value) {
|
|
111
|
+
if (typeof value === 'number') return value;
|
|
112
|
+
if (Array.isArray(value)) return value.length;
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
72
116
|
/**
|
|
73
117
|
* ── RENDERABLE ⊋ SCHEMA-VALID (#964) ───────────────────────────────────────
|
|
74
118
|
*
|
|
@@ -259,6 +303,29 @@ function fmLine(key, value) {
|
|
|
259
303
|
* reachability is therefore zero; see the follow-up note in the #964 report
|
|
260
304
|
* before treating it as dead code — deletion is a separate decision, and the
|
|
261
305
|
* `normalizeSessionEntry` alias path can still synthesize a scalar `waves`.
|
|
306
|
+
*
|
|
307
|
+
* #1074 — THE v2 BRANCH WAS DEAD AT BIRTH, AND THE NUMBER IS PINNED. Re-measured
|
|
308
|
+
* 2026-08-19 over 253 records: **v1 253, v2 0, v3 0**, both raw and
|
|
309
|
+
* post-`normalizeSessionEntry`. This is not a coincidence of the current data —
|
|
310
|
+
* the v2 clause is UNSATISFIABLE by construction: it requires
|
|
311
|
+
* `total_agents === undefined`, while `total_agents` is in `REQUIRED_FIELDS`
|
|
312
|
+
* (scripts/lib/session-schema/constants.mjs) and enforced by
|
|
313
|
+
* `validateSession`, so every record the writer accepts carries it (measured:
|
|
314
|
+
* 253/253 define it). Commit 9cb6d9c added the branch 4h23m BEFORE the first
|
|
315
|
+
* record using the `agents` alias was written, and no historical tracked ledger
|
|
316
|
+
* state would have routed one either.
|
|
317
|
+
*
|
|
318
|
+
* The consequence is the reason `generateSessionNote`'s wave table no longer
|
|
319
|
+
* consults this function for its alias handling at all: version detection is
|
|
320
|
+
* the WRONG AXIS for per-wave producer-key drift, because the alias varies per
|
|
321
|
+
* wave object and no session-level field — `schema_version` included — predicts
|
|
322
|
+
* it. See the census in the `waveRows` comment there. This function still
|
|
323
|
+
* routes the three GENERATORS and is unchanged; do not "repair" the wave table
|
|
324
|
+
* by re-anchoring it here.
|
|
325
|
+
*
|
|
326
|
+
* The generators are intentionally NOT deleted (operator decision, deferred
|
|
327
|
+
* once already in #964). Pinning the number here is the point: the next reader
|
|
328
|
+
* inherits the measurement instead of re-running it.
|
|
262
329
|
*/
|
|
263
330
|
export function detectSessionSchema(entry) {
|
|
264
331
|
if (!entry) return 'v1';
|
|
@@ -368,11 +435,55 @@ export function generateSessionNote(entry, options = {}) {
|
|
|
368
435
|
// validated, so all three are optional and were rendering as the literal
|
|
369
436
|
// string `undefined`. Guarded with the same `?? '?'` the v2 generator's wave
|
|
370
437
|
// rows already used — `??` so a measured `0` still renders `0`.
|
|
438
|
+
//
|
|
439
|
+
// ── #1074: PER-WAVE ALIASES, NOT PER-SESSION VERSION DETECTION ────────────
|
|
440
|
+
//
|
|
441
|
+
// #M1 stopped the cells reading `undefined`, but left them reading `?` for
|
|
442
|
+
// every record whose producer used a different key — and that is most of the
|
|
443
|
+
// ledger. Census over 253 records / 599 wave objects (2026-08-19):
|
|
444
|
+
//
|
|
445
|
+
// Agents `?` 240 cells in 55 records (recoverable: agents 214, agents_dispatched 20, dispatched 5)
|
|
446
|
+
// Files `?` 232 cells in 52 records (recoverable: files 5)
|
|
447
|
+
// Quality `?` 386 cells in 88 records (recoverable: quality_check 168, status 72, result 35, outcome 5)
|
|
448
|
+
//
|
|
449
|
+
// The version-detection route cannot fix this. `detectSessionSchema` keys on
|
|
450
|
+
// SESSION-level fields, but the alias in use varies PER WAVE OBJECT and no
|
|
451
|
+
// session-level field predicts it — not even `schema_version` (under
|
|
452
|
+
// `schema_version: 1` the ledger carries agent_count 75, agents 33, none 30,
|
|
453
|
+
// agents_dispatched 4, both 2, dispatched 1). The axis is empirically
|
|
454
|
+
// refuted, so the repair is a per-wave alias chain instead.
|
|
455
|
+
//
|
|
456
|
+
// v1-canonical names come FIRST in every chain, so a cell that rendered a
|
|
457
|
+
// value before renders the identical value now: this can only ever replace a
|
|
458
|
+
// `?`. Verified over all 599 wave objects — repaired 239 agents / 5 files /
|
|
459
|
+
// 280 quality, with ZERO existing agents or quality values changed. The one
|
|
460
|
+
// deliberate change is the Files cell of `main-2026-05-26-housekeeping-1`,
|
|
461
|
+
// which stops printing a raw file-path list and prints `3` (see `waveCount`).
|
|
462
|
+
//
|
|
463
|
+
// The Quality chain needs no `waveCount`: all five of its aliases are 100%
|
|
464
|
+
// strings across the ledger (quality 213, quality_check 168, status 72,
|
|
465
|
+
// result 35, outcome 5 — zero objects or arrays), so there is no
|
|
466
|
+
// `[object Object]` hazard to guard. Should a producer ever emit a structured
|
|
467
|
+
// quality verdict, the fixture-coverage test in render-sessions.test.mjs is
|
|
468
|
+
// what surfaces it — this comment is the ceiling, that test is the trigger.
|
|
469
|
+
//
|
|
470
|
+
// A wave with no count under ANY alias keeps rendering `?`, and must: the
|
|
471
|
+
// coord-direct wave of `main-2026-05-26-housekeeping-1` dispatched no agents
|
|
472
|
+
// and recorded no number, so its Agents cell is genuinely unknown. A chain
|
|
473
|
+
// that "repaired" that one too would be inventing a measurement.
|
|
371
474
|
const waveRows = waves
|
|
372
|
-
.map(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
475
|
+
.map((w) => {
|
|
476
|
+
const agentsCell =
|
|
477
|
+
waveCount(w.agent_count) ??
|
|
478
|
+
waveCount(w.agents) ??
|
|
479
|
+
waveCount(w.agents_dispatched) ??
|
|
480
|
+
waveCount(w.dispatched) ??
|
|
481
|
+
MISSING_CELL;
|
|
482
|
+
const filesCell = waveCount(w.files_changed) ?? waveCount(w.files) ?? MISSING_CELL;
|
|
483
|
+
const qualityCell =
|
|
484
|
+
w.quality ?? w.quality_check ?? w.status ?? w.result ?? w.outcome ?? MISSING_CELL;
|
|
485
|
+
return `| ${w.wave} | ${w.role} | ${agentsCell} | ${filesCell} | ${qualityCell} |`;
|
|
486
|
+
})
|
|
376
487
|
.join('\n');
|
|
377
488
|
|
|
378
489
|
// Skip-emit guard: avoid `platform: undefined` literal coercion (issue #343).
|