onto-mcp 0.3.2 → 0.4.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/.onto/processes/reconstruct/actionable-ontology-seed-recomposition-design.md +447 -0
- package/.onto/processes/reconstruct/foundry-style-ontology-seed-contract.md +934 -0
- package/.onto/processes/reconstruct/reconstruct-boundary-contract.md +303 -725
- package/.onto/processes/reconstruct/reconstruct-contract-registry.yaml +1645 -0
- package/.onto/processes/reconstruct/reconstruct-execution-ux-contract.md +26 -22
- package/.onto/processes/reconstruct/source-profile-contract.md +49 -23
- package/.onto/processes/reconstruct/source-profiles/code.md +6 -3
- package/.onto/processes/reconstruct/source-profiles/database.md +5 -2
- package/.onto/processes/reconstruct/source-profiles/document.md +5 -2
- package/.onto/processes/reconstruct/source-profiles/spreadsheet.md +5 -4
- package/.onto/processes/review/review-execution-ux-contract.md +40 -0
- package/.onto/processes/shared/pipeline-execution-ledger-contract.md +26 -10
- package/.onto/processes/shared/target-material-kind-contract.md +29 -16
- package/AGENTS.md +6 -4
- package/README.md +135 -76
- package/dist/cli.js +8 -8
- package/dist/core-api/reconstruct-api.js +117 -31
- package/dist/core-api/review-api.js +47 -0
- package/dist/core-runtime/cli/codex-review-unit-executor.js +39 -2
- package/dist/core-runtime/cli/complete-review-session.js +2 -2
- package/dist/core-runtime/cli/mock-review-unit-executor.js +1 -1
- package/dist/core-runtime/cli/review-invoke.js +9 -9
- package/dist/core-runtime/cli/run-review-prompt-execution.js +39 -5
- package/dist/core-runtime/cli/spawn-watcher.js +266 -47
- package/dist/core-runtime/cli/start-review-session.js +3 -3
- package/dist/core-runtime/llm/llm-caller.js +11 -0
- package/dist/core-runtime/llm/llm-tool-loop.js +2 -0
- package/dist/core-runtime/observability/runtime-stream-observation.js +118 -0
- package/dist/core-runtime/onboard/cli-host.js +149 -0
- package/dist/core-runtime/onboard/host-target.js +22 -0
- package/dist/core-runtime/onboard/json-config-host.js +122 -0
- package/dist/core-runtime/onboard/path-scan.js +26 -0
- package/dist/core-runtime/onboard/prompt.js +51 -0
- package/dist/core-runtime/onboard/register.js +207 -0
- package/dist/core-runtime/onboard/types.js +27 -0
- package/dist/core-runtime/reconstruct/actionable-seed-validation.js +1777 -0
- package/dist/core-runtime/reconstruct/artifact-types.js +10 -4
- package/dist/core-runtime/reconstruct/contract-registry.js +623 -0
- package/dist/core-runtime/reconstruct/domain-id.js +10 -0
- package/dist/core-runtime/reconstruct/governing-snapshot.js +716 -0
- package/dist/core-runtime/reconstruct/material-profile-validation.js +191 -0
- package/dist/core-runtime/reconstruct/materialize-preparation.js +49 -11
- package/dist/core-runtime/reconstruct/pipeline-execution-ledger.js +269 -79
- package/dist/core-runtime/reconstruct/post-seed-validation.js +1194 -51
- package/dist/core-runtime/reconstruct/record.js +104 -20
- package/dist/core-runtime/reconstruct/run.js +2107 -413
- package/dist/core-runtime/reconstruct/seed-claim-projections.js +268 -0
- package/dist/core-runtime/reconstruct/source-profiles.js +93 -4
- package/dist/core-runtime/reconstruct/terminal-validation.js +807 -0
- package/dist/core-runtime/review/review-invocation-runner.js +4 -4
- package/dist/mcp/server.js +110 -38
- package/dist/mcp/tool-schemas.js +20 -6
- package/package.json +8 -17
- package/scripts/onto-review-watch.sh +486 -0
- package/scripts/onto-runtime-watch.sh +122 -0
- package/scripts/postinstall-hint.js +22 -0
- package/.onto/processes/reconstruct/top-level-concept-discovery-contract.md +0 -387
- package/dist/core-runtime/cli/bootstrap-review-binding.js +0 -186
- package/dist/core-runtime/cli/codex-nested-dispatch.test.js +0 -390
- package/dist/core-runtime/cli/codex-nested-teamlead-executor.test.js +0 -335
- package/dist/core-runtime/cli/coordinator-helpers.js +0 -583
- package/dist/core-runtime/cli/coordinator-state-machine-deliberation.test.js +0 -167
- package/dist/core-runtime/cli/coordinator-state-machine.js +0 -794
- package/dist/core-runtime/cli/e2e-codex-multi-agent-fixes.test.js +0 -615
- package/dist/core-runtime/cli/e2e-start-review-session.test.js +0 -312
- package/dist/core-runtime/cli/health.js +0 -44
- package/dist/core-runtime/cli/inline-http-review-unit-executor.test.js +0 -567
- package/dist/core-runtime/cli/materialize-review-execution-preparation.js +0 -104
- package/dist/core-runtime/cli/migrate-session-roots.js +0 -118
- package/dist/core-runtime/cli/repo-layout-migration-replace.smoke.test.js +0 -106
- package/dist/core-runtime/cli/review-invoke-auto-resolution.test.js +0 -268
- package/dist/core-runtime/cli/review-invoke-coordinator-topology.test.js +0 -136
- package/dist/core-runtime/cli/review-invoke-resolver-caching.test.js +0 -201
- package/dist/core-runtime/cli/review-invoke-topology-dispatch.test.js +0 -192
- package/dist/core-runtime/cli/session-root-guard.js +0 -168
- package/dist/core-runtime/cli/spawn-watcher.test.js +0 -457
- package/dist/core-runtime/cli/strip-wrapping-code-fence.test.js +0 -79
- package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.js +0 -412
- package/dist/core-runtime/cli/teamcreate-lens-deliberation-executor.test.js +0 -351
- package/dist/core-runtime/cli/topology-executor-mapping.js +0 -139
- package/dist/core-runtime/cli/topology-executor-mapping.test.js +0 -173
- package/dist/core-runtime/cli/write-review-interpretation.js +0 -81
- package/dist/core-runtime/config/onto-config-cli.js +0 -278
- package/dist/core-runtime/config/onto-config-key-path.js +0 -288
- package/dist/core-runtime/config/onto-config-key-path.test.js +0 -195
- package/dist/core-runtime/config/onto-config-preview.js +0 -108
- package/dist/core-runtime/config/onto-config-preview.test.js +0 -132
- package/dist/core-runtime/discovery/config-chain.js +0 -118
- package/dist/core-runtime/discovery/config-chain.test.js +0 -103
- package/dist/core-runtime/discovery/config-profile.js +0 -199
- package/dist/core-runtime/discovery/config-profile.test.js +0 -233
- package/dist/core-runtime/discovery/host-detection.test.js +0 -186
- package/dist/core-runtime/discovery/installation-paths.test.js +0 -65
- package/dist/core-runtime/discovery/lens-registry.test.js +0 -81
- package/dist/core-runtime/discovery/path-normalization.test.js +0 -22
- package/dist/core-runtime/discovery/plugin-path.js +0 -72
- package/dist/core-runtime/discovery/plugin-path.test.js +0 -95
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.js +0 -344
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile-defense.test.js +0 -915
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile.js +0 -564
- package/dist/core-runtime/evolve/adapters/code-product/compile/compile.test.js +0 -708
- package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.js +0 -165
- package/dist/core-runtime/evolve/adapters/code-product/parsers/brief-parser.test.js +0 -227
- package/dist/core-runtime/evolve/adapters/code-product/validators/validate.js +0 -59
- package/dist/core-runtime/evolve/adapters/code-product/validators/validate.test.js +0 -205
- package/dist/core-runtime/evolve/adapters/methodology/adapter.js +0 -16
- package/dist/core-runtime/evolve/adapters/methodology/adapter.test.js +0 -9
- package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.js +0 -298
- package/dist/core-runtime/evolve/adapters/methodology/perspectives/authority-consistency.test.js +0 -70
- package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.js +0 -46
- package/dist/core-runtime/evolve/adapters/methodology/scope-types/process.test.js +0 -73
- package/dist/core-runtime/evolve/adapters/registry.js +0 -47
- package/dist/core-runtime/evolve/adapters/registry.test.js +0 -67
- package/dist/core-runtime/evolve/cli.js +0 -256
- package/dist/core-runtime/evolve/commands/align.js +0 -194
- package/dist/core-runtime/evolve/commands/align.test.js +0 -82
- package/dist/core-runtime/evolve/commands/apply.js +0 -161
- package/dist/core-runtime/evolve/commands/apply.test.js +0 -138
- package/dist/core-runtime/evolve/commands/close.js +0 -39
- package/dist/core-runtime/evolve/commands/close.test.js +0 -99
- package/dist/core-runtime/evolve/commands/defer.js +0 -40
- package/dist/core-runtime/evolve/commands/defer.test.js +0 -134
- package/dist/core-runtime/evolve/commands/draft.js +0 -323
- package/dist/core-runtime/evolve/commands/draft.test.js +0 -178
- package/dist/core-runtime/evolve/commands/e2e-evolve-full-cycle.test.js +0 -208
- package/dist/core-runtime/evolve/commands/error-messages.js +0 -125
- package/dist/core-runtime/evolve/commands/error-messages.test.js +0 -167
- package/dist/core-runtime/evolve/commands/propose-align.js +0 -222
- package/dist/core-runtime/evolve/commands/propose-align.test.js +0 -136
- package/dist/core-runtime/evolve/commands/reconstruct.js +0 -330
- package/dist/core-runtime/evolve/commands/reconstruct.test.js +0 -278
- package/dist/core-runtime/evolve/commands/shared.js +0 -22
- package/dist/core-runtime/evolve/commands/stale-check.js +0 -103
- package/dist/core-runtime/evolve/commands/stale-check.test.js +0 -84
- package/dist/core-runtime/evolve/commands/start.js +0 -887
- package/dist/core-runtime/evolve/commands/start.test.js +0 -396
- package/dist/core-runtime/evolve/config/project-config.js +0 -99
- package/dist/core-runtime/evolve/config/project-config.test.js +0 -170
- package/dist/core-runtime/evolve/renderers/align-packet.js +0 -280
- package/dist/core-runtime/evolve/renderers/align-packet.test.js +0 -332
- package/dist/core-runtime/evolve/renderers/draft-packet.js +0 -303
- package/dist/core-runtime/evolve/renderers/draft-packet.test.js +0 -377
- package/dist/core-runtime/evolve/renderers/format.js +0 -5
- package/dist/core-runtime/evolve/renderers/scope-md.js +0 -237
- package/dist/core-runtime/evolve/renderers/scope-md.test.js +0 -306
- package/dist/core-runtime/govern/cli.js +0 -369
- package/dist/core-runtime/govern/cli.test.js +0 -314
- package/dist/core-runtime/govern/drift-engine.js +0 -103
- package/dist/core-runtime/govern/drift-engine.test.js +0 -319
- package/dist/core-runtime/govern/promote-principle.js +0 -206
- package/dist/core-runtime/govern/promote-principle.test.js +0 -368
- package/dist/core-runtime/govern/queue.js +0 -81
- package/dist/core-runtime/govern/types.js +0 -16
- package/dist/core-runtime/install/cli.js +0 -530
- package/dist/core-runtime/install/detect.js +0 -128
- package/dist/core-runtime/install/detect.test.js +0 -155
- package/dist/core-runtime/install/gitignore-update.js +0 -74
- package/dist/core-runtime/install/gitignore-update.test.js +0 -64
- package/dist/core-runtime/install/install-integration.test.js +0 -373
- package/dist/core-runtime/install/prompts.js +0 -389
- package/dist/core-runtime/install/prompts.test.js +0 -293
- package/dist/core-runtime/install/types.js +0 -26
- package/dist/core-runtime/install/validation.js +0 -295
- package/dist/core-runtime/install/validation.test.js +0 -313
- package/dist/core-runtime/install/writer.js +0 -254
- package/dist/core-runtime/install/writer.test.js +0 -218
- package/dist/core-runtime/learning/extractor.js +0 -461
- package/dist/core-runtime/learning/feedback.js +0 -179
- package/dist/core-runtime/learning/health-report.js +0 -165
- package/dist/core-runtime/learning/health-report.test.js +0 -169
- package/dist/core-runtime/learning/loader.js +0 -388
- package/dist/core-runtime/learning/loader.test.js +0 -102
- package/dist/core-runtime/learning/promote/apply-state.js +0 -240
- package/dist/core-runtime/learning/promote/audit-obligation.js +0 -195
- package/dist/core-runtime/learning/promote/collector.js +0 -432
- package/dist/core-runtime/learning/promote/degraded-state.js +0 -125
- package/dist/core-runtime/learning/promote/domain-doc-proposer.js +0 -166
- package/dist/core-runtime/learning/promote/e2e-promote.test.js +0 -6385
- package/dist/core-runtime/learning/promote/health-snapshot.js +0 -150
- package/dist/core-runtime/learning/promote/insight-reclassifier.js +0 -544
- package/dist/core-runtime/learning/promote/judgment-auditor.js +0 -517
- package/dist/core-runtime/learning/promote/panel-reviewer.js +0 -1158
- package/dist/core-runtime/learning/promote/promote-executor.js +0 -1675
- package/dist/core-runtime/learning/promote/promoter.js +0 -307
- package/dist/core-runtime/learning/promote/retirement.js +0 -122
- package/dist/core-runtime/learning/promote/types.js +0 -23
- package/dist/core-runtime/learning/prompt-sections.js +0 -51
- package/dist/core-runtime/learning/shared/artifact-registry-init.js +0 -45
- package/dist/core-runtime/learning/shared/artifact-registry.js +0 -254
- package/dist/core-runtime/learning/shared/audit-obligation-kernel.js +0 -73
- package/dist/core-runtime/learning/shared/audit-state.js +0 -99
- package/dist/core-runtime/learning/shared/duplicate-check.js +0 -28
- package/dist/core-runtime/learning/shared/llm-caller.js +0 -831
- package/dist/core-runtime/learning/shared/llm-caller.test.js +0 -601
- package/dist/core-runtime/learning/shared/llm-tool-loop.js +0 -393
- package/dist/core-runtime/learning/shared/mode.js +0 -25
- package/dist/core-runtime/learning/shared/paths.js +0 -84
- package/dist/core-runtime/learning/shared/paths.test.js +0 -79
- package/dist/core-runtime/learning/shared/patterns.js +0 -37
- package/dist/core-runtime/learning/shared/recoverability.js +0 -355
- package/dist/core-runtime/learning/shared/recovery-context.js +0 -374
- package/dist/core-runtime/learning/shared/scope.js +0 -1
- package/dist/core-runtime/learning/shared/semantic-classifier.js +0 -94
- package/dist/core-runtime/learning/shared/specs/apply-execution-state-spec.js +0 -42
- package/dist/core-runtime/learning/shared/specs/audit-state-spec.js +0 -37
- package/dist/core-runtime/learning/shared/specs/backup-metadata-spec.js +0 -39
- package/dist/core-runtime/learning/shared/specs/emergency-log-spec.js +0 -41
- package/dist/core-runtime/learning/shared/specs/layout-version-spec.js +0 -38
- package/dist/core-runtime/learning/shared/specs/promote-decisions-spec.js +0 -43
- package/dist/core-runtime/learning/shared/specs/promote-report-spec.js +0 -113
- package/dist/core-runtime/learning/shared/specs/prune-log-spec.js +0 -36
- package/dist/core-runtime/learning/shared/specs/recovery-resolution-spec.js +0 -48
- package/dist/core-runtime/learning/shared/specs/restore-manifest-spec.js +0 -43
- package/dist/core-runtime/learning/shared/specs/spec-helpers.js +0 -64
- package/dist/core-runtime/learning/usage-tracker.js +0 -190
- package/dist/core-runtime/learning/usage-tracker.test.js +0 -176
- package/dist/core-runtime/onboard/detect-review-axes.js +0 -122
- package/dist/core-runtime/onboard/detect-review-axes.test.js +0 -127
- package/dist/core-runtime/onboard/write-review-block.js +0 -188
- package/dist/core-runtime/onboard/write-review-block.test.js +0 -240
- package/dist/core-runtime/readers/brownfield-builder.js +0 -150
- package/dist/core-runtime/readers/brownfield-builder.test.js +0 -136
- package/dist/core-runtime/readers/code-chunk-collector.js +0 -53
- package/dist/core-runtime/readers/code-chunk-collector.test.js +0 -136
- package/dist/core-runtime/readers/file-utils.js +0 -240
- package/dist/core-runtime/readers/file-utils.test.js +0 -146
- package/dist/core-runtime/readers/lexicon-citation-check.js +0 -93
- package/dist/core-runtime/readers/lexicon-citation-check.test.js +0 -77
- package/dist/core-runtime/readers/mcp-figma.js +0 -30
- package/dist/core-runtime/readers/mcp-figma.test.js +0 -82
- package/dist/core-runtime/readers/mcp-generic.js +0 -31
- package/dist/core-runtime/readers/mcp-generic.test.js +0 -76
- package/dist/core-runtime/readers/ontology-index.js +0 -148
- package/dist/core-runtime/readers/ontology-index.test.js +0 -245
- package/dist/core-runtime/readers/ontology-query.js +0 -168
- package/dist/core-runtime/readers/ontology-query.test.js +0 -311
- package/dist/core-runtime/readers/ontology-resolve.js +0 -48
- package/dist/core-runtime/readers/ontology-resolve.test.js +0 -48
- package/dist/core-runtime/readers/patterns/index.js +0 -7
- package/dist/core-runtime/readers/review-log.js +0 -213
- package/dist/core-runtime/readers/review-log.test.js +0 -313
- package/dist/core-runtime/readers/scan-local.js +0 -102
- package/dist/core-runtime/readers/scan-local.test.js +0 -102
- package/dist/core-runtime/readers/scan-tarball.js +0 -121
- package/dist/core-runtime/readers/scan-tarball.test.js +0 -283
- package/dist/core-runtime/readers/scan-vault.js +0 -34
- package/dist/core-runtime/readers/scan-vault.test.js +0 -81
- package/dist/core-runtime/readers/types.js +0 -42
- package/dist/core-runtime/readers/types.test.js +0 -94
- package/dist/core-runtime/readers/viewpoint-collectors.js +0 -229
- package/dist/core-runtime/reconstruct/seed-candidate-validation.js +0 -385
- package/dist/core-runtime/review/citation-audit.test.js +0 -165
- package/dist/core-runtime/review/execution-plan-resolver.js +0 -247
- package/dist/core-runtime/review/execution-plan-resolver.test.js +0 -243
- package/dist/core-runtime/review/execution-topology-resolver-axis-first.test.js +0 -246
- package/dist/core-runtime/review/execution-topology-resolver.js +0 -401
- package/dist/core-runtime/review/execution-topology-resolver.test.js +0 -315
- package/dist/core-runtime/review/inline-context-embedder.test.js +0 -154
- package/dist/core-runtime/review/legacy-mode-policy.js +0 -88
- package/dist/core-runtime/review/materializers-effort-persist.test.js +0 -79
- package/dist/core-runtime/review/ontology-path-classifier.js +0 -179
- package/dist/core-runtime/review/ontology-path-classifier.test.js +0 -216
- package/dist/core-runtime/review/packet-boundary-policy.test.js +0 -107
- package/dist/core-runtime/review/participating-lens-paths.test.js +0 -73
- package/dist/core-runtime/review/review-config-legacy-translate.js +0 -244
- package/dist/core-runtime/review/review-config-legacy-translate.test.js +0 -161
- package/dist/core-runtime/review/review-config-validator.js +0 -289
- package/dist/core-runtime/review/review-config-validator.test.js +0 -236
- package/dist/core-runtime/review/shape-pipeline-audit.test.js +0 -311
- package/dist/core-runtime/review/shape-to-topology-id.js +0 -117
- package/dist/core-runtime/review/shape-to-topology-id.test.js +0 -132
- package/dist/core-runtime/review/topology-shape-derivation.js +0 -155
- package/dist/core-runtime/review/topology-shape-derivation.test.js +0 -195
- package/dist/core-runtime/scope-runtime/constants.js +0 -12
- package/dist/core-runtime/scope-runtime/constraint-pool.js +0 -166
- package/dist/core-runtime/scope-runtime/constraint-pool.test.js +0 -674
- package/dist/core-runtime/scope-runtime/domain-validation-log.js +0 -135
- package/dist/core-runtime/scope-runtime/domain-validation-log.test.js +0 -156
- package/dist/core-runtime/scope-runtime/eval-persistence.js +0 -65
- package/dist/core-runtime/scope-runtime/eval-persistence.test.js +0 -84
- package/dist/core-runtime/scope-runtime/event-pipeline.js +0 -64
- package/dist/core-runtime/scope-runtime/event-pipeline.test.js +0 -450
- package/dist/core-runtime/scope-runtime/event-store.js +0 -39
- package/dist/core-runtime/scope-runtime/event-store.test.js +0 -95
- package/dist/core-runtime/scope-runtime/gate-guard.js +0 -348
- package/dist/core-runtime/scope-runtime/gate-guard.test.js +0 -1047
- package/dist/core-runtime/scope-runtime/hash.js +0 -4
- package/dist/core-runtime/scope-runtime/hash.test.js +0 -33
- package/dist/core-runtime/scope-runtime/id.js +0 -4
- package/dist/core-runtime/scope-runtime/id.test.js +0 -17
- package/dist/core-runtime/scope-runtime/reducer.js +0 -297
- package/dist/core-runtime/scope-runtime/reducer.test.js +0 -759
- package/dist/core-runtime/scope-runtime/scope-manager.js +0 -161
- package/dist/core-runtime/scope-runtime/state-machine.js +0 -309
- package/dist/core-runtime/scope-runtime/state-machine.test.js +0 -704
- package/dist/core-runtime/scope-runtime/types.js +0 -116
- package/dist/core-runtime/scope-runtime/types.test.js +0 -69
- package/dist/core-runtime/translate/render-for-user.js +0 -169
- package/dist/core-runtime/translate/render-for-user.test.js +0 -122
- package/dist/providers/capability-contract.js +0 -1
|
@@ -1,583 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Runtime helpers for the Nested Spawn Coordinator.
|
|
4
|
-
*
|
|
5
|
-
* These automate the deterministic boilerplate that the coordinator
|
|
6
|
-
* previously performed manually between Agent tool dispatches.
|
|
7
|
-
*
|
|
8
|
-
* Non-deterministic elements (documented):
|
|
9
|
-
* - Failure messages: generic "output file missing or empty" (Agent tool
|
|
10
|
-
* does not provide structured error info)
|
|
11
|
-
* - Timing: approximate timestamps recorded at process invocation time
|
|
12
|
-
*/
|
|
13
|
-
import fs from "node:fs/promises";
|
|
14
|
-
import path from "node:path";
|
|
15
|
-
import { parseArgs } from "node:util";
|
|
16
|
-
import { pathToFileURL } from "node:url";
|
|
17
|
-
import { appendMarkdownLogEntry, fileExists, isoNow, readYamlDocument, requireString, writeYamlDocument, parseMarkdownFrontmatter, } from "../review/review-artifact-utils.js";
|
|
18
|
-
import { ISSUE_ARTIFACT_IDS, renderIssueArtifactContext, } from "../review/issue-artifact-runtime.js";
|
|
19
|
-
import { resolveRequiredParticipatingLensCount } from "../review/lens-completion-policy.js";
|
|
20
|
-
function toRelativePath(absolutePath, projectRoot) {
|
|
21
|
-
return path.relative(projectRoot, absolutePath);
|
|
22
|
-
}
|
|
23
|
-
function renderBoundaryStateLog(effectiveBoundaryState) {
|
|
24
|
-
const lines = [];
|
|
25
|
-
for (const [dimension, state] of Object.entries(effectiveBoundaryState)) {
|
|
26
|
-
if (state && typeof state === "object" && "requested_policy" in state) {
|
|
27
|
-
const s = state;
|
|
28
|
-
lines.push(`${dimension}: requested=${s.requested_policy}, effective=${s.effective_policy}, guarantee=${s.guarantee_level}`);
|
|
29
|
-
const notes = s.notes;
|
|
30
|
-
if (Array.isArray(notes)) {
|
|
31
|
-
for (const note of notes) {
|
|
32
|
-
lines.push(`note.${dimension}: ${note}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
else if (dimension === "filesystem_scope" && state && typeof state === "object") {
|
|
37
|
-
const fs = state;
|
|
38
|
-
const roots = Array.isArray(fs.effective_allowed_roots)
|
|
39
|
-
? fs.effective_allowed_roots.join(", ")
|
|
40
|
-
: String(fs.effective_allowed_roots ?? "");
|
|
41
|
-
lines.push(`filesystem_scope_effective: ${roots}`);
|
|
42
|
-
lines.push(`filesystem_scope_guarantee: ${fs.guarantee_level}`);
|
|
43
|
-
if (Array.isArray(fs.notes)) {
|
|
44
|
-
for (const note of fs.notes) {
|
|
45
|
-
lines.push(`note.filesystem_scope: ${note}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return lines.join("\n");
|
|
51
|
-
}
|
|
52
|
-
export async function initCoordinatorLog(argv) {
|
|
53
|
-
const { values } = parseArgs({
|
|
54
|
-
options: {
|
|
55
|
-
"session-root": { type: "string" },
|
|
56
|
-
},
|
|
57
|
-
strict: true,
|
|
58
|
-
allowPositionals: false,
|
|
59
|
-
args: argv,
|
|
60
|
-
});
|
|
61
|
-
const sessionRoot = path.resolve(requireString(values["session-root"], "session-root"));
|
|
62
|
-
const executionPlanPath = path.join(sessionRoot, "execution-plan.yaml");
|
|
63
|
-
const executionPlan = await readYamlDocument(executionPlanPath);
|
|
64
|
-
const errorLogPath = executionPlan.error_log_path ?? path.join(sessionRoot, "error-log.md");
|
|
65
|
-
const maxConcurrentLenses = executionPlan.max_concurrent_lenses ??
|
|
66
|
-
executionPlan.lens_prompt_packet_seats.length;
|
|
67
|
-
await appendMarkdownLogEntry(errorLogPath, "runner boundary state", renderBoundaryStateLog(executionPlan.effective_boundary_state));
|
|
68
|
-
await appendMarkdownLogEntry(errorLogPath, "runner parallel dispatch policy", `max_concurrent_lenses: ${maxConcurrentLenses}`);
|
|
69
|
-
return {
|
|
70
|
-
error_log_path: errorLogPath,
|
|
71
|
-
max_concurrent_lenses: maxConcurrentLenses,
|
|
72
|
-
lens_count: executionPlan.lens_prompt_packet_seats.length,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
export async function runInitCoordinatorLog(argv) {
|
|
76
|
-
const result = await initCoordinatorLog(argv);
|
|
77
|
-
console.log(JSON.stringify(result, null, 2));
|
|
78
|
-
return 0;
|
|
79
|
-
}
|
|
80
|
-
export async function buildSynthesizeRuntimePacket(argv) {
|
|
81
|
-
const { values } = parseArgs({
|
|
82
|
-
options: {
|
|
83
|
-
"session-root": { type: "string" },
|
|
84
|
-
"project-root": { type: "string", default: "." },
|
|
85
|
-
"require-deliberation": { type: "boolean", default: false },
|
|
86
|
-
"validate-lenses-only": { type: "boolean", default: false },
|
|
87
|
-
},
|
|
88
|
-
strict: true,
|
|
89
|
-
allowPositionals: false,
|
|
90
|
-
args: argv,
|
|
91
|
-
});
|
|
92
|
-
const sessionRoot = path.resolve(requireString(values["session-root"], "session-root"));
|
|
93
|
-
const projectRoot = path.resolve(requireString(values["project-root"], "project-root"));
|
|
94
|
-
const requireDeliberation = Boolean(values["require-deliberation"]);
|
|
95
|
-
const validateLensesOnly = Boolean(values["validate-lenses-only"]);
|
|
96
|
-
const executionPlanPath = path.join(sessionRoot, "execution-plan.yaml");
|
|
97
|
-
const executionPlan = await readYamlDocument(executionPlanPath);
|
|
98
|
-
const errorLogPath = executionPlan.error_log_path ?? path.join(sessionRoot, "error-log.md");
|
|
99
|
-
// Check lens outputs
|
|
100
|
-
const participating = [];
|
|
101
|
-
const degraded = [];
|
|
102
|
-
for (const seat of executionPlan.lens_prompt_packet_seats) {
|
|
103
|
-
if (await fileExists(seat.output_path)) {
|
|
104
|
-
const text = await fs.readFile(seat.output_path, "utf8");
|
|
105
|
-
if (text.trim().length > 0) {
|
|
106
|
-
participating.push(seat.lens_id);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
degraded.push({
|
|
111
|
-
lens_id: seat.lens_id,
|
|
112
|
-
message: "output file missing or empty",
|
|
113
|
-
});
|
|
114
|
-
await appendMarkdownLogEntry(errorLogPath, `lens failure: ${seat.lens_id}`, `unit_id: ${seat.lens_id}\nunit_kind: lens\npacket_path: ${seat.packet_path}\noutput_path: ${seat.output_path}\nmessage: output file missing or empty`);
|
|
115
|
-
}
|
|
116
|
-
const minimumParticipating = resolveRequiredParticipatingLensCount(executionPlan);
|
|
117
|
-
if (participating.length < minimumParticipating) {
|
|
118
|
-
const haltReason = participating.length === 0
|
|
119
|
-
? "No participating lens outputs were produced."
|
|
120
|
-
: `Fewer than ${minimumParticipating} participating lens outputs remain after degraded execution.`;
|
|
121
|
-
await appendMarkdownLogEntry(errorLogPath, "runner halted before synthesize", haltReason);
|
|
122
|
-
return {
|
|
123
|
-
halt: true,
|
|
124
|
-
halt_reason: haltReason,
|
|
125
|
-
participating_lens_ids: participating,
|
|
126
|
-
degraded_lens_ids: degraded.map((d) => d.lens_id),
|
|
127
|
-
runtime_packet_path: undefined,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
if (validateLensesOnly) {
|
|
131
|
-
return {
|
|
132
|
-
halt: false,
|
|
133
|
-
halt_reason: undefined,
|
|
134
|
-
participating_lens_ids: participating,
|
|
135
|
-
degraded_lens_ids: degraded.map((d) => d.lens_id),
|
|
136
|
-
runtime_packet_path: undefined,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
// Build enriched synthesize packet
|
|
140
|
-
const synthesizePacketText = await fs.readFile(executionPlan.synthesize_prompt_packet_path, "utf8");
|
|
141
|
-
const lensRefsSection = participating
|
|
142
|
-
.map((lensId) => {
|
|
143
|
-
const seat = executionPlan.lens_prompt_packet_seats.find((s) => s.lens_id === lensId);
|
|
144
|
-
return `- ${lensId}: ${toRelativePath(seat?.output_path ?? "", projectRoot)}`;
|
|
145
|
-
})
|
|
146
|
-
.join("\n");
|
|
147
|
-
const degradedSection = degraded.length > 0
|
|
148
|
-
? `\n## Degraded Lens Failures\n${degraded.map((d) => `- ${d.lens_id}: ${d.message}`).join("\n")}\n`
|
|
149
|
-
: "";
|
|
150
|
-
if (requireDeliberation && !(await fileExists(executionPlan.deliberation_output_path))) {
|
|
151
|
-
throw new Error(`Missing controlled deliberation result before synthesize: ${executionPlan.deliberation_output_path}`);
|
|
152
|
-
}
|
|
153
|
-
const deliberationSection = (await fileExists(executionPlan.deliberation_output_path))
|
|
154
|
-
? [
|
|
155
|
-
"",
|
|
156
|
-
"## Controlled Lens Deliberation Result",
|
|
157
|
-
`- teamlead result: ${toRelativePath(executionPlan.deliberation_output_path, projectRoot)}`,
|
|
158
|
-
"",
|
|
159
|
-
"## Lens Deliberation Responses",
|
|
160
|
-
...participating.map((lensId) => {
|
|
161
|
-
const seat = executionPlan.lens_deliberation_prompt_packet_seats.find((candidate) => candidate.lens_id === lensId);
|
|
162
|
-
if (!seat) {
|
|
163
|
-
throw new Error(`Missing deliberation prompt seat for lens: ${lensId}`);
|
|
164
|
-
}
|
|
165
|
-
return `- ${lensId}: ${toRelativePath(seat.output_path, projectRoot)}`;
|
|
166
|
-
}),
|
|
167
|
-
"",
|
|
168
|
-
].join("\n")
|
|
169
|
-
: "";
|
|
170
|
-
const issueArtifactSection = [
|
|
171
|
-
"",
|
|
172
|
-
"## Issue-Stance Closure Artifact Context",
|
|
173
|
-
await renderIssueArtifactContext({
|
|
174
|
-
projectRoot,
|
|
175
|
-
executionPlan,
|
|
176
|
-
artifactIds: ISSUE_ARTIFACT_IDS,
|
|
177
|
-
}),
|
|
178
|
-
"",
|
|
179
|
-
].join("\n");
|
|
180
|
-
const runtimePacketPath = path.join(executionPlan.prompt_packets_root ?? path.join(sessionRoot, "prompt-packets"), "synthesize.runtime.prompt.md");
|
|
181
|
-
const enrichedText = `${synthesizePacketText.trimEnd()}\n\n## Runtime Participating Lens Outputs\n${lensRefsSection}\n${deliberationSection}\n${issueArtifactSection}${degradedSection}`;
|
|
182
|
-
await fs.writeFile(runtimePacketPath, enrichedText.trimEnd() + "\n", "utf8");
|
|
183
|
-
return {
|
|
184
|
-
halt: false,
|
|
185
|
-
halt_reason: undefined,
|
|
186
|
-
participating_lens_ids: participating,
|
|
187
|
-
degraded_lens_ids: degraded.map((d) => d.lens_id),
|
|
188
|
-
runtime_packet_path: runtimePacketPath,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
export async function runBuildSynthesizeRuntimePacket(argv) {
|
|
192
|
-
const result = await buildSynthesizeRuntimePacket(argv);
|
|
193
|
-
console.log(JSON.stringify(result, null, 2));
|
|
194
|
-
return 0;
|
|
195
|
-
}
|
|
196
|
-
// ─────────────────────────────────────────────
|
|
197
|
-
// Subcommand: write-execution-result
|
|
198
|
-
// ─────────────────────────────────────────────
|
|
199
|
-
//
|
|
200
|
-
// Per-unit timestamp provenance (coordinator path):
|
|
201
|
-
// - started_at: derived from coordinator-state.yaml transition timestamps
|
|
202
|
-
// (awaiting_lens_dispatch / awaiting_synthesize_dispatch). Represents
|
|
203
|
-
// dispatch instruction time, which precedes actual agent execution start.
|
|
204
|
-
// Over-estimation bound: dispatch latency + agent boot + LLM execution +
|
|
205
|
-
// file-write. Typically tens of seconds to a few minutes for LLM agents;
|
|
206
|
-
// unsuitable for ms-scale SLA comparisons.
|
|
207
|
-
// - completed_at: derived from fs.stat(output_path).mtime for participating
|
|
208
|
-
// units. Filesystem mtime precision is platform-dependent (e.g. HFS+ 1s).
|
|
209
|
-
// Post-write assumption: round1/*.md and synthesis.md must not be re-touched
|
|
210
|
-
// by any writer after the dispatched agent completes (deliberation writes
|
|
211
|
-
// to deliberation.md, render writes to final-output.md — no overlap).
|
|
212
|
-
// - Non-participating / failed / skipped cases fall back to the batch
|
|
213
|
-
// `completedAt` for completed_at: those timestamps are NOT per-unit
|
|
214
|
-
// measurements and `duration_ms` for such units is batch wall-clock
|
|
215
|
-
// time, not per-unit execution time.
|
|
216
|
-
// - TS runner path (run-review-prompt-execution.ts) uses process wall-clock
|
|
217
|
-
// measurements; both paths write to the same ReviewUnitExecutionResult
|
|
218
|
-
// interface but carry different semantic provenance. Consumers comparing
|
|
219
|
-
// `duration_ms` across realizations must account for this (see
|
|
220
|
-
// `execution_realization` field). A discriminator field at schema level is
|
|
221
|
-
// tracked as a follow-up (K2 of PR #25 re-review; session
|
|
222
|
-
// .onto/review/20260413-7880b48f).
|
|
223
|
-
function deriveExecutionStatus(synthesisExecuted, degradedLensCount) {
|
|
224
|
-
if (!synthesisExecuted)
|
|
225
|
-
return "halted_partial";
|
|
226
|
-
if (degradedLensCount > 0)
|
|
227
|
-
return "completed_with_degradation";
|
|
228
|
-
return "completed";
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Read coordinator state file. Fails soft by returning a null `state`,
|
|
232
|
-
* but preserves the reason (missing vs unreadable) for observability.
|
|
233
|
-
*/
|
|
234
|
-
async function readCoordinatorStateFile(sessionRoot) {
|
|
235
|
-
const stateFilePath = path.join(sessionRoot, "coordinator-state.yaml");
|
|
236
|
-
if (!(await fileExists(stateFilePath))) {
|
|
237
|
-
return { kind: "missing", state: null };
|
|
238
|
-
}
|
|
239
|
-
try {
|
|
240
|
-
const state = await readYamlDocument(stateFilePath);
|
|
241
|
-
return { kind: "present", state };
|
|
242
|
-
}
|
|
243
|
-
catch {
|
|
244
|
-
return { kind: "unreadable", state: null };
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Find the timestamp of the first transition with matching `to` state.
|
|
249
|
-
*
|
|
250
|
-
* Invariant (current state machine): each target state appears at most once in
|
|
251
|
-
* `transitions` per session, so "first match" is unambiguous. If future
|
|
252
|
-
* retry/resume flows allow re-entering the same state, the semantics of
|
|
253
|
-
* `started_at` would straddle cycles — switch to `findLast`-style lookup then.
|
|
254
|
-
*
|
|
255
|
-
* Fails soft by returning `null` when `stateFile` is absent or the
|
|
256
|
-
* `transitions` array is missing/malformed (runtime YAML shape is not
|
|
257
|
-
* compile-time guaranteed).
|
|
258
|
-
*/
|
|
259
|
-
function findTransitionAt(stateFile, toState) {
|
|
260
|
-
if (!stateFile)
|
|
261
|
-
return null;
|
|
262
|
-
if (!Array.isArray(stateFile.transitions))
|
|
263
|
-
return null;
|
|
264
|
-
const transition = stateFile.transitions.find((t) => t.to === toState);
|
|
265
|
-
return transition?.at ?? null;
|
|
266
|
-
}
|
|
267
|
-
/** Read file mtime as ISO string. Returns null on failure. */
|
|
268
|
-
async function readFileMtimeIsoOrNull(filePath) {
|
|
269
|
-
try {
|
|
270
|
-
const stat = await fs.stat(filePath);
|
|
271
|
-
return stat.mtime.toISOString();
|
|
272
|
-
}
|
|
273
|
-
catch {
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Compute duration in ms, clamping negative deltas to 0.
|
|
279
|
-
*
|
|
280
|
-
* A negative delta indicates clock inversion (wall vs filesystem mtime, or
|
|
281
|
-
* state-transition timestamp ordering mismatch) and is typically a sign of
|
|
282
|
-
* clock skew or misconfigured NTP, not normal execution. We warn when
|
|
283
|
-
* `unitId` is provided so that clamping is not silent.
|
|
284
|
-
*/
|
|
285
|
-
function computeDurationMs(startedAt, completedAt, unitId) {
|
|
286
|
-
const delta = new Date(completedAt).getTime() - new Date(startedAt).getTime();
|
|
287
|
-
if (delta < 0 && unitId) {
|
|
288
|
-
console.warn(`[coordinator-helpers] negative duration clamped for ${unitId}: ` +
|
|
289
|
-
`started_at=${startedAt}, completed_at=${completedAt} (clock skew?)`);
|
|
290
|
-
}
|
|
291
|
-
return Math.max(0, delta);
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Warn on stderr AND persist to error-log.md with a structured prefix.
|
|
295
|
-
* The `kind` discriminator lets post-session aggregators group degradation
|
|
296
|
-
* events without parsing the free-form message body.
|
|
297
|
-
*/
|
|
298
|
-
async function warnAndLogDegradation(errorLogPath, kind, title, message) {
|
|
299
|
-
console.warn(`[coordinator-helpers] ${message}`);
|
|
300
|
-
await appendMarkdownLogEntry(errorLogPath, title, `degradation_kind: ${kind}\n${message}`);
|
|
301
|
-
}
|
|
302
|
-
export async function writeExecutionResult(argv) {
|
|
303
|
-
const { values } = parseArgs({
|
|
304
|
-
options: {
|
|
305
|
-
"session-root": { type: "string" },
|
|
306
|
-
"started-at": { type: "string" },
|
|
307
|
-
"synthesis-executed": { type: "string", default: "true" },
|
|
308
|
-
"halt-reason": { type: "string" },
|
|
309
|
-
},
|
|
310
|
-
strict: true,
|
|
311
|
-
allowPositionals: false,
|
|
312
|
-
args: argv,
|
|
313
|
-
});
|
|
314
|
-
const sessionRoot = path.resolve(requireString(values["session-root"], "session-root"));
|
|
315
|
-
const executionPlanPath = path.join(sessionRoot, "execution-plan.yaml");
|
|
316
|
-
const executionPlan = await readYamlDocument(executionPlanPath);
|
|
317
|
-
const executionStartedAt = typeof values["started-at"] === "string"
|
|
318
|
-
? values["started-at"]
|
|
319
|
-
: isoNow();
|
|
320
|
-
const synthesisExecuted = values["synthesis-executed"] !== "false";
|
|
321
|
-
const haltReason = typeof values["halt-reason"] === "string" && values["halt-reason"].length > 0
|
|
322
|
-
? values["halt-reason"]
|
|
323
|
-
: null;
|
|
324
|
-
// Check lens outputs
|
|
325
|
-
const planned = executionPlan.lens_prompt_packet_seats.map((s) => s.lens_id);
|
|
326
|
-
const participating = [];
|
|
327
|
-
const degraded = [];
|
|
328
|
-
for (const seat of executionPlan.lens_prompt_packet_seats) {
|
|
329
|
-
if (await fileExists(seat.output_path)) {
|
|
330
|
-
const text = await fs.readFile(seat.output_path, "utf8");
|
|
331
|
-
if (text.trim().length > 0) {
|
|
332
|
-
participating.push(seat.lens_id);
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
degraded.push(seat.lens_id);
|
|
337
|
-
}
|
|
338
|
-
const excluded = planned.filter((id) => !participating.includes(id) && !degraded.includes(id));
|
|
339
|
-
// Controlled lens deliberation is the source of truth for deliberation status.
|
|
340
|
-
let deliberationStatus = null;
|
|
341
|
-
const synthesisPath = executionPlan.synthesis_output_path;
|
|
342
|
-
if (synthesisExecuted && await fileExists(synthesisPath)) {
|
|
343
|
-
const synthesisText = await fs.readFile(synthesisPath, "utf8");
|
|
344
|
-
const parsed = parseMarkdownFrontmatter(synthesisText);
|
|
345
|
-
deliberationStatus = parsed.metadata?.deliberation_status ?? null;
|
|
346
|
-
}
|
|
347
|
-
const deliberationPath = executionPlan.deliberation_output_path;
|
|
348
|
-
if (synthesisExecuted) {
|
|
349
|
-
if (!(await fileExists(deliberationPath))) {
|
|
350
|
-
throw new Error(`Missing controlled deliberation result: ${deliberationPath}`);
|
|
351
|
-
}
|
|
352
|
-
const deliberationText = await fs.readFile(deliberationPath, "utf8");
|
|
353
|
-
const parsed = parseMarkdownFrontmatter(deliberationText);
|
|
354
|
-
if (parsed.metadata?.deliberation_status !== "performed") {
|
|
355
|
-
throw new Error(`Controlled deliberation result must declare deliberation_status: performed in ${deliberationPath}`);
|
|
356
|
-
}
|
|
357
|
-
if (deliberationStatus !== "performed") {
|
|
358
|
-
throw new Error(`Synthesis result must declare deliberation_status: performed in ${synthesisPath}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const completedAt = isoNow();
|
|
362
|
-
// Per-unit timestamp precision: read coordinator state transitions + file mtime.
|
|
363
|
-
// On any failure, fall back to batch timestamps (executionStartedAt / completedAt)
|
|
364
|
-
// while emitting a warning so the degradation is not silent. Warnings are also
|
|
365
|
-
// persisted to error-log.md so that post-session inspection can reconstruct
|
|
366
|
-
// whether per-unit timing was degraded for this session.
|
|
367
|
-
const errorLogPath = executionPlan.error_log_path ?? path.join(sessionRoot, "error-log.md");
|
|
368
|
-
const readOutcome = await readCoordinatorStateFile(sessionRoot);
|
|
369
|
-
const stateFile = readOutcome.state;
|
|
370
|
-
if (readOutcome.kind === "missing") {
|
|
371
|
-
await warnAndLogDegradation(errorLogPath, "state_file_missing", "per-unit timestamp degraded", "coordinator-state.yaml not found; falling back to batch timestamps for per-unit started_at.");
|
|
372
|
-
}
|
|
373
|
-
else if (readOutcome.kind === "unreadable") {
|
|
374
|
-
await warnAndLogDegradation(errorLogPath, "state_file_unreadable", "per-unit timestamp degraded", "coordinator-state.yaml present but unreadable (YAML parse failed); falling back to batch timestamps for per-unit started_at.");
|
|
375
|
-
}
|
|
376
|
-
const lensDispatchAt = findTransitionAt(stateFile, "awaiting_lens_dispatch");
|
|
377
|
-
if (stateFile && !lensDispatchAt) {
|
|
378
|
-
await warnAndLogDegradation(errorLogPath, "transition_missing_lens", "per-unit timestamp degraded (lens)", "coordinator-state.yaml has no 'awaiting_lens_dispatch' transition; falling back to batch timestamp for lens started_at.");
|
|
379
|
-
}
|
|
380
|
-
const lensStartedAt = lensDispatchAt ?? executionStartedAt;
|
|
381
|
-
const lensResults = await Promise.all(executionPlan.lens_prompt_packet_seats.map(async (seat) => {
|
|
382
|
-
const isParticipating = participating.includes(seat.lens_id);
|
|
383
|
-
const mtimeIso = isParticipating
|
|
384
|
-
? await readFileMtimeIsoOrNull(seat.output_path)
|
|
385
|
-
: null;
|
|
386
|
-
if (isParticipating && mtimeIso === null) {
|
|
387
|
-
await warnAndLogDegradation(errorLogPath, "mtime_read_failed", `per-unit timestamp degraded (lens:${seat.lens_id})`, `fs.stat failed for ${seat.output_path}; falling back to batch completedAt.`);
|
|
388
|
-
}
|
|
389
|
-
const unitCompletedAt = mtimeIso ?? completedAt;
|
|
390
|
-
// Provenance: both started_at and completed_at must come from per-unit
|
|
391
|
-
// sources (state transition + mtime) for the unit to count as
|
|
392
|
-
// `coordinator_derived`. Otherwise, the unit gets the session-level
|
|
393
|
-
// batch window marker.
|
|
394
|
-
const hasPerUnitStart = Boolean(lensDispatchAt);
|
|
395
|
-
const hasPerUnitEnd = isParticipating && mtimeIso !== null;
|
|
396
|
-
const provenance = hasPerUnitStart && hasPerUnitEnd
|
|
397
|
-
? "coordinator_derived"
|
|
398
|
-
: "batch_window";
|
|
399
|
-
return {
|
|
400
|
-
unit_id: seat.lens_id,
|
|
401
|
-
unit_kind: "lens",
|
|
402
|
-
packet_path: seat.packet_path,
|
|
403
|
-
output_path: seat.output_path,
|
|
404
|
-
status: isParticipating ? "completed" : "failed",
|
|
405
|
-
started_at: lensStartedAt,
|
|
406
|
-
completed_at: unitCompletedAt,
|
|
407
|
-
duration_ms: computeDurationMs(lensStartedAt, unitCompletedAt, `lens:${seat.lens_id}`),
|
|
408
|
-
timestamp_provenance: provenance,
|
|
409
|
-
failure_message: degraded.includes(seat.lens_id) ? "output file missing or empty" : null,
|
|
410
|
-
};
|
|
411
|
-
}));
|
|
412
|
-
// Per-PR #25 review NF-2: log any lens that ended up in `excluded` (neither
|
|
413
|
-
// participating nor degraded) so a post-session reader can reconstruct why
|
|
414
|
-
// the planned set did not fully resolve.
|
|
415
|
-
if (excluded.length > 0) {
|
|
416
|
-
await warnAndLogDegradation(errorLogPath, "lens_excluded", "lens excluded from participating/degraded partition", `excluded_lens_ids: ${excluded.join(", ")} (planned but neither participating nor degraded)`);
|
|
417
|
-
}
|
|
418
|
-
const runtimePacketPath = path.join(executionPlan.prompt_packets_root ?? path.join(sessionRoot, "prompt-packets"), "synthesize.runtime.prompt.md");
|
|
419
|
-
const issueArtifactDispatchAt = findTransitionAt(stateFile, "awaiting_adjudication");
|
|
420
|
-
const issueArtifactStartedAt = issueArtifactDispatchAt ?? executionStartedAt;
|
|
421
|
-
const issueArtifactResults = await Promise.all(executionPlan.issue_artifact_prompt_packet_seats.map(async (seat) => {
|
|
422
|
-
const outputExists = await fileExists(seat.output_path);
|
|
423
|
-
const hasContent = outputExists
|
|
424
|
-
? (await fs.readFile(seat.output_path, "utf8")).trim().length > 0
|
|
425
|
-
: false;
|
|
426
|
-
const mtimeIso = hasContent
|
|
427
|
-
? await readFileMtimeIsoOrNull(seat.output_path)
|
|
428
|
-
: null;
|
|
429
|
-
const unitCompletedAt = mtimeIso ?? completedAt;
|
|
430
|
-
const provenance = issueArtifactDispatchAt && mtimeIso ? "coordinator_derived" : "batch_window";
|
|
431
|
-
return {
|
|
432
|
-
unit_id: seat.artifact_id,
|
|
433
|
-
unit_kind: "issue_artifact",
|
|
434
|
-
packet_path: seat.packet_path,
|
|
435
|
-
output_path: seat.output_path,
|
|
436
|
-
status: hasContent ? "completed" : "failed",
|
|
437
|
-
started_at: issueArtifactStartedAt,
|
|
438
|
-
completed_at: unitCompletedAt,
|
|
439
|
-
duration_ms: computeDurationMs(issueArtifactStartedAt, unitCompletedAt, `issue_artifact:${seat.artifact_id}`),
|
|
440
|
-
timestamp_provenance: provenance,
|
|
441
|
-
failure_message: hasContent ? null : "output file missing or empty",
|
|
442
|
-
};
|
|
443
|
-
}));
|
|
444
|
-
const deliberationDispatchAt = findTransitionAt(stateFile, "awaiting_deliberation");
|
|
445
|
-
const deliberationStartedAt = deliberationDispatchAt ?? executionStartedAt;
|
|
446
|
-
const lensDeliberationResults = await Promise.all(executionPlan.lens_deliberation_prompt_packet_seats.map(async (seat) => {
|
|
447
|
-
const outputExists = await fileExists(seat.output_path);
|
|
448
|
-
const mtimeIso = outputExists
|
|
449
|
-
? await readFileMtimeIsoOrNull(seat.output_path)
|
|
450
|
-
: null;
|
|
451
|
-
const unitCompletedAt = mtimeIso ?? completedAt;
|
|
452
|
-
const provenance = deliberationDispatchAt && mtimeIso ? "coordinator_derived" : "batch_window";
|
|
453
|
-
return {
|
|
454
|
-
unit_id: `deliberation-${seat.lens_id}`,
|
|
455
|
-
unit_kind: "deliberation",
|
|
456
|
-
packet_path: seat.packet_path,
|
|
457
|
-
output_path: seat.output_path,
|
|
458
|
-
status: outputExists ? "completed" : "failed",
|
|
459
|
-
started_at: deliberationStartedAt,
|
|
460
|
-
completed_at: unitCompletedAt,
|
|
461
|
-
duration_ms: computeDurationMs(deliberationStartedAt, unitCompletedAt, `deliberation:${seat.lens_id}`),
|
|
462
|
-
timestamp_provenance: provenance,
|
|
463
|
-
failure_message: outputExists ? null : "output file missing or empty",
|
|
464
|
-
};
|
|
465
|
-
}));
|
|
466
|
-
const teamleadDeliberationMtimeIso = synthesisExecuted
|
|
467
|
-
? await readFileMtimeIsoOrNull(deliberationPath)
|
|
468
|
-
: null;
|
|
469
|
-
const teamleadDeliberationResult = synthesisExecuted
|
|
470
|
-
? {
|
|
471
|
-
unit_id: "controlled-deliberation",
|
|
472
|
-
unit_kind: "deliberation",
|
|
473
|
-
packet_path: executionPlan.teamlead_deliberation_prompt_packet_path,
|
|
474
|
-
output_path: deliberationPath,
|
|
475
|
-
status: (await fileExists(deliberationPath)) ? "completed" : "failed",
|
|
476
|
-
started_at: deliberationStartedAt,
|
|
477
|
-
completed_at: teamleadDeliberationMtimeIso ?? completedAt,
|
|
478
|
-
duration_ms: computeDurationMs(deliberationStartedAt, teamleadDeliberationMtimeIso ?? completedAt, "controlled-deliberation"),
|
|
479
|
-
timestamp_provenance: deliberationDispatchAt && teamleadDeliberationMtimeIso
|
|
480
|
-
? "coordinator_derived"
|
|
481
|
-
: "batch_window",
|
|
482
|
-
failure_message: null,
|
|
483
|
-
}
|
|
484
|
-
: null;
|
|
485
|
-
const synthesizeDispatchAt = findTransitionAt(stateFile, "awaiting_synthesize_dispatch");
|
|
486
|
-
if (synthesisExecuted && stateFile && !synthesizeDispatchAt) {
|
|
487
|
-
await warnAndLogDegradation(errorLogPath, "transition_missing_synthesize", "per-unit timestamp degraded (synthesize)", "coordinator-state.yaml has no 'awaiting_synthesize_dispatch' transition; falling back to batch timestamp for synthesize started_at.");
|
|
488
|
-
}
|
|
489
|
-
const synthesizeStartedAt = synthesizeDispatchAt ?? executionStartedAt;
|
|
490
|
-
const synthesizeMtimeIso = synthesisExecuted
|
|
491
|
-
? await readFileMtimeIsoOrNull(synthesisPath)
|
|
492
|
-
: null;
|
|
493
|
-
if (synthesisExecuted && synthesizeMtimeIso === null) {
|
|
494
|
-
await warnAndLogDegradation(errorLogPath, "mtime_read_failed", "per-unit timestamp degraded (synthesize)", `fs.stat failed for ${synthesisPath}; falling back to batch completedAt.`);
|
|
495
|
-
}
|
|
496
|
-
const synthesizeCompletedAt = synthesizeMtimeIso ?? completedAt;
|
|
497
|
-
const synthesizeProvenance = synthesizeDispatchAt && synthesizeMtimeIso
|
|
498
|
-
? "coordinator_derived"
|
|
499
|
-
: "batch_window";
|
|
500
|
-
const synthesizeResult = synthesisExecuted
|
|
501
|
-
? {
|
|
502
|
-
unit_id: "synthesize",
|
|
503
|
-
unit_kind: "synthesize",
|
|
504
|
-
packet_path: runtimePacketPath,
|
|
505
|
-
output_path: synthesisPath,
|
|
506
|
-
status: (await fileExists(synthesisPath)) ? "completed" : "failed",
|
|
507
|
-
started_at: synthesizeStartedAt,
|
|
508
|
-
completed_at: synthesizeCompletedAt,
|
|
509
|
-
duration_ms: computeDurationMs(synthesizeStartedAt, synthesizeCompletedAt, "synthesize"),
|
|
510
|
-
timestamp_provenance: synthesizeProvenance,
|
|
511
|
-
failure_message: null,
|
|
512
|
-
}
|
|
513
|
-
: null;
|
|
514
|
-
const artifact = {
|
|
515
|
-
session_id: executionPlan.session_id,
|
|
516
|
-
session_root: sessionRoot,
|
|
517
|
-
execution_realization: executionPlan.execution_realization,
|
|
518
|
-
host_runtime: executionPlan.host_runtime,
|
|
519
|
-
review_mode: executionPlan.review_mode,
|
|
520
|
-
execution_status: deriveExecutionStatus(synthesisExecuted, degraded.length),
|
|
521
|
-
execution_started_at: executionStartedAt,
|
|
522
|
-
execution_completed_at: completedAt,
|
|
523
|
-
total_duration_ms: computeDurationMs(executionStartedAt, completedAt),
|
|
524
|
-
max_concurrent_lenses: planned.length,
|
|
525
|
-
planned_lens_ids: planned,
|
|
526
|
-
participating_lens_ids: participating,
|
|
527
|
-
degraded_lens_ids: degraded,
|
|
528
|
-
excluded_lens_ids: excluded,
|
|
529
|
-
executed_lens_count: participating.length,
|
|
530
|
-
synthesis_executed: synthesisExecuted,
|
|
531
|
-
deliberation_status: deliberationStatus,
|
|
532
|
-
halt_reason: haltReason,
|
|
533
|
-
error_log_path: errorLogPath,
|
|
534
|
-
lens_execution_results: lensResults,
|
|
535
|
-
issue_artifact_execution_results: issueArtifactResults,
|
|
536
|
-
deliberation_execution_results: [
|
|
537
|
-
...lensDeliberationResults,
|
|
538
|
-
...(teamleadDeliberationResult ? [teamleadDeliberationResult] : []),
|
|
539
|
-
],
|
|
540
|
-
synthesize_execution_result: synthesizeResult,
|
|
541
|
-
};
|
|
542
|
-
const resultPath = executionPlan.execution_result_path ?? path.join(sessionRoot, "execution-result.yaml");
|
|
543
|
-
await writeYamlDocument(resultPath, artifact);
|
|
544
|
-
return {
|
|
545
|
-
execution_result_path: resultPath,
|
|
546
|
-
execution_status: artifact.execution_status,
|
|
547
|
-
participating_lens_count: participating.length,
|
|
548
|
-
degraded_lens_count: degraded.length,
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
export async function runWriteExecutionResult(argv) {
|
|
552
|
-
const result = await writeExecutionResult(argv);
|
|
553
|
-
console.log(JSON.stringify(result, null, 2));
|
|
554
|
-
return 0;
|
|
555
|
-
}
|
|
556
|
-
// ─────────────────────────────────────────────
|
|
557
|
-
// Runtime dispatch
|
|
558
|
-
// ─────────────────────────────────────────────
|
|
559
|
-
/** SSOT for subcommand names: one map, used both by dispatch and the help text. */
|
|
560
|
-
const SUBCOMMANDS = {
|
|
561
|
-
"init-log": runInitCoordinatorLog,
|
|
562
|
-
"build-synthesize-packet": runBuildSynthesizeRuntimePacket,
|
|
563
|
-
"write-execution-result": runWriteExecutionResult,
|
|
564
|
-
};
|
|
565
|
-
async function main() {
|
|
566
|
-
const subcommand = process.argv[2];
|
|
567
|
-
const subArgv = process.argv.slice(3);
|
|
568
|
-
const handler = subcommand && (subcommand in SUBCOMMANDS)
|
|
569
|
-
? SUBCOMMANDS[subcommand]
|
|
570
|
-
: null;
|
|
571
|
-
if (!handler) {
|
|
572
|
-
console.error(`Unknown coordinator-helper subcommand: ${subcommand}`);
|
|
573
|
-
console.error(`Available: ${Object.keys(SUBCOMMANDS).join(", ")}`);
|
|
574
|
-
return 1;
|
|
575
|
-
}
|
|
576
|
-
return handler(subArgv);
|
|
577
|
-
}
|
|
578
|
-
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
579
|
-
main().then((exitCode) => process.exit(exitCode), (error) => {
|
|
580
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
581
|
-
process.exit(1);
|
|
582
|
-
});
|
|
583
|
-
}
|