harnery 0.36.0 → 0.37.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/dist/commander.js +4 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +87 -46
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +26 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +11 -0
- package/dist/commands/diagnostics.d.ts +4 -0
- package/dist/commands/diagnostics.d.ts.map +1 -0
- package/dist/commands/diagnostics.js +229 -0
- package/dist/commands/files.d.ts +12 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -1
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +4 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +71 -2
- package/dist/commands/qa-run.d.ts +4 -0
- package/dist/commands/qa-run.d.ts.map +1 -0
- package/dist/commands/qa-run.js +141 -0
- package/dist/commands/resources.d.ts +4 -0
- package/dist/commands/resources.d.ts.map +1 -0
- package/dist/commands/resources.js +29 -0
- package/dist/commands/supervisor.d.ts +4 -0
- package/dist/commands/supervisor.d.ts.map +1 -0
- package/dist/commands/supervisor.js +101 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +17 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +4 -0
- package/dist/core/agents/cli.js +7 -3
- package/dist/core/agents/health.d.ts +17 -0
- package/dist/core/agents/health.d.ts.map +1 -0
- package/dist/core/agents/health.js +109 -0
- package/dist/core/agents/mailbox.d.ts +92 -0
- package/dist/core/agents/mailbox.d.ts.map +1 -0
- package/dist/core/agents/mailbox.js +325 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts +44 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts.map +1 -0
- package/dist/core/agents/reconcile-coordination-v3.js +58 -0
- package/dist/core/agents/render/prompt-context.d.ts +5 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +34 -13
- package/dist/core/agents/render/session-context.d.ts +8 -0
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +34 -3
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +50 -1
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +6 -10
- package/dist/core/agents/session-finalizer-v3.js +4 -1
- package/dist/core/artifacts/index.d.ts +26 -1
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +146 -6
- package/dist/core/config.d.ts +12 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +43 -0
- package/dist/core/diagnostics/advice.d.ts +9 -0
- package/dist/core/diagnostics/advice.d.ts.map +1 -0
- package/dist/core/diagnostics/advice.js +112 -0
- package/dist/core/diagnostics/bundle.d.ts +35 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -0
- package/dist/core/diagnostics/bundle.js +874 -0
- package/dist/core/diagnostics/comparison.d.ts +5 -0
- package/dist/core/diagnostics/comparison.d.ts.map +1 -0
- package/dist/core/diagnostics/comparison.js +444 -0
- package/dist/core/diagnostics/contract.d.ts +245 -0
- package/dist/core/diagnostics/contract.d.ts.map +1 -0
- package/dist/core/diagnostics/contract.js +18 -0
- package/dist/core/diagnostics/identity.d.ts +3 -0
- package/dist/core/diagnostics/identity.d.ts.map +1 -0
- package/dist/core/diagnostics/identity.js +10 -0
- package/dist/core/diagnostics/index.d.ts +8 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -0
- package/dist/core/diagnostics/index.js +7 -0
- package/dist/core/diagnostics/replay.d.ts +8 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -0
- package/dist/core/diagnostics/replay.js +213 -0
- package/dist/core/diagnostics/sanitize.d.ts +9 -0
- package/dist/core/diagnostics/sanitize.d.ts.map +1 -0
- package/dist/core/diagnostics/sanitize.js +84 -0
- package/dist/core/events/legacy-storage/compression.d.ts +13 -0
- package/dist/core/events/legacy-storage/compression.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/compression.js +107 -0
- package/dist/core/events/legacy-storage/index.d.ts +1 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/index.js +1 -0
- package/dist/core/events/v3/archive-retention.d.ts +33 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -0
- package/dist/core/events/v3/archive-retention.js +195 -0
- package/dist/core/events/v3/capabilities.d.ts +1 -1
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +1 -0
- package/dist/core/events/v3/index.d.ts +1 -0
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +1 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +1 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +1 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +13 -2
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +1 -0
- package/dist/core/events/v3/producers/recorder.d.ts +16 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +88 -1
- package/dist/core/hooks/adapter/output.d.ts +8 -0
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +11 -1
- package/dist/core/hooks/cli.js +183 -192
- package/dist/core/hooks/health.d.ts +59 -0
- package/dist/core/hooks/health.d.ts.map +1 -0
- package/dist/core/hooks/health.js +84 -0
- package/dist/core/resources/contract.d.ts +90 -0
- package/dist/core/resources/contract.d.ts.map +1 -0
- package/dist/core/resources/contract.js +2 -0
- package/dist/core/resources/index.d.ts +6 -0
- package/dist/core/resources/index.d.ts.map +1 -0
- package/dist/core/resources/index.js +5 -0
- package/dist/core/resources/sampler.d.ts +27 -0
- package/dist/core/resources/sampler.d.ts.map +1 -0
- package/dist/core/resources/sampler.js +357 -0
- package/dist/core/resources/service-status.d.ts +3 -0
- package/dist/core/resources/service-status.d.ts.map +1 -0
- package/dist/core/resources/service-status.js +48 -0
- package/dist/core/resources/service.d.ts +26 -0
- package/dist/core/resources/service.d.ts.map +1 -0
- package/dist/core/resources/service.js +292 -0
- package/dist/core/resources/storage.d.ts +13 -0
- package/dist/core/resources/storage.d.ts.map +1 -0
- package/dist/core/resources/storage.js +30 -0
- package/dist/core/storage/atomic-json.d.ts +3 -0
- package/dist/core/storage/atomic-json.d.ts.map +1 -0
- package/dist/core/storage/atomic-json.js +15 -0
- package/dist/core/storage/builtins.d.ts.map +1 -1
- package/dist/core/storage/builtins.js +45 -6
- package/dist/core/storage/logger.d.ts +2 -0
- package/dist/core/storage/logger.d.ts.map +1 -1
- package/dist/core/storage/logger.js +2 -0
- package/dist/core/storage/query.d.ts +14 -0
- package/dist/core/storage/query.d.ts.map +1 -1
- package/dist/core/storage/query.js +51 -0
- package/dist/core/supervisor/activity.d.ts +4 -0
- package/dist/core/supervisor/activity.d.ts.map +1 -0
- package/dist/core/supervisor/activity.js +141 -0
- package/dist/core/supervisor/contract.d.ts +268 -0
- package/dist/core/supervisor/contract.d.ts.map +1 -0
- package/dist/core/supervisor/contract.js +35 -0
- package/dist/core/supervisor/explanations.d.ts +4 -0
- package/dist/core/supervisor/explanations.d.ts.map +1 -0
- package/dist/core/supervisor/explanations.js +71 -0
- package/dist/core/supervisor/findings.d.ts +20 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -0
- package/dist/core/supervisor/findings.js +399 -0
- package/dist/core/supervisor/history.d.ts +9 -0
- package/dist/core/supervisor/history.d.ts.map +1 -0
- package/dist/core/supervisor/history.js +46 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts +14 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-alerts.js +70 -0
- package/dist/core/supervisor/hook-health-storage.d.ts +5 -0
- package/dist/core/supervisor/hook-health-storage.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-storage.js +24 -0
- package/dist/core/supervisor/hook-health.d.ts +72 -0
- package/dist/core/supervisor/hook-health.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health.js +203 -0
- package/dist/core/supervisor/hooks.d.ts +10 -0
- package/dist/core/supervisor/hooks.d.ts.map +1 -0
- package/dist/core/supervisor/hooks.js +28 -0
- package/dist/core/supervisor/index.d.ts +15 -0
- package/dist/core/supervisor/index.d.ts.map +1 -0
- package/dist/core/supervisor/index.js +14 -0
- package/dist/core/supervisor/log-feed.d.ts +9 -0
- package/dist/core/supervisor/log-feed.d.ts.map +1 -0
- package/dist/core/supervisor/log-feed.js +103 -0
- package/dist/core/supervisor/service.d.ts +29 -0
- package/dist/core/supervisor/service.d.ts.map +1 -0
- package/dist/core/supervisor/service.js +450 -0
- package/dist/core/supervisor/services.d.ts +11 -0
- package/dist/core/supervisor/services.d.ts.map +1 -0
- package/dist/core/supervisor/services.js +155 -0
- package/dist/core/supervisor/status.d.ts +3 -0
- package/dist/core/supervisor/status.d.ts.map +1 -0
- package/dist/core/supervisor/status.js +48 -0
- package/dist/core/supervisor/storage.d.ts +30 -0
- package/dist/core/supervisor/storage.d.ts.map +1 -0
- package/dist/core/supervisor/storage.js +73 -0
- package/dist/core/supervisor/timeline.d.ts +3 -0
- package/dist/core/supervisor/timeline.d.ts.map +1 -0
- package/dist/core/supervisor/timeline.js +87 -0
- package/dist/core/workflow/admission.d.ts +23 -0
- package/dist/core/workflow/admission.d.ts.map +1 -0
- package/dist/core/workflow/admission.js +136 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +77 -2
- package/dist/core/workflow/index.d.ts +3 -2
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +2 -1
- package/dist/core/workflow/proof.d.ts +2 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +39 -1
- package/dist/core/workflow/run-state.d.ts +3 -2
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +8 -1
- package/dist/core/workflow/types.d.ts +33 -1
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +2 -1
- package/dist/lib/browser/client.d.ts +5 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +1 -0
- package/dist/lib/browser/index.d.ts +2 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +173 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
- package/dist/lib/browser/qa-run-contracts.js +226 -0
- package/dist/lib/browser/qa-run.d.ts +51 -0
- package/dist/lib/browser/qa-run.d.ts.map +1 -0
- package/dist/lib/browser/qa-run.js +684 -0
- package/dist/lib/coord-root-id.d.ts +9 -0
- package/dist/lib/coord-root-id.d.ts.map +1 -0
- package/dist/lib/coord-root-id.js +17 -0
- package/dist/lib/instructions/apply.d.ts +3 -1
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +74 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +6 -0
- package/package.json +12 -1
- package/src/commander.ts +26 -0
- package/src/commands/agents.ts +102 -49
- package/src/commands/artifacts.ts +40 -2
- package/src/commands/browse.ts +15 -0
- package/src/commands/diagnostics.ts +271 -0
- package/src/commands/files.ts +102 -2
- package/src/commands/governor.ts +8 -0
- package/src/commands/ledger-v3.ts +82 -0
- package/src/commands/qa-run.ts +184 -0
- package/src/commands/resources.ts +38 -0
- package/src/commands/supervisor.ts +141 -0
- package/src/commands/web.ts +19 -0
- package/src/commands/workflow.ts +8 -0
- package/src/core/agents/cli.ts +7 -3
- package/src/core/agents/health.ts +142 -0
- package/src/core/agents/mailbox.ts +373 -0
- package/src/core/agents/reconcile-coordination-v3.ts +77 -0
- package/src/core/agents/render/prompt-context.ts +42 -12
- package/src/core/agents/render/session-context.ts +37 -3
- package/src/core/agents/rules/commit-conflict.ts +58 -1
- package/src/core/agents/rules/stop-hook.ts +6 -12
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/artifacts/index.ts +196 -10
- package/src/core/config.ts +111 -2
- package/src/core/diagnostics/advice.ts +147 -0
- package/src/core/diagnostics/bundle.ts +1142 -0
- package/src/core/diagnostics/comparison.ts +565 -0
- package/src/core/diagnostics/contract.ts +311 -0
- package/src/core/diagnostics/identity.ts +11 -0
- package/src/core/diagnostics/index.ts +7 -0
- package/src/core/diagnostics/replay.ts +314 -0
- package/src/core/diagnostics/sanitize.ts +97 -0
- package/src/core/events/legacy-storage/compression.ts +130 -0
- package/src/core/events/legacy-storage/index.ts +1 -0
- package/src/core/events/v3/archive-retention.ts +251 -0
- package/src/core/events/v3/capabilities.ts +2 -0
- package/src/core/events/v3/index.ts +9 -0
- package/src/core/events/v3/live-routing.ts +1 -0
- package/src/core/events/v3/producers/hook-base.ts +14 -2
- package/src/core/events/v3/producers/intake.ts +1 -0
- package/src/core/events/v3/producers/recorder.ts +110 -1
- package/src/core/hooks/adapter/output.ts +12 -1
- package/src/core/hooks/cli.ts +192 -215
- package/src/core/hooks/health.ts +146 -0
- package/src/core/resources/contract.ts +98 -0
- package/src/core/resources/index.ts +5 -0
- package/src/core/resources/sampler.ts +458 -0
- package/src/core/resources/service-status.ts +62 -0
- package/src/core/resources/service.ts +337 -0
- package/src/core/resources/storage.ts +44 -0
- package/src/core/storage/atomic-json.ts +15 -0
- package/src/core/storage/builtins.ts +62 -6
- package/src/core/storage/logger.ts +2 -0
- package/src/core/storage/query.ts +58 -0
- package/src/core/supervisor/activity.ts +193 -0
- package/src/core/supervisor/contract.ts +312 -0
- package/src/core/supervisor/explanations.ts +104 -0
- package/src/core/supervisor/findings.ts +788 -0
- package/src/core/supervisor/history.ts +61 -0
- package/src/core/supervisor/hook-health-alerts.ts +108 -0
- package/src/core/supervisor/hook-health-storage.ts +25 -0
- package/src/core/supervisor/hook-health.ts +301 -0
- package/src/core/supervisor/hooks.ts +35 -0
- package/src/core/supervisor/index.ts +14 -0
- package/src/core/supervisor/log-feed.ts +131 -0
- package/src/core/supervisor/service.ts +511 -0
- package/src/core/supervisor/services.ts +203 -0
- package/src/core/supervisor/status.ts +59 -0
- package/src/core/supervisor/storage.ts +126 -0
- package/src/core/supervisor/timeline.ts +133 -0
- package/src/core/workflow/admission.ts +215 -0
- package/src/core/workflow/engine.ts +93 -1
- package/src/core/workflow/index.ts +10 -0
- package/src/core/workflow/proof.ts +54 -1
- package/src/core/workflow/run-state.ts +13 -1
- package/src/core/workflow/types.ts +39 -1
- package/src/lib/browser/client.ts +6 -0
- package/src/lib/browser/index.ts +29 -0
- package/src/lib/browser/qa-run-contracts.ts +380 -0
- package/src/lib/browser/qa-run.ts +784 -0
- package/src/lib/coord-root-id.ts +23 -0
- package/src/lib/instructions/apply.ts +81 -2
- package/src/lib/instructions/templates.ts +6 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { monorepoRoot, resolveOwner } from "../core/agents/index.js";
|
|
2
|
+
import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.js";
|
|
3
|
+
import { buildDiagnosticAdvice, captureDiagnosticBundle, compareDiagnosticBundles, DIAGNOSTIC_COMMAND_SCHEMA_VERSION, listDiagnosticBundles, renderDiagnosticBundleComparison, replayDiagnosticBundle, showDiagnosticBundle, } from "../core/diagnostics/index.js";
|
|
4
|
+
import { buildSupervisorTimeline, explainSupervisorFinding, readSupervisorExplanation, readSupervisorFindings, readSupervisorStatus, readSupervisorTimeline, } from "../core/supervisor/index.js";
|
|
5
|
+
export function registerDiagnosticsCommand(program, emit, context) {
|
|
6
|
+
const root = program
|
|
7
|
+
.command("diagnostics")
|
|
8
|
+
.description("Capture, inspect, and replay sanitized local diagnostic bundles.");
|
|
9
|
+
root
|
|
10
|
+
.command("list")
|
|
11
|
+
.description("List live findings and managed diagnostic bundles.")
|
|
12
|
+
.action(() => {
|
|
13
|
+
run(emit, () => {
|
|
14
|
+
const repoRoot = requireRepoRoot(context);
|
|
15
|
+
const report = readSupervisorFindings(repoRoot);
|
|
16
|
+
const findings = mergeFindings(report?.active ?? [], report?.transitions ?? []);
|
|
17
|
+
const bundles = listDiagnosticBundles(repoRoot);
|
|
18
|
+
const capability = liveFindingsCapability(repoRoot, report !== undefined);
|
|
19
|
+
emit.data({
|
|
20
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
21
|
+
kind: "diagnostic_list",
|
|
22
|
+
findings,
|
|
23
|
+
bundles,
|
|
24
|
+
capability,
|
|
25
|
+
total_findings: findings.length,
|
|
26
|
+
total_bundles: bundles.length,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
root
|
|
31
|
+
.command("show <ref>")
|
|
32
|
+
.description("Show one finding or validate one diagnostic bundle.")
|
|
33
|
+
.action((ref) => {
|
|
34
|
+
run(emit, () => {
|
|
35
|
+
const repoRoot = requireRepoRoot(context);
|
|
36
|
+
const finding = findFinding(repoRoot, ref);
|
|
37
|
+
if (finding) {
|
|
38
|
+
emit.data({
|
|
39
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
40
|
+
kind: "diagnostic_finding",
|
|
41
|
+
finding,
|
|
42
|
+
timeline: readSupervisorTimeline(repoRoot, finding.id) ?? buildSupervisorTimeline(finding),
|
|
43
|
+
explanation: readSupervisorExplanation(repoRoot, finding.id) ?? explainSupervisorFinding(finding),
|
|
44
|
+
});
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const bundle = showDiagnosticBundle(repoRoot, ref);
|
|
48
|
+
emit.data({
|
|
49
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
50
|
+
kind: "diagnostic_bundle",
|
|
51
|
+
bundle: {
|
|
52
|
+
path: bundle.path,
|
|
53
|
+
manifest: bundle.manifest,
|
|
54
|
+
summary: bundle.summary,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
root
|
|
60
|
+
.command("explain")
|
|
61
|
+
.description("Report bounded local pressure advice without taking action.")
|
|
62
|
+
.option("--bundle <artifact-ref>", "Use a frozen diagnostic bundle instead of live state")
|
|
63
|
+
.option("--json", "Emit structured JSON")
|
|
64
|
+
.action((opts) => {
|
|
65
|
+
run(emit, () => {
|
|
66
|
+
if (opts.json)
|
|
67
|
+
emit.config({ format: "json" });
|
|
68
|
+
const repoRoot = requireRepoRoot(context);
|
|
69
|
+
if (opts.bundle) {
|
|
70
|
+
const bundle = showDiagnosticBundle(repoRoot, opts.bundle);
|
|
71
|
+
emit.data({
|
|
72
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
73
|
+
kind: "diagnostic_advice",
|
|
74
|
+
source: {
|
|
75
|
+
mode: "frozen",
|
|
76
|
+
artifact_id: bundle.manifest.artifact_id,
|
|
77
|
+
captured_at: bundle.manifest.captured_at,
|
|
78
|
+
},
|
|
79
|
+
advice: bundle.expected.advice,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const report = readSupervisorFindings(repoRoot);
|
|
84
|
+
const findings = mergeFindings(report?.active ?? [], report?.transitions ?? []);
|
|
85
|
+
const sourceCapability = liveFindingsCapability(repoRoot, report !== undefined);
|
|
86
|
+
emit.data({
|
|
87
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
88
|
+
kind: "diagnostic_advice",
|
|
89
|
+
source: { mode: "live" },
|
|
90
|
+
advice: buildDiagnosticAdvice({
|
|
91
|
+
findings,
|
|
92
|
+
sourceCapability,
|
|
93
|
+
evaluatedAt: new Date().toISOString(),
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
root
|
|
99
|
+
.command("capture")
|
|
100
|
+
.description("Capture sanitized supervisor inputs into a frozen managed bundle.")
|
|
101
|
+
.option("--finding <id>", "Capture the time range for one finding")
|
|
102
|
+
.option("--from <timestamp>", "Capture observations from this ISO timestamp")
|
|
103
|
+
.option("--to <timestamp>", "Capture observations through this ISO timestamp")
|
|
104
|
+
.option("--days <n>", "Managed artifact retention in days")
|
|
105
|
+
.action((opts) => {
|
|
106
|
+
run(emit, () => {
|
|
107
|
+
const repoRoot = requireRepoRoot(context);
|
|
108
|
+
const captured = captureDiagnosticBundle(repoRoot, {
|
|
109
|
+
findingId: opts.finding,
|
|
110
|
+
startAt: opts.from,
|
|
111
|
+
endAt: opts.to,
|
|
112
|
+
retentionDays: opts.days === undefined ? undefined : parseDays(opts.days),
|
|
113
|
+
actor: currentActor(repoRoot),
|
|
114
|
+
});
|
|
115
|
+
emit.data({
|
|
116
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
117
|
+
kind: "diagnostic_bundle_capture",
|
|
118
|
+
bundle: {
|
|
119
|
+
path: captured.path,
|
|
120
|
+
artifact_id: captured.manifest.artifact_id,
|
|
121
|
+
captured_at: captured.manifest.captured_at,
|
|
122
|
+
finding_id: captured.manifest.finding_id,
|
|
123
|
+
summary: captured.summary,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
root
|
|
129
|
+
.command("replay <artifact-ref>")
|
|
130
|
+
.description("Replay a frozen bundle without reading live supervisor state.")
|
|
131
|
+
.action((ref) => {
|
|
132
|
+
run(emit, () => {
|
|
133
|
+
emit.data({
|
|
134
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
135
|
+
kind: "diagnostic_bundle_replay",
|
|
136
|
+
replay: replayDiagnosticBundle(requireRepoRoot(context), ref),
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
root
|
|
141
|
+
.command("compare <before> <after>")
|
|
142
|
+
.description("Compare two frozen bundles without reading live supervisor state.")
|
|
143
|
+
.option("--json", "Emit structured JSON")
|
|
144
|
+
.action((before, after, opts) => {
|
|
145
|
+
run(emit, () => {
|
|
146
|
+
const comparison = compareDiagnosticBundles(requireRepoRoot(context), before, after);
|
|
147
|
+
if (opts.json) {
|
|
148
|
+
emit.config({ format: "json" });
|
|
149
|
+
emit.data({
|
|
150
|
+
schema_version: DIAGNOSTIC_COMMAND_SCHEMA_VERSION,
|
|
151
|
+
kind: "diagnostic_bundle_comparison",
|
|
152
|
+
comparison,
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
emit.text(renderDiagnosticBundleComparison(comparison));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function liveFindingsCapability(repoRoot, reportPresent) {
|
|
161
|
+
if (!reportPresent) {
|
|
162
|
+
return {
|
|
163
|
+
source_kind: "supervisor.findings",
|
|
164
|
+
state: "unsupported",
|
|
165
|
+
reason_code: "source_missing",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const status = readSupervisorStatus(repoRoot);
|
|
169
|
+
if (status.running)
|
|
170
|
+
return { source_kind: "supervisor.findings", state: "supported" };
|
|
171
|
+
return {
|
|
172
|
+
source_kind: "supervisor.findings",
|
|
173
|
+
state: "expired",
|
|
174
|
+
reason_code: status.stale
|
|
175
|
+
? "supervisor_status_stale"
|
|
176
|
+
: status.record
|
|
177
|
+
? "supervisor_not_running"
|
|
178
|
+
: "supervisor_status_missing",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function findFinding(repoRoot, id) {
|
|
182
|
+
const report = readSupervisorFindings(repoRoot);
|
|
183
|
+
return mergeFindings(report?.active ?? [], report?.transitions ?? []).find((finding) => finding.id === id);
|
|
184
|
+
}
|
|
185
|
+
function mergeFindings(active, transitions) {
|
|
186
|
+
const byId = new Map();
|
|
187
|
+
for (const finding of transitions)
|
|
188
|
+
byId.set(finding.id, finding);
|
|
189
|
+
for (const finding of active)
|
|
190
|
+
byId.set(finding.id, finding);
|
|
191
|
+
return [...byId.values()].sort((left, right) => Date.parse(right.observed_at) - Date.parse(left.observed_at) ||
|
|
192
|
+
left.id.localeCompare(right.id));
|
|
193
|
+
}
|
|
194
|
+
function currentActor(repoRoot) {
|
|
195
|
+
const instanceId = resolveOwner();
|
|
196
|
+
if (!instanceId)
|
|
197
|
+
return undefined;
|
|
198
|
+
const heartbeat = readLiveCoordinationRow(repoRoot, instanceId);
|
|
199
|
+
return {
|
|
200
|
+
instance_id: instanceId,
|
|
201
|
+
session_id: heartbeat?.session_id,
|
|
202
|
+
name: heartbeat?.name,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function requireRepoRoot(context) {
|
|
206
|
+
const root = context?.repoRoot ?? monorepoRoot();
|
|
207
|
+
if (!root)
|
|
208
|
+
throw new Error("not inside a Git repository");
|
|
209
|
+
return root;
|
|
210
|
+
}
|
|
211
|
+
function parseDays(value) {
|
|
212
|
+
const parsed = Number(value);
|
|
213
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 3_650) {
|
|
214
|
+
throw new Error("--days must be between 1 and 3650");
|
|
215
|
+
}
|
|
216
|
+
return parsed;
|
|
217
|
+
}
|
|
218
|
+
function run(emit, fn) {
|
|
219
|
+
try {
|
|
220
|
+
fn();
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
emit.error({
|
|
224
|
+
code: "diagnostics_failed",
|
|
225
|
+
message: error instanceof Error ? error.message : String(error),
|
|
226
|
+
});
|
|
227
|
+
emit.setExitCode(1);
|
|
228
|
+
}
|
|
229
|
+
}
|
package/dist/commands/files.d.ts
CHANGED
|
@@ -12,6 +12,18 @@ export interface LocalFileUrl {
|
|
|
12
12
|
relPath: string;
|
|
13
13
|
mode: Exclude<LocalFileUrlMode, "auto">;
|
|
14
14
|
}
|
|
15
|
+
export type DashboardRootErrorCode = "dashboard_unreachable" | "dashboard_identity_unavailable" | "dashboard_root_mismatch";
|
|
16
|
+
export declare class DashboardRootError extends Error {
|
|
17
|
+
readonly code: DashboardRootErrorCode;
|
|
18
|
+
readonly hint: string;
|
|
19
|
+
constructor(code: DashboardRootErrorCode, message: string, hint: string);
|
|
20
|
+
}
|
|
21
|
+
export type DashboardRootFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
22
|
+
/**
|
|
23
|
+
* Prove that the dashboard on the selected port serves the same canonical
|
|
24
|
+
* coordination root used to mint the file URL.
|
|
25
|
+
*/
|
|
26
|
+
export declare function verifyDashboardRoot(coordRoot: string, port: number, fetchImpl?: DashboardRootFetch): Promise<void>;
|
|
15
27
|
/**
|
|
16
28
|
* Mint the local browser URL for a file under the dashboard's coord root.
|
|
17
29
|
* HTML defaults to the isolated files origin so scripts and relative assets
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAM1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,gCAAgC,GAChC,yBAAyB,CAAC;AAE9B,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAErC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAFZ,IAAI,EAAE,sBAAsB,EACrC,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM;CAKxB;AAMD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC,IAAI,CAAC,CAmDf;AAuCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAS1F;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA0EN"}
|
package/dist/commands/files.js
CHANGED
|
@@ -2,8 +2,53 @@ import { realpathSync, statSync } from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { resolveCoordRoot } from "../core/agents/coord-client.js";
|
|
4
4
|
import { DEFAULT_WEB_PORT, resolveWebPort } from "../core/config.js";
|
|
5
|
+
import { coordRootId, localCoordRootIdUrl } from "../lib/coord-root-id.js";
|
|
5
6
|
import { localFilesOriginUrl, localFileViewerUrl } from "../lib/local-file-url.js";
|
|
6
7
|
export { FILES_ORIGIN_HOST } from "../lib/local-file-url.js";
|
|
8
|
+
export class DashboardRootError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
hint;
|
|
11
|
+
constructor(code, message, hint) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.hint = hint;
|
|
15
|
+
this.name = "DashboardRootError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Prove that the dashboard on the selected port serves the same canonical
|
|
20
|
+
* coordination root used to mint the file URL.
|
|
21
|
+
*/
|
|
22
|
+
export async function verifyDashboardRoot(coordRoot, port, fetchImpl = fetch) {
|
|
23
|
+
const url = localCoordRootIdUrl(port);
|
|
24
|
+
let response;
|
|
25
|
+
try {
|
|
26
|
+
response = await fetchImpl(url, {
|
|
27
|
+
headers: { accept: "application/json" },
|
|
28
|
+
signal: AbortSignal.timeout(5_000),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new DashboardRootError("dashboard_unreachable", `dashboard is not reachable at http://localhost:${port}`, "Start the dashboard for this repository, then retry.");
|
|
33
|
+
}
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw new DashboardRootError("dashboard_identity_unavailable", `dashboard at http://localhost:${port} cannot report its repository identity (HTTP ${response.status})`, "Update and restart the dashboard, then retry.");
|
|
36
|
+
}
|
|
37
|
+
let payload;
|
|
38
|
+
try {
|
|
39
|
+
payload = (await response.json());
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new DashboardRootError("dashboard_identity_unavailable", `dashboard at http://localhost:${port} returned an invalid repository identity`, "Update and restart the dashboard, then retry.");
|
|
43
|
+
}
|
|
44
|
+
if (typeof payload.root_id !== "string") {
|
|
45
|
+
throw new DashboardRootError("dashboard_identity_unavailable", `dashboard at http://localhost:${port} returned an invalid repository identity`, "Update and restart the dashboard, then retry.");
|
|
46
|
+
}
|
|
47
|
+
const expected = coordRootId(coordRoot);
|
|
48
|
+
if (payload.root_id !== expected) {
|
|
49
|
+
throw new DashboardRootError("dashboard_root_mismatch", `dashboard at http://localhost:${port} serves a different repository`, "Stop that dashboard and start this repository's dashboard, then retry.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
7
52
|
function isOutsideRoot(relPath) {
|
|
8
53
|
return relPath === "" || relPath === ".." || relPath.startsWith(`..${path.sep}`);
|
|
9
54
|
}
|
|
@@ -66,7 +111,8 @@ export function registerFilesCommand(program, emit, context) {
|
|
|
66
111
|
.option("--coord-root <dir>", "Override the coord root")
|
|
67
112
|
.option("--raw", "Use the isolated files origin, regardless of extension")
|
|
68
113
|
.option("--viewer", "Use the dashboard file viewer, regardless of extension")
|
|
69
|
-
.
|
|
114
|
+
.option("--no-verify", "Mint without checking the running dashboard's repository identity")
|
|
115
|
+
.action(async (filePath, opts) => {
|
|
70
116
|
if (opts.raw && opts.viewer) {
|
|
71
117
|
emit.error({
|
|
72
118
|
code: "conflicting_url_modes",
|
|
@@ -99,9 +145,16 @@ export function registerFilesCommand(program, emit, context) {
|
|
|
99
145
|
port,
|
|
100
146
|
mode: opts.raw ? "raw" : opts.viewer ? "viewer" : "auto",
|
|
101
147
|
});
|
|
148
|
+
if (opts.verify !== false)
|
|
149
|
+
await verifyDashboardRoot(coordRoot, port);
|
|
102
150
|
emit.text(`${result.url}\n`);
|
|
103
151
|
}
|
|
104
152
|
catch (error) {
|
|
153
|
+
if (error instanceof DashboardRootError) {
|
|
154
|
+
emit.error({ code: error.code, message: error.message, hint: error.hint });
|
|
155
|
+
emit.setExitCode(1);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
105
158
|
emit.error({
|
|
106
159
|
code: "invalid_local_file",
|
|
107
160
|
message: error instanceof Error ? error.message : "invalid local file path",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governor.d.ts","sourceRoot":"","sources":["../../src/commands/governor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"governor.d.ts","sourceRoot":"","sources":["../../src/commands/governor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA8EnD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA6HjF"}
|
|
@@ -302,6 +302,7 @@ function addServiceOptions(command) {
|
|
|
302
302
|
.option("--error-backoff-max-ms <n>", "Maximum service-error backoff (default 300000)")
|
|
303
303
|
.option("--adapter <name>", "Fallback adapter for agent calls without a specialist")
|
|
304
304
|
.option("--cwd <dir>", "Working directory for child agents")
|
|
305
|
+
.option("--observe-pressure", "Record observer-only local pressure before each workflow's first real child dispatch")
|
|
305
306
|
.option("--subscription-only", "Require stored adapter-login billing")
|
|
306
307
|
.option("--allow-api-billing", "Permit API-key override billing")
|
|
307
308
|
.option("--policy <file>", "Host policy JSON/JSONC")
|
|
@@ -431,6 +432,9 @@ function registerRunCommand(governor, mode, registry, emit) {
|
|
|
431
432
|
spawners: registry.spawners(),
|
|
432
433
|
defaultAdapter: opts.adapter,
|
|
433
434
|
cwd: opts.cwd,
|
|
435
|
+
diagnosticAdmission: opts.observePressure
|
|
436
|
+
? { schema_version: 1, mode: "shadow" }
|
|
437
|
+
: undefined,
|
|
434
438
|
subscriptionOnly: opts.subscriptionOnly === true ? true : workflowSubscriptionOnly(coordRoot),
|
|
435
439
|
allowApiBilling: opts.allowApiBilling,
|
|
436
440
|
...adapterProofInputs(registry.list().map((adapter) => adapter.profile), { versionProbe: probeBinaryVersion }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-v3.d.ts","sourceRoot":"","sources":["../../src/commands/ledger-v3.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ledger-v3.d.ts","sourceRoot":"","sources":["../../src/commands/ledger-v3.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAsC1E,2DAA2D;AAC3D,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAiaN"}
|
|
@@ -2,8 +2,8 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
|
-
import { inventoryLegacyV1Segments, streamLegacyV1Rows, verifyLegacyV1HardFence, writeLegacyV1Canary, } from "../core/events/legacy-storage/index.js";
|
|
6
|
-
import { initializeEventLedgerV3, readEventV3ControlState, recoverInvalidEventLedgerV3, sha256V3, } from "../core/events/v3/index.js";
|
|
5
|
+
import { compressSealedLegacyV1Segments, inventoryLegacyV1Segments, streamLegacyV1Rows, verifyLegacyV1HardFence, writeLegacyV1Canary, } from "../core/events/legacy-storage/index.js";
|
|
6
|
+
import { cleanEventV3Archives, initializeEventLedgerV3, inventoryEventV3Archives, readEventV3ControlState, recoverInvalidEventLedgerV3, sha256V3, } from "../core/events/v3/index.js";
|
|
7
7
|
import { authorizeEventV3SupportReplacement, inventoryEventV3Support, planEventV3SupportReplacement, planEventV3SupportTransaction, readEventV3SupportPackManifest, readEventV3SupportTransaction, streamEventV3SupportPackRecords, unpackEventV3SupportPack, verifyEventV3SupportTransactionShadow, writeEventV3SupportTransactionShadow, } from "../core/events/v3/support-storage/index.js";
|
|
8
8
|
/** Inspect or initialize the universal V3 event ledger. */
|
|
9
9
|
export function registerLedgerV3Command(program, emit, context) {
|
|
@@ -21,6 +21,38 @@ export function registerLedgerV3Command(program, emit, context) {
|
|
|
21
21
|
emitFailure(emit, "ledger_v3_status_failed", error);
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
+
const archives = command
|
|
25
|
+
.command("archives")
|
|
26
|
+
.description("Inventory and enforce bounded retention for complete closed V3 epochs");
|
|
27
|
+
archives
|
|
28
|
+
.command("list")
|
|
29
|
+
.description("Show closed epochs, retention classifications, and planned actions")
|
|
30
|
+
.option("--root <path>", "Explicit coordination root")
|
|
31
|
+
.action((options) => {
|
|
32
|
+
try {
|
|
33
|
+
const rows = inventoryEventV3Archives(resolve(options.root ?? coordRoot(context)));
|
|
34
|
+
emit.data({ rows, meta: summarizeArchiveRows(rows) });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
emitFailure(emit, "ledger_v3_archive_inventory_failed", error);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
archives
|
|
41
|
+
.command("clean")
|
|
42
|
+
.description("Preview closed-epoch deletion; pass --yes to execute the exact current plan")
|
|
43
|
+
.option("--root <path>", "Explicit coordination root")
|
|
44
|
+
.option("--yes", "Delete only epochs still classified expired or over-budget")
|
|
45
|
+
.action((options) => {
|
|
46
|
+
try {
|
|
47
|
+
const rows = cleanEventV3Archives(resolve(options.root ?? coordRoot(context)), {
|
|
48
|
+
yes: options.yes,
|
|
49
|
+
});
|
|
50
|
+
emit.data({ rows, meta: summarizeArchiveRows(rows) });
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
emitFailure(emit, "ledger_v3_archive_cleanup_failed", error);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
24
56
|
command
|
|
25
57
|
.command("initialize")
|
|
26
58
|
.description("Create V3 control state, or archive and replace the current V3 epoch")
|
|
@@ -279,6 +311,29 @@ export function registerLedgerV3Command(program, emit, context) {
|
|
|
279
311
|
emitFailure(emit, "ledger_v1_inventory_failed", error);
|
|
280
312
|
}
|
|
281
313
|
});
|
|
314
|
+
command
|
|
315
|
+
.command("legacy-compress")
|
|
316
|
+
.description("Preview verified gzip replacement of sealed non-terminal V1 shards")
|
|
317
|
+
.option("--root <path>", "Explicit coordination root")
|
|
318
|
+
.option("--yes", "Replace only unchanged shards after exact logical-row parity")
|
|
319
|
+
.action(async (options) => {
|
|
320
|
+
try {
|
|
321
|
+
const rows = await compressSealedLegacyV1Segments(resolve(options.root ?? coordRoot(context)), { yes: options.yes });
|
|
322
|
+
emit.data({
|
|
323
|
+
rows,
|
|
324
|
+
meta: {
|
|
325
|
+
total: rows.length,
|
|
326
|
+
would_compress: rows.filter((row) => row.action === "would-compress").length,
|
|
327
|
+
compressed: rows.filter((row) => row.action === "compressed").length,
|
|
328
|
+
bytes_before: rows.reduce((sum, row) => sum + row.bytes_before, 0),
|
|
329
|
+
bytes_after: rows.reduce((sum, row) => sum + (row.bytes_after ?? row.bytes_before), 0),
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
emitFailure(emit, "ledger_v1_compression_failed", error);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
282
337
|
command
|
|
283
338
|
.command("verify-legacy")
|
|
284
339
|
.description("Stream and validate one loose or manifest-bound gzip legacy segment")
|
|
@@ -431,6 +486,20 @@ function sameSortedStrings(left, right) {
|
|
|
431
486
|
return (leftSorted.length === rightSorted.length &&
|
|
432
487
|
leftSorted.every((value, index) => value === rightSorted[index]));
|
|
433
488
|
}
|
|
489
|
+
function summarizeArchiveRows(rows) {
|
|
490
|
+
const classifications = {};
|
|
491
|
+
for (const row of rows) {
|
|
492
|
+
classifications[row.classification] = (classifications[row.classification] ?? 0) + 1;
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
total: rows.length,
|
|
496
|
+
bytes: rows.reduce((sum, row) => sum + (row.bytes ?? 0), 0),
|
|
497
|
+
classifications,
|
|
498
|
+
would_delete: rows.filter((row) => row.action === "would-delete").length,
|
|
499
|
+
would_delete_bytes: rows.reduce((sum, row) => sum + (row.action === "would-delete" ? (row.bytes ?? 0) : 0), 0),
|
|
500
|
+
deleted: rows.filter((row) => row.action === "deleted").length,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
434
503
|
function emitFailure(emit, code, error) {
|
|
435
504
|
emit.error({ code, message: error instanceof Error ? error.message : String(error) });
|
|
436
505
|
throw error;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qa-run.d.ts","sourceRoot":"","sources":["../../src/commands/qa-run.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAiBnD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA+J9E"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// `qa-run <target>`: run the whole page-QA matrix (planner, deterministic
|
|
2
|
+
// gates, interactions, critique, snapshot) in one command. The agent's loop
|
|
3
|
+
// collapses to: build the job, run this, read page-qa-result.json.
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
import { QA_RUN_RESULT_FILENAME, runQaMatrix } from "../lib/browser/qa-run.js";
|
|
7
|
+
import { QA_RUN_JOB_SCHEMA_VERSION, validateQaRunJob, } from "../lib/browser/qa-run-contracts.js";
|
|
8
|
+
export function registerQaRunCommand(program, emit) {
|
|
9
|
+
program
|
|
10
|
+
.command("qa-run <target>")
|
|
11
|
+
.description("Run the whole page-QA matrix in one command: QA planner, deterministic " +
|
|
12
|
+
"gates per viewport/theme/state through a bounded process pool, serial " +
|
|
13
|
+
"interaction assertions, manifest-required vision critique, and the QA " +
|
|
14
|
+
"snapshot. Writes page-qa-result.json with a fail-closed verdict.")
|
|
15
|
+
.option("--job <file>", "QA job document (JSON). Validated before any browser starts — secret-bearing " +
|
|
16
|
+
"fields are refused, and the job may widen but never narrow the planner's coverage. " +
|
|
17
|
+
"Absent: a minimal implicit job for <target> is used.")
|
|
18
|
+
.option("--mode <mode>", "signoff persists a QA snapshot on a passing run; review never does.", "signoff")
|
|
19
|
+
.option("--concurrency <n>", "Concurrent deterministic captures (1-8; default 2). Interactions and critique " +
|
|
20
|
+
"always run serially.")
|
|
21
|
+
.option("--allow-metered", "Permit the critique provider's metered-API fallback. Default: subscription-backed " +
|
|
22
|
+
"headless harnesses only — exhaustion becomes an incomplete blocker, never a metered call.")
|
|
23
|
+
.option("--out-dir <dir>", "Artifact + result directory (default: .qa-run/<timestamp> under the current directory).")
|
|
24
|
+
.option("--json", "Print the full QaRunResult JSON to stdout.")
|
|
25
|
+
.addHelpText("after", "\nExit codes: 0 verdict passed · 1 usage or job-validation error · " +
|
|
26
|
+
"2 verdict failed · 4 verdict incomplete.")
|
|
27
|
+
.action(async (target, opts, command) => {
|
|
28
|
+
if (opts.mode !== "signoff" && opts.mode !== "review") {
|
|
29
|
+
emit.error({
|
|
30
|
+
code: "qa_run_invalid_mode",
|
|
31
|
+
message: '--mode must be "signoff" or "review"',
|
|
32
|
+
});
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const modeExplicit = command.getOptionValueSource("mode") === "cli";
|
|
37
|
+
let jobDocument;
|
|
38
|
+
if (opts.job) {
|
|
39
|
+
let rawText;
|
|
40
|
+
try {
|
|
41
|
+
rawText = readFileSync(opts.job, "utf8");
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
emit.error({
|
|
45
|
+
code: "qa_run_job_unreadable",
|
|
46
|
+
message: `cannot read --job file ${opts.job}: ${err instanceof Error ? err.message : String(err)}`,
|
|
47
|
+
});
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(rawText);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
emit.error({
|
|
57
|
+
code: "qa_run_job_invalid_json",
|
|
58
|
+
message: `--job file ${opts.job} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
|
|
59
|
+
});
|
|
60
|
+
process.exitCode = 1;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
64
|
+
const raw = parsed;
|
|
65
|
+
// The CLI target argument is authoritative; a job file may omit
|
|
66
|
+
// target and mode. An explicit --mode overrides the job's mode.
|
|
67
|
+
jobDocument = {
|
|
68
|
+
...raw,
|
|
69
|
+
target,
|
|
70
|
+
...(raw.mode === undefined || modeExplicit ? { mode: opts.mode } : {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
jobDocument = parsed;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
jobDocument = { schema_version: QA_RUN_JOB_SCHEMA_VERSION, target, mode: opts.mode };
|
|
79
|
+
}
|
|
80
|
+
// All validation errors print at once, before any browser starts.
|
|
81
|
+
const validation = validateQaRunJob(jobDocument);
|
|
82
|
+
if (!validation.ok) {
|
|
83
|
+
for (const message of validation.errors)
|
|
84
|
+
emit.log(`job: ${message}`, "error");
|
|
85
|
+
emit.error({
|
|
86
|
+
code: "qa_run_invalid_job",
|
|
87
|
+
message: `job validation failed with ${validation.errors.length} error${validation.errors.length === 1 ? "" : "s"}`,
|
|
88
|
+
});
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const policy = { ...validation.job.policy };
|
|
93
|
+
if (opts.concurrency !== undefined) {
|
|
94
|
+
const n = Number.parseInt(opts.concurrency, 10);
|
|
95
|
+
if (!Number.isInteger(n) || n < 1 || n > 8) {
|
|
96
|
+
emit.error({
|
|
97
|
+
code: "qa_run_invalid_concurrency",
|
|
98
|
+
message: "--concurrency must be an integer between 1 and 8",
|
|
99
|
+
});
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
policy.command_concurrency = n;
|
|
104
|
+
}
|
|
105
|
+
if (opts.allowMetered)
|
|
106
|
+
policy.allow_metered_critique = true;
|
|
107
|
+
const job = { ...validation.job, policy };
|
|
108
|
+
const outDir = resolve(opts.outDir ?? join(".qa-run", new Date().toISOString().replace(/[:.]/g, "-")));
|
|
109
|
+
const cliScript = process.argv[1];
|
|
110
|
+
if (!cliScript) {
|
|
111
|
+
emit.error({
|
|
112
|
+
code: "qa_run_no_cli_script",
|
|
113
|
+
message: "cannot resolve the host CLI script path for child browse invocations",
|
|
114
|
+
});
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Children run the same host CLI, so they inherit the host's browse
|
|
119
|
+
// wiring (critique provider, cookie jar, profiles) unchanged.
|
|
120
|
+
const browseArgv = [process.execPath, cliScript, "browse"];
|
|
121
|
+
const result = await runQaMatrix({
|
|
122
|
+
job,
|
|
123
|
+
outDir,
|
|
124
|
+
browseArgv,
|
|
125
|
+
onLog: (message) => emit.log(message, "info"),
|
|
126
|
+
});
|
|
127
|
+
if (opts.json)
|
|
128
|
+
emit.data(result);
|
|
129
|
+
const resultPath = join(outDir, QA_RUN_RESULT_FILENAME);
|
|
130
|
+
for (const blocker of result.blockers) {
|
|
131
|
+
emit.log(`blocker [${blocker.stage}${blocker.context_id ? ` ${blocker.context_id}` : ""}]: ${blocker.reason}`, "warn");
|
|
132
|
+
}
|
|
133
|
+
emit.log(`verdict: ${result.verdict} — ${result.contexts.length} context${result.contexts.length === 1 ? "" : "s"}, ` +
|
|
134
|
+
`${result.commands.length} command${result.commands.length === 1 ? "" : "s"}, ` +
|
|
135
|
+
`${result.blockers.length} blocker${result.blockers.length === 1 ? "" : "s"}; result: ${resultPath}`, result.verdict === "passed" ? "info" : "warn");
|
|
136
|
+
if (result.verdict === "failed")
|
|
137
|
+
process.exitCode = 2;
|
|
138
|
+
else if (result.verdict === "incomplete")
|
|
139
|
+
process.exitCode = 4;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { EmitContext, HarneryProgramContext } from "../commander.js";
|
|
3
|
+
export declare function registerResourcesCommand(program: Command, emit: EmitContext, context?: HarneryProgramContext): void;
|
|
4
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/commands/resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG1E,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAgBN"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { sampleResources } from "../core/resources/index.js";
|
|
3
|
+
export function registerResourcesCommand(program, emit, context) {
|
|
4
|
+
const resources = program
|
|
5
|
+
.command("resources")
|
|
6
|
+
.description("Observe local CPU and memory pressure by agent and process tree");
|
|
7
|
+
resources
|
|
8
|
+
.command("snapshot")
|
|
9
|
+
.description("Capture one machine and process-resource snapshot")
|
|
10
|
+
.option("--root <path>", "Explicit coordination root")
|
|
11
|
+
.action((options) => {
|
|
12
|
+
try {
|
|
13
|
+
emit.data(sampleResources(resolve(options.root ?? coordRoot(context))).snapshot);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
fail(emit, "resource_snapshot_failed", error);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function coordRoot(context) {
|
|
21
|
+
return context?.resolveCoordRoot?.() ?? context?.repoRoot ?? process.cwd();
|
|
22
|
+
}
|
|
23
|
+
function fail(emit, code, error) {
|
|
24
|
+
emit.error({
|
|
25
|
+
code,
|
|
26
|
+
message: error instanceof Error ? error.message : String(error),
|
|
27
|
+
});
|
|
28
|
+
emit.setExitCode(1);
|
|
29
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { EmitContext, HarneryProgramContext } from "../commander.js";
|
|
3
|
+
export declare function registerSupervisorCommand(program: Command, emit: EmitContext, context?: HarneryProgramContext): void;
|
|
4
|
+
//# sourceMappingURL=supervisor.d.ts.map
|