session-orchestrator 5.2.0 → 5.3.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/.agents/skills/architecture/SKILL.md +3 -1
- package/.agents/skills/autopilot/SKILL.md +5 -1
- package/.agents/skills/autopilot/agents/openai.yaml +5 -0
- package/.agents/skills/bootstrap/SKILL.md +5 -1
- package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
- package/.agents/skills/brainstorm/SKILL.md +5 -1
- package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
- package/.agents/skills/claude-md-drift-check/SKILL.md +3 -1
- package/.agents/skills/close/SKILL.md +5 -1
- package/.agents/skills/close/agents/openai.yaml +5 -0
- package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
- package/.agents/skills/debug/SKILL.md +5 -1
- package/.agents/skills/debug/agents/openai.yaml +5 -0
- package/.agents/skills/discovery/SKILL.md +5 -1
- package/.agents/skills/discovery/agents/openai.yaml +5 -0
- package/.agents/skills/dispatcher/SKILL.md +5 -1
- package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
- package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ecosystem-health/SKILL.md +3 -1
- package/.agents/skills/eli5/SKILL.md +5 -1
- package/.agents/skills/eli5/agents/openai.yaml +5 -0
- package/.agents/skills/eval/SKILL.md +6 -2
- package/.agents/skills/eval/agents/openai.yaml +5 -0
- package/.agents/skills/evolve/SKILL.md +6 -2
- package/.agents/skills/evolve/agents/openai.yaml +5 -0
- package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
- package/.agents/skills/gitlab-ops/SKILL.md +3 -1
- package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
- package/.agents/skills/go/SKILL.md +5 -1
- package/.agents/skills/go/agents/openai.yaml +5 -0
- package/.agents/skills/grill/SKILL.md +5 -1
- package/.agents/skills/grill/agents/openai.yaml +5 -0
- package/.agents/skills/harness-audit/SKILL.md +5 -1
- package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
- package/.agents/skills/hook-development/SKILL.md +3 -1
- package/.agents/skills/mcp-builder/SKILL.md +3 -1
- package/.agents/skills/memory-cleanup/SKILL.md +5 -1
- package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
- package/.agents/skills/mode-selector/SKILL.md +3 -1
- package/.agents/skills/npm-publish/SKILL.md +4 -2
- package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
- package/.agents/skills/persona-panel/SKILL.md +5 -1
- package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
- package/.agents/skills/plan/SKILL.md +5 -1
- package/.agents/skills/plan/agents/openai.yaml +5 -0
- package/.agents/skills/playwright-driver/SKILL.md +3 -1
- package/.agents/skills/portfolio/SKILL.md +5 -1
- package/.agents/skills/portfolio/agents/openai.yaml +5 -0
- package/.agents/skills/quality-gates/SKILL.md +3 -1
- package/.agents/skills/reconcile/SKILL.md +5 -1
- package/.agents/skills/reconcile/agents/openai.yaml +5 -0
- package/.agents/skills/release/SKILL.md +5 -1
- package/.agents/skills/release/agents/openai.yaml +5 -0
- package/.agents/skills/remote-offload/SKILL.md +3 -1
- package/.agents/skills/repo-audit/SKILL.md +5 -1
- package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
- package/.agents/skills/session/SKILL.md +21 -0
- package/.agents/skills/session/agents/openai.yaml +5 -0
- package/.agents/skills/session-end/SKILL.md +3 -1
- package/.agents/skills/session-plan/SKILL.md +3 -1
- package/.agents/skills/session-start/SKILL.md +3 -1
- package/.agents/skills/spinout/SKILL.md +5 -1
- package/.agents/skills/spinout/agents/openai.yaml +5 -0
- package/.agents/skills/sunset-review/SKILL.md +5 -1
- package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
- package/.agents/skills/templates-ack/SKILL.md +21 -0
- package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
- package/.agents/skills/test/SKILL.md +5 -1
- package/.agents/skills/test/agents/openai.yaml +5 -0
- package/.agents/skills/test-runner/SKILL.md +3 -1
- package/.agents/skills/tmux-layout/SKILL.md +3 -1
- package/.agents/skills/using-orchestrator/SKILL.md +3 -1
- package/.agents/skills/ux-grill/SKILL.md +5 -1
- package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
- package/.agents/skills/vault-mirror/SKILL.md +3 -1
- package/.agents/skills/vault-sync/SKILL.md +3 -1
- package/.agents/skills/wave-executor/SKILL.md +3 -1
- package/.agents/skills/write-executable-plan/SKILL.md +3 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +4 -4
- package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -3
- package/.codex-plugin/skills/eval/SKILL.md +1 -1
- package/.codex-plugin/skills/evolve/SKILL.md +1 -1
- package/.codex-plugin/skills/npm-publish/SKILL.md +1 -3
- package/.codex-plugin/skills/session/SKILL.md +1 -1
- package/.cursor/commands/eval.md +1 -1
- package/.cursor/commands/session.md +1 -1
- package/.cursor/rules/000-session-orchestrator.mdc +0 -2
- package/.cursor/rules/050-plan.mdc +1 -1
- package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
- package/.cursor/skills/eval/SKILL.md +1 -1
- package/.cursor/skills/npm-publish/SKILL.md +1 -0
- package/.cursor-plugin/plugin.json +1 -1
- package/.orchestrator/policy/blocked-commands.json +12 -3
- package/AGENTS.md +3 -2
- package/CHANGELOG.md +136 -0
- package/README.md +9 -9
- package/SECURITY.md +12 -0
- package/agents/dialectic-deriver.md +13 -10
- package/agents/eval-judge.md +67 -45
- package/agents/skill-applied-judge.md +34 -19
- package/commands/session.md +7 -3
- package/docs/baseline.md +12 -6
- package/docs/codex-setup.md +14 -2
- package/docs/components.md +7 -5
- package/docs/events-schema.md +56 -9
- package/docs/rule-authoring.md +58 -6
- package/docs/session-config-reference.md +100 -7
- package/docs/session-config-template.md +31 -2
- package/docs/telemetry.md +2 -0
- package/hooks/_lib/hook-import-set.json +85 -8
- package/hooks/_lib/subagent-transcript.mjs +582 -31
- package/hooks/config-protection.mjs +11 -3
- package/hooks/cwd-change-restore.mjs +11 -3
- package/hooks/enforce-commands.mjs +70 -23
- package/hooks/enforce-scope.mjs +143 -33
- package/hooks/hooks-codex.json +1 -1
- package/hooks/hooks.json +1 -1
- package/hooks/loop-guard.mjs +11 -3
- package/hooks/on-session-end.mjs +58 -23
- package/hooks/on-session-start.mjs +48 -11
- package/hooks/on-stop.mjs +168 -22
- package/hooks/operator-steer.mjs +11 -3
- package/hooks/post-bash-issue-budget-refund.mjs +18 -8
- package/hooks/post-bash-write-verify.mjs +3 -2
- package/hooks/post-edit-import-probe.mjs +17 -9
- package/hooks/post-edit-validate.mjs +13 -5
- package/hooks/post-subagent-discovery-validator.mjs +98 -13
- package/hooks/post-tool-batch-wave-signal.mjs +200 -38
- package/hooks/post-tool-failure-corrective-context.mjs +11 -5
- package/hooks/post-tooluse-frontend-slop.mjs +10 -4
- package/hooks/pre-auq-clarity.mjs +15 -2
- package/hooks/pre-bash-destructive-guard.mjs +80 -9
- package/hooks/pre-bash-issue-budget.mjs +16 -11
- package/hooks/pre-bash-memory-propose-audit.mjs +86 -54
- package/hooks/pre-bash-sessions-ledger-guard.mjs +391 -20
- package/hooks/pre-bash-staging-fence.mjs +335 -31
- package/hooks/pre-bash-templates-first.mjs +19 -14
- package/hooks/pre-task-scope-disjoint.mjs +233 -2
- package/hooks/subagent-telemetry.mjs +15 -19
- package/hooks/wave-scope-commit-guard.mjs +197 -100
- package/monitors/monitors.json +1 -1
- package/output-styles/wave-summary.md +1 -1
- package/package.json +1 -1
- package/pi/prompts/eval.md +1 -1
- package/pi/prompts/session.md +1 -1
- package/rules/README.md +1 -1
- package/rules/opt-in-domain/prompt-caching.md +1 -1
- package/rules/opt-in-stack/backend-data.md +1 -1
- package/rules/opt-in-stack/backend.md +3 -3
- package/rules/opt-in-stack/frontend.md +1 -1
- package/rules/opt-in-stack/security-web.md +3 -3
- package/rules/opt-in-stack/swift.md +1 -1
- package/scripts/autopilot.mjs +23 -2
- package/scripts/backfill-abandoned-sessions.mjs +117 -15
- package/scripts/check-sessions-integrity.mjs +300 -0
- package/scripts/dialectic-deriver.mjs +50 -13
- package/scripts/emit-session.mjs +75 -29
- package/scripts/eval-session.mjs +65 -3
- package/scripts/generate-agents-skills.mjs +102 -29
- package/scripts/generate-cursor-adapter.mjs +61 -16
- package/scripts/lib/agent-status.mjs +2 -31
- package/scripts/lib/auq/clarity.mjs +10 -2
- package/scripts/lib/auq/parse.mjs +12 -31
- package/scripts/lib/auq/schema.mjs +56 -41
- package/scripts/lib/auto-dialectic.mjs +304 -15
- package/scripts/lib/autopilot/flags.mjs +12 -1
- package/scripts/lib/autopilot/kill-switches.mjs +6 -3
- package/scripts/lib/autopilot/loop.mjs +14 -1
- package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
- package/scripts/lib/ci-status-banner.mjs +376 -16
- package/scripts/lib/command-blocker.mjs +275 -28
- package/scripts/lib/config/dialectic.mjs +12 -3
- package/scripts/lib/config/gate.mjs +74 -0
- package/scripts/lib/config/reaper.mjs +162 -0
- package/scripts/lib/config.mjs +14 -0
- package/scripts/lib/convergence-monitor.mjs +74 -11
- package/scripts/lib/ecosystem-health.mjs +11 -0
- package/scripts/lib/eval/engine.mjs +421 -53
- package/scripts/lib/eval/judge.mjs +463 -40
- package/scripts/lib/eval/schema.mjs +10 -1
- package/scripts/lib/events-rotation.mjs +221 -25
- package/scripts/lib/events-schema.mjs +114 -0
- package/scripts/lib/events.mjs +524 -5
- package/scripts/lib/frontmatter-guard.mjs +21 -10
- package/scripts/lib/gates/gate-baseline.mjs +27 -2
- package/scripts/lib/gates/gate-full.mjs +28 -3
- package/scripts/lib/gates/gate-helpers.mjs +243 -21
- package/scripts/lib/gates/gate-incremental.mjs +28 -3
- package/scripts/lib/gates/gate-per-file.mjs +27 -2
- package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
- package/scripts/lib/instruction-budget-guard.mjs +146 -4
- package/scripts/lib/io.mjs +42 -8
- package/scripts/lib/issue-close-strip-labels.mjs +207 -49
- package/scripts/lib/js-mask.mjs +197 -0
- package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
- package/scripts/lib/maintenance-due-banner.mjs +53 -88
- package/scripts/lib/orphan-reaper.mjs +1588 -0
- package/scripts/lib/peer-cards/merger.mjs +48 -10
- package/scripts/lib/peer-cards/reader.mjs +78 -2
- package/scripts/lib/process-group.mjs +899 -0
- package/scripts/lib/quality-gate.mjs +107 -28
- package/scripts/lib/reconcile/backlog.mjs +368 -0
- package/scripts/lib/reconcile/engine.mjs +55 -188
- package/scripts/lib/reconcile/rule-expiry-sweep.mjs +302 -60
- package/scripts/lib/reconcile/sanitize.mjs +69 -3
- package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
- package/scripts/lib/resource-probe/parsers.mjs +31 -0
- package/scripts/lib/rule-loader.mjs +41 -12
- package/scripts/lib/scope-echo.mjs +39 -2
- package/scripts/lib/scope-gate.mjs +605 -1
- package/scripts/lib/session-close-backfill.mjs +33 -6
- package/scripts/lib/session-id.mjs +9 -20
- package/scripts/lib/session-invocation.mjs +20 -0
- package/scripts/lib/session-schema/constants.mjs +30 -2
- package/scripts/lib/session-schema/normalizer.mjs +56 -4
- package/scripts/lib/session-schema.mjs +8 -3
- package/scripts/lib/session-start-probes.mjs +95 -10
- package/scripts/lib/sessions-canonical.mjs +23 -0
- package/scripts/lib/sessions-integrity-banner.mjs +7 -1
- package/scripts/lib/sessions-staleness-banner.mjs +193 -51
- package/scripts/lib/skill-evidence-window.mjs +891 -0
- package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
- package/scripts/lib/skill-evolution/engine.mjs +18 -9
- package/scripts/lib/skill-judge.mjs +45 -3
- package/scripts/lib/tail-window.mjs +56 -0
- package/scripts/lib/telemetry/schema.mjs +30 -0
- package/scripts/lib/telemetry/sync.mjs +61 -6
- package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
- package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
- package/scripts/lib/tmux-layout/telemetry-stats.mjs +72 -13
- package/scripts/lib/user-invocable-skills.mjs +23 -3
- package/scripts/lib/ux-grill/reconcile.mjs +48 -22
- package/scripts/lib/validate/check-agents-skills.mjs +26 -15
- package/scripts/lib/validate/check-cursor-adapter.mjs +1 -0
- package/scripts/lib/validate/check-entry-guard.mjs +13 -50
- package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
- package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
- package/scripts/lib/validate/check-rules.mjs +7 -5
- package/scripts/lib/validate/check-skill-links.mjs +9 -1
- package/scripts/lib/validate/check-skill-script-paths.mjs +239 -27
- package/scripts/lib/validate/check-test-git-config-target.mjs +24 -34
- package/scripts/lib/validate/check-untracked-test-deps.mjs +7 -102
- package/scripts/lib/validate/check-unwired-features.mjs +130 -27
- package/scripts/lib/validate/check-validator-registration.mjs +34 -10
- package/scripts/lib/validate/confidential-names.mjs +10 -0
- package/scripts/lib/validate-vendored-rules.mjs +4 -3
- package/scripts/lib/vault-mirror/namespace.mjs +46 -8
- package/scripts/lib/vault-mirror/process.mjs +10 -3
- package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
- package/scripts/lib/vault-status/narrative-mirror.mjs +31 -7
- package/scripts/lib/vault-yaml.mjs +118 -0
- package/scripts/lib/worktree/lifecycle.mjs +153 -1
- package/scripts/release-session-lock.mjs +305 -0
- package/scripts/release.mjs +30 -5
- package/scripts/resolve-session-invocation.mjs +59 -0
- package/scripts/run-quality-gate.mjs +156 -17
- package/scripts/sweep-expired-rules.mjs +14 -3
- package/scripts/validate-plugin.mjs +12 -0
- package/scripts/validate-wave-scope.mjs +32 -105
- package/scripts/vault-mirror.mjs +9 -1
- package/skills/_shared/platform-tools.md +23 -11
- package/skills/autopilot/SKILL.md +22 -7
- package/skills/claude-md-drift-check/SKILL.md +1 -1
- package/skills/convergence-monitoring/README.md +8 -1
- package/skills/convergence-monitoring/SIGNALS.md +50 -6
- package/skills/convergence-monitoring/SKILL.md +15 -6
- package/skills/eval/SKILL.md +39 -24
- package/skills/eval/rubric-v1.md +1 -0
- package/skills/eval/rubric-v2.md +457 -0
- package/skills/evolve/SKILL.md +1 -1
- package/skills/evolve/references/evolve-dialectic-mode.md +42 -25
- package/skills/gitlab-ops/SKILL.md +3 -2
- package/skills/npm-publish/SKILL.md +1 -1
- package/skills/reconcile/SKILL.md +11 -0
- package/skills/session-end/SKILL.md +13 -16
- package/skills/session-end/discovery-scan.md +1 -1
- package/skills/session-end/phase-3-6-tail.md +55 -9
- package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
- package/skills/session-end/session-metrics-write.md +10 -0
- package/skills/session-plan/SKILL.md +17 -5
- package/skills/session-plan/references/session-plan-task-classification.md +2 -2
- package/skills/session-start/references/phase-4-ssot-environment-check.md +2 -1
- package/skills/ux-grill/SKILL.md +1 -1
- package/skills/wave-executor/SKILL.md +8 -4
- package/skills/wave-executor/circuit-breaker.md +2 -0
- package/skills/wave-executor/references/wave-executor-state-init.md +5 -3
- package/skills/wave-executor/references/wave-loop-dispatch.md +2 -1
- package/.codex-plugin/skills/convergence-monitoring/agents/openai.yaml +0 -5
- package/.codex-plugin/skills/npm-publish/agents/openai.yaml +0 -5
- package/.cursor/commands/convergence-monitoring.md +0 -13
- package/.cursor/commands/npm-publish.md +0 -13
- package/pi/prompts/convergence-monitoring.md +0 -11
- package/pi/prompts/npm-publish.md +0 -11
|
@@ -70,9 +70,10 @@
|
|
|
70
70
|
* @module scripts/lib/maintenance-due-banner
|
|
71
71
|
*/
|
|
72
72
|
|
|
73
|
-
import {
|
|
73
|
+
import { existsSync, statSync } from 'node:fs';
|
|
74
74
|
import path from 'node:path';
|
|
75
75
|
|
|
76
|
+
import { SCAN_CHUNK_BYTES, scanEventsBackwards } from './events.mjs';
|
|
76
77
|
import { computeReconcileNudge } from './reconcile-nudge-banner.mjs';
|
|
77
78
|
import { sweepExpiredLearnings } from './learnings/expiry-sweep.mjs';
|
|
78
79
|
import { shouldDispatchAutoDialectic } from './auto-dialectic.mjs';
|
|
@@ -152,104 +153,64 @@ function isoDay(ts) {
|
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
/**
|
|
155
|
-
* Backwards-scan chunk size (#1290 item 2)
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* handful of reads instead of loading the whole 7.9 MB file. The scan is
|
|
160
|
-
* UNBOUNDED in the worst case ON PURPOSE: "never ran" is a claim about every
|
|
161
|
-
* line and cannot be made from a tail, so a repo with no `evolve.completed`
|
|
162
|
-
* record still walks the file to its start — just in chunks, never all at once
|
|
163
|
-
* in one string.
|
|
164
|
-
*
|
|
165
|
-
* REVISIT TRIGGER: the maintenance probe's median passes 1000 ms (half
|
|
166
|
-
* `PROBE_BUDGET_MS`), or one repo's `events.jsonl` passes 50 MB. Either means
|
|
167
|
-
* the "never ran" walk has become the cost that matters and the answer needs an
|
|
168
|
-
* index rather than a scan.
|
|
156
|
+
* Backwards-scan chunk size (#1290 item 2) — the shared reader's constant, kept
|
|
157
|
+
* under this module's own name because it is the number this probe's cost is
|
|
158
|
+
* reasoned about in. NAMED CEILING + revisit trigger live at
|
|
159
|
+
* {@link SCAN_CHUNK_BYTES}.
|
|
169
160
|
*/
|
|
170
|
-
export const TAIL_CHUNK_BYTES =
|
|
161
|
+
export const TAIL_CHUNK_BYTES = SCAN_CHUNK_BYTES;
|
|
171
162
|
|
|
172
163
|
/**
|
|
173
|
-
*
|
|
164
|
+
* Wall-clock budget for the "did /evolve ever run?" walk (#1414).
|
|
165
|
+
*
|
|
166
|
+
* NAMED CEILING (BV-004): 1000 ms is half of `PROBE_BUDGET_MS` (2000 ms in
|
|
167
|
+
* `session-start-probes.mjs`), which this probe shares with six other signals.
|
|
168
|
+
* The walk is UNBOUNDED in principle — "never ran" is a claim about every line
|
|
169
|
+
* of every source — so it needs an own limit now that it spans the archives
|
|
170
|
+
* too, and running out must report `truncated`, never a clean "never".
|
|
174
171
|
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
172
|
+
* REVISIT TRIGGER: a repo where this reports `truncated` more than rarely. That
|
|
173
|
+
* means the answer needs an index rather than a scan, not a bigger budget
|
|
174
|
+
* (HR-101).
|
|
177
175
|
*/
|
|
178
|
-
|
|
179
|
-
if (buf.length === 0) return null;
|
|
180
|
-
const lines = buf.toString('utf8').split('\n');
|
|
181
|
-
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
182
|
-
const line = lines[i];
|
|
183
|
-
if (!line || !line.includes(EVOLVE_EVENT)) continue; // cheap pre-filter before JSON.parse
|
|
184
|
-
try {
|
|
185
|
-
const rec = JSON.parse(line);
|
|
186
|
-
if (rec?.event !== EVOLVE_EVENT) continue;
|
|
187
|
-
return { lastAt: typeof rec.timestamp === 'string' ? rec.timestamp : null };
|
|
188
|
-
} catch {
|
|
189
|
-
continue; // a malformed line is not evidence either way — keep scanning
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
176
|
+
export const EVOLVE_SCAN_BUDGET_MS = 1000;
|
|
194
177
|
|
|
195
178
|
/**
|
|
196
|
-
* Find the most recent `orchestrator.evolve.completed` record
|
|
197
|
-
*
|
|
198
|
-
* Reads the ledger BACKWARDS in {@link TAIL_CHUNK_BYTES} chunks and stops at
|
|
199
|
-
* the first hit, because the interesting answer is the LAST occurrence. The
|
|
200
|
-
* former implementation `readFileSync`-ed the whole file (7.9 MB here, 30–44 ms)
|
|
201
|
-
* to answer a question the last few kilobytes usually settle.
|
|
179
|
+
* Find the most recent `orchestrator.evolve.completed` record — across ROTATION
|
|
180
|
+
* boundaries (#1414).
|
|
202
181
|
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
182
|
+
* Walks the ledger backwards through every source, newest first, and stops at
|
|
183
|
+
* the first hit, because the interesting answer is the LAST occurrence. Reading
|
|
184
|
+
* the active file alone was the bug: "never ran" is a claim about EVERY line
|
|
185
|
+
* ever written, and after a rotation the only `evolve.completed` record on the
|
|
186
|
+
* host can sit in `_archive/` — the probe then nags a repo that has run
|
|
187
|
+
* /evolve, which is the HR-101 failure mode this module exists to avoid.
|
|
208
188
|
*
|
|
209
189
|
* @param {string} repoRoot
|
|
210
|
-
* @returns {{ok: boolean, lastAt: string|null}} `ok: false`
|
|
211
|
-
* but could not be read
|
|
190
|
+
* @returns {{ok: boolean, lastAt: string|null, truncated: boolean}} `ok: false`
|
|
191
|
+
* ⇒ a source exists but could not be read; `truncated: true` ⇒ the budget ran
|
|
192
|
+
* out before the walk finished. In BOTH cases the caller must record
|
|
193
|
+
* `undeterminable`, never clean — a walk that did not finish has not proven
|
|
194
|
+
* "never".
|
|
212
195
|
*/
|
|
213
196
|
function readLastEvolveRun(repoRoot) {
|
|
214
197
|
const file = path.join(repoRoot, '.orchestrator', 'metrics', 'events.jsonl');
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
carry = block; // no complete line yet — a line longer than one chunk
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
const hit = scanEvolveLines(block.subarray(firstNewline + 1));
|
|
235
|
-
if (hit) return { ok: true, lastAt: hit.lastAt };
|
|
236
|
-
carry = block.subarray(0, firstNewline);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// pos === 0: the carry is the file's FIRST line, complete by construction.
|
|
240
|
-
const hit = scanEvolveLines(carry);
|
|
241
|
-
return { ok: true, lastAt: hit ? hit.lastAt : null };
|
|
242
|
-
} catch {
|
|
243
|
-
return { ok: false, lastAt: null };
|
|
244
|
-
} finally {
|
|
245
|
-
if (fd !== undefined) {
|
|
246
|
-
try {
|
|
247
|
-
closeSync(fd);
|
|
248
|
-
} catch {
|
|
249
|
-
/* best-effort */
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
198
|
+
let lastAt = null;
|
|
199
|
+
const scan = scanEventsBackwards({
|
|
200
|
+
filePath: file,
|
|
201
|
+
chunkBytes: TAIL_CHUNK_BYTES,
|
|
202
|
+
budgetMs: EVOLVE_SCAN_BUDGET_MS,
|
|
203
|
+
// Cheap substring pre-filter before JSON.parse — the property the previous
|
|
204
|
+
// hand-rolled scan was written for, kept here rather than re-derived.
|
|
205
|
+
filter: EVOLVE_EVENT,
|
|
206
|
+
onRecord: (rec) => {
|
|
207
|
+
if (rec?.event !== EVOLVE_EVENT) return false;
|
|
208
|
+
lastAt = typeof rec.timestamp === 'string' ? rec.timestamp : null;
|
|
209
|
+
return true;
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
if (scan.unreadable.length > 0) return { ok: false, lastAt: null, truncated: false };
|
|
213
|
+
return { ok: true, lastAt, truncated: scan.truncated };
|
|
253
214
|
}
|
|
254
215
|
|
|
255
216
|
/**
|
|
@@ -335,7 +296,9 @@ export async function computeMaintenanceDue(opts = {}) {
|
|
|
335
296
|
} else {
|
|
336
297
|
// --- evolve (S1) -------------------------------------------------------
|
|
337
298
|
const evolve = readLastEvolveRun(repoRoot);
|
|
338
|
-
|
|
299
|
+
// `truncated` is NOT "not found": a walk that ran out of budget proves
|
|
300
|
+
// nothing about the lines it never reached (#1414).
|
|
301
|
+
if (!evolve.ok || evolve.truncated) {
|
|
339
302
|
undeterminable.push('evolve');
|
|
340
303
|
} else if (evolve.lastAt === null && nudge.activeLearnings >= MAINTENANCE_MIN_LEARNINGS) {
|
|
341
304
|
markDue('evolve', `never, ${nudge.activeLearnings} active learnings`);
|
|
@@ -344,7 +307,9 @@ export async function computeMaintenanceDue(opts = {}) {
|
|
|
344
307
|
// --- reconcile (S3) ----------------------------------------------------
|
|
345
308
|
if (nudge.nudge === true) {
|
|
346
309
|
// HR-106: report what the rule JUDGED. `computeReconcileNudge` nudges on
|
|
347
|
-
// a BACKLOG
|
|
310
|
+
// a BACKLOG — rule-eligible learnings minus those already materialized
|
|
311
|
+
// in the sidecar or `.claude/rules/` (`countReconcileBacklog`, #1380;
|
|
312
|
+
// before #1380 it counted all eligible ones) — never on a date — so
|
|
348
313
|
// printing `lastRunAt` here put today's date next to the word "due" and
|
|
349
314
|
// read as "last run today and already due again". Measured 2026-09-09
|
|
350
315
|
// (learning 013a45ba): with 108 learnings capped under
|