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,374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Recovery context — DD-22 + DD-23.
|
|
3
|
-
*
|
|
4
|
-
* Design authority:
|
|
5
|
-
* - learn-phase3-design-v9.md DD-22 (canonical attempt selection, source_kind enum)
|
|
6
|
-
* - learn-phase3-design-v9.md DD-23 (RecoveryResolution canonical seat)
|
|
7
|
-
* - learn-phase3-design-v8.md DD-22 (attempt_id lifecycle, conflict policy)
|
|
8
|
-
* - learn-phase3-design-v7.md DD-22 (single consumer + freshness)
|
|
9
|
-
*
|
|
10
|
-
* Responsibility:
|
|
11
|
-
* - Gather recovery sources (in-band ApplyExecutionState, out-of-band
|
|
12
|
-
* emergency log, checkpoint manifest) for a given session
|
|
13
|
-
* - Resolve which is the canonical truth using attempt_id + generation
|
|
14
|
-
* - Surface manual escalation when multiple attempt_ids conflict and the
|
|
15
|
-
* operator has not yet recorded a RecoveryResolution
|
|
16
|
-
* - Persist operator decisions (DD-23) so subsequent --resume runs respect them
|
|
17
|
-
*/
|
|
18
|
-
import fs from "node:fs";
|
|
19
|
-
import path from "node:path";
|
|
20
|
-
import { REGISTRY } from "./artifact-registry.js";
|
|
21
|
-
import { BACKUP_ROOT } from "./recoverability.js";
|
|
22
|
-
/** v8 axiology default — fail-close for canonical knowledge mutation. */
|
|
23
|
-
export const DEFAULT_RECOVERY_POLICY = {
|
|
24
|
-
cross_attempt_conflict: "manual_escalation",
|
|
25
|
-
};
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// Path helpers
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
export function getSessionPromoteRoot(projectRoot, sessionId) {
|
|
30
|
-
return path.join(projectRoot, ".onto", "sessions", "promote", sessionId);
|
|
31
|
-
}
|
|
32
|
-
export function getApplyStatePath(projectRoot, sessionId) {
|
|
33
|
-
return path.join(getSessionPromoteRoot(projectRoot, sessionId), "promote-execution-result.json");
|
|
34
|
-
}
|
|
35
|
-
export function getRecoveryResolutionPath(projectRoot, sessionId) {
|
|
36
|
-
return path.join(getSessionPromoteRoot(projectRoot, sessionId), "recovery-resolution.yaml");
|
|
37
|
-
}
|
|
38
|
-
export function getCheckpointDir(sessionId) {
|
|
39
|
-
return path.join(BACKUP_ROOT, sessionId);
|
|
40
|
-
}
|
|
41
|
-
export function getCheckpointManifestPath(sessionId) {
|
|
42
|
-
return path.join(getCheckpointDir(sessionId), "restore-manifest.yaml");
|
|
43
|
-
}
|
|
44
|
-
export function getCheckpointMetadataPath(sessionId) {
|
|
45
|
-
return path.join(getCheckpointDir(sessionId), "backup-metadata.yaml");
|
|
46
|
-
}
|
|
47
|
-
export const EMERGENCY_LOG_PATH = path.join(
|
|
48
|
-
// ~/.onto/emergency-log.jsonl. We resolve via process.env.HOME so callers
|
|
49
|
-
// running under tmpdir-based tests can override the home directory.
|
|
50
|
-
process.env.HOME ?? "", ".onto", "emergency-log.jsonl");
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
// Source gathering
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
|
-
function getFreshness(source) {
|
|
55
|
-
return source.freshness;
|
|
56
|
-
}
|
|
57
|
-
function readEmergencyLogEntries(sessionId, logPath) {
|
|
58
|
-
if (!fs.existsSync(logPath))
|
|
59
|
-
return [];
|
|
60
|
-
const content = fs.readFileSync(logPath, "utf8");
|
|
61
|
-
const lines = content.split("\n").filter((l) => l.trim().length > 0);
|
|
62
|
-
const entries = [];
|
|
63
|
-
for (const line of lines) {
|
|
64
|
-
try {
|
|
65
|
-
const parsed = JSON.parse(line);
|
|
66
|
-
if (parsed.session_id === sessionId && parsed.schema_version === "1") {
|
|
67
|
-
entries.push(parsed);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
// Malformed line — skip. Real Phase 3 read protocol surfaces this via
|
|
72
|
-
// the proper EmergencyLogReadResult; this gather-helper is best-effort.
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return entries;
|
|
76
|
-
}
|
|
77
|
-
function reconstructCheckpointFromManifest(manifest, metadata) {
|
|
78
|
-
return {
|
|
79
|
-
schema_version: "1",
|
|
80
|
-
session_id: manifest.session_id,
|
|
81
|
-
created_at: manifest.created_at,
|
|
82
|
-
manifest_path: getCheckpointManifestPath(manifest.session_id),
|
|
83
|
-
backups: manifest.backups,
|
|
84
|
-
total_bytes: metadata.total_bytes,
|
|
85
|
-
protected: metadata.protected,
|
|
86
|
-
protection_reason: metadata.protection_reason,
|
|
87
|
-
attempt_id: manifest.attempt_id,
|
|
88
|
-
generation: manifest.generation,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
export async function gatherRecoveryContext(sessionId, projectRoot) {
|
|
92
|
-
const context = {
|
|
93
|
-
session_id: sessionId,
|
|
94
|
-
gathered_at: new Date().toISOString(),
|
|
95
|
-
apply_state: null,
|
|
96
|
-
emergency_log: null,
|
|
97
|
-
checkpoint_manifest: null,
|
|
98
|
-
};
|
|
99
|
-
// 1. apply_state (in-band)
|
|
100
|
-
const applyStatePath = getApplyStatePath(projectRoot, sessionId);
|
|
101
|
-
if (fs.existsSync(applyStatePath)) {
|
|
102
|
-
try {
|
|
103
|
-
const state = REGISTRY.loadFromFile("apply_execution_state", applyStatePath);
|
|
104
|
-
context.apply_state = {
|
|
105
|
-
kind: "apply_state",
|
|
106
|
-
state,
|
|
107
|
-
freshness: {
|
|
108
|
-
attempt_id: state.attempt_id,
|
|
109
|
-
generation: state.generation,
|
|
110
|
-
source_recorded_at: state.last_updated_at,
|
|
111
|
-
source_kind: "apply_state",
|
|
112
|
-
},
|
|
113
|
-
artifact_path: applyStatePath,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// Load failure — leave null. The recovery resolver will treat it as
|
|
118
|
-
// missing and fall back to other sources.
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// 2. emergency_log (out-of-band)
|
|
122
|
-
const emergencyEntries = readEmergencyLogEntries(sessionId, EMERGENCY_LOG_PATH);
|
|
123
|
-
if (emergencyEntries.length > 0) {
|
|
124
|
-
const sorted = [...emergencyEntries].sort((a, b) => b.generation - a.generation);
|
|
125
|
-
const latest = sorted[0];
|
|
126
|
-
context.emergency_log = {
|
|
127
|
-
kind: "emergency_log",
|
|
128
|
-
entries: sorted,
|
|
129
|
-
latest_entry: latest,
|
|
130
|
-
freshness: {
|
|
131
|
-
attempt_id: latest.attempt_id,
|
|
132
|
-
generation: latest.generation,
|
|
133
|
-
source_recorded_at: latest.written_at,
|
|
134
|
-
source_kind: "emergency_log",
|
|
135
|
-
},
|
|
136
|
-
log_path: EMERGENCY_LOG_PATH,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
// 3. checkpoint_manifest
|
|
140
|
-
const manifestPath = getCheckpointManifestPath(sessionId);
|
|
141
|
-
const metadataPath = getCheckpointMetadataPath(sessionId);
|
|
142
|
-
if (fs.existsSync(manifestPath) && fs.existsSync(metadataPath)) {
|
|
143
|
-
try {
|
|
144
|
-
const manifest = REGISTRY.loadFromFile("restore_manifest", manifestPath);
|
|
145
|
-
const metadata = REGISTRY.loadFromFile("backup_metadata", metadataPath);
|
|
146
|
-
const checkpoint = reconstructCheckpointFromManifest(manifest, metadata);
|
|
147
|
-
context.checkpoint_manifest = {
|
|
148
|
-
kind: "checkpoint_manifest",
|
|
149
|
-
manifest,
|
|
150
|
-
checkpoint,
|
|
151
|
-
freshness: {
|
|
152
|
-
attempt_id: manifest.attempt_id,
|
|
153
|
-
generation: manifest.generation,
|
|
154
|
-
source_recorded_at: manifest.created_at,
|
|
155
|
-
source_kind: "checkpoint_manifest",
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
// Manifest corrupted: skip. Operator must intervene manually.
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return context;
|
|
164
|
-
}
|
|
165
|
-
// ---------------------------------------------------------------------------
|
|
166
|
-
// DD-23 recovery resolution persistence
|
|
167
|
-
// ---------------------------------------------------------------------------
|
|
168
|
-
export function loadRecoveryResolution(projectRoot, sessionId) {
|
|
169
|
-
const p = getRecoveryResolutionPath(projectRoot, sessionId);
|
|
170
|
-
if (!fs.existsSync(p))
|
|
171
|
-
return null;
|
|
172
|
-
return REGISTRY.loadFromFile("recovery_resolution", p);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* NQ-21: append-only resolution history.
|
|
176
|
-
*
|
|
177
|
-
* If a prior recovery-resolution.yaml exists for this session, the new entry
|
|
178
|
-
* is APPENDED to its resolution_history array and the top-level fields are
|
|
179
|
-
* updated to reflect the latest decision. Older history entries are
|
|
180
|
-
* preserved verbatim — the audit trail must show every reversal and reason.
|
|
181
|
-
*
|
|
182
|
-
* If no prior file exists, the new entry becomes the sole history entry.
|
|
183
|
-
*
|
|
184
|
-
* The caller passes a RecoveryResolution where the top-level fields describe
|
|
185
|
-
* the new decision and resolution_history contains exactly one entry (the
|
|
186
|
-
* new decision). saveRecoveryResolution() expands resolution_history with
|
|
187
|
-
* the prior entries when applicable.
|
|
188
|
-
*/
|
|
189
|
-
export function saveRecoveryResolution(projectRoot, resolution) {
|
|
190
|
-
// m-2 fix: validate input contract before touching disk. Empty
|
|
191
|
-
// resolution_history would crash on the [length-1] access below; throw
|
|
192
|
-
// explicitly so the caller knows their input is malformed.
|
|
193
|
-
if (resolution.resolution_history.length === 0) {
|
|
194
|
-
throw new Error(`saveRecoveryResolution: resolution_history must contain at least one entry ` +
|
|
195
|
-
`(got 0). The caller is expected to pass a single-entry history; merging ` +
|
|
196
|
-
`with prior entries is handled here.`);
|
|
197
|
-
}
|
|
198
|
-
// N-3 acknowledged: this load → merge → save sequence is not atomic across
|
|
199
|
-
// processes. Two concurrent recovery-resolution writes
|
|
200
|
-
// for the same session could lose updates. Phase 3 is single-process per
|
|
201
|
-
// session by design; cross-process coordination is a follow-up requiring a
|
|
202
|
-
// file lock or rename-temp pattern. Documented as a known limitation.
|
|
203
|
-
const p = getRecoveryResolutionPath(projectRoot, resolution.session_id);
|
|
204
|
-
// Load prior history if any. We probe via fs.existsSync to distinguish
|
|
205
|
-
// "first decision" from "load failed" — load failure should propagate.
|
|
206
|
-
let priorHistory = [];
|
|
207
|
-
if (fs.existsSync(p)) {
|
|
208
|
-
const prior = REGISTRY.loadFromFile("recovery_resolution", p);
|
|
209
|
-
priorHistory = prior.resolution_history;
|
|
210
|
-
}
|
|
211
|
-
// The caller passes a single-entry resolution_history with the new decision.
|
|
212
|
-
// We expand it with the prior entries during merge. Multi-entry input is
|
|
213
|
-
// rejected by the length check above so the LAST-entry fallback is no longer
|
|
214
|
-
// needed.
|
|
215
|
-
const newEntry = resolution.resolution_history[resolution.resolution_history.length - 1];
|
|
216
|
-
const merged = {
|
|
217
|
-
schema_version: "1",
|
|
218
|
-
session_id: resolution.session_id,
|
|
219
|
-
resolved_at: newEntry.resolved_at,
|
|
220
|
-
resolved_by: newEntry.resolved_by,
|
|
221
|
-
resolution_method: newEntry.resolution_method,
|
|
222
|
-
selected_attempt_id: newEntry.selected_attempt_id,
|
|
223
|
-
selected_attempt_reason: newEntry.selected_attempt_reason,
|
|
224
|
-
all_attempts_at_resolution_time: newEntry.all_attempts_at_resolution_time,
|
|
225
|
-
...(newEntry.operator_note !== undefined
|
|
226
|
-
? { operator_note: newEntry.operator_note }
|
|
227
|
-
: {}),
|
|
228
|
-
resolution_history: [...priorHistory, newEntry],
|
|
229
|
-
};
|
|
230
|
-
REGISTRY.saveToFile("recovery_resolution", p, merged);
|
|
231
|
-
}
|
|
232
|
-
// ---------------------------------------------------------------------------
|
|
233
|
-
// Truth resolution
|
|
234
|
-
// ---------------------------------------------------------------------------
|
|
235
|
-
function collectAllSources(context) {
|
|
236
|
-
const sources = [];
|
|
237
|
-
if (context.apply_state)
|
|
238
|
-
sources.push(context.apply_state);
|
|
239
|
-
if (context.emergency_log)
|
|
240
|
-
sources.push(context.emergency_log);
|
|
241
|
-
if (context.checkpoint_manifest)
|
|
242
|
-
sources.push(context.checkpoint_manifest);
|
|
243
|
-
return sources;
|
|
244
|
-
}
|
|
245
|
-
function getArtifactPath(source) {
|
|
246
|
-
switch (source.kind) {
|
|
247
|
-
case "apply_state":
|
|
248
|
-
return source.artifact_path;
|
|
249
|
-
case "emergency_log":
|
|
250
|
-
return source.log_path;
|
|
251
|
-
case "checkpoint_manifest":
|
|
252
|
-
return source.checkpoint.manifest_path;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
function toAttemptInfo(source) {
|
|
256
|
-
return {
|
|
257
|
-
attempt_id: source.freshness.attempt_id,
|
|
258
|
-
source_kind: source.freshness.source_kind,
|
|
259
|
-
generation: source.freshness.generation,
|
|
260
|
-
source_recorded_at: source.freshness.source_recorded_at,
|
|
261
|
-
artifact_path: getArtifactPath(source),
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
function resolveWithinAttempt(sources) {
|
|
265
|
-
const sorted = [...sources].sort((a, b) => getFreshness(b).generation - getFreshness(a).generation);
|
|
266
|
-
return {
|
|
267
|
-
latest_source: sorted[0],
|
|
268
|
-
older_sources: sorted.slice(1),
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Cross-attempt selection (auto_resolve_latest_generation policy).
|
|
273
|
-
*
|
|
274
|
-
* SYN-CONS-01 (v9): generation is only monotonic WITHIN one attempt_id.
|
|
275
|
-
* Cross-attempt comparison must first select a canonical attempt by ULID
|
|
276
|
-
* timestamp ordering (lexicographic == chronological for ULID).
|
|
277
|
-
*/
|
|
278
|
-
function selectCanonicalAttemptAuto(sources) {
|
|
279
|
-
const byAttempt = new Map();
|
|
280
|
-
for (const source of sources) {
|
|
281
|
-
const id = getFreshness(source).attempt_id;
|
|
282
|
-
const existing = byAttempt.get(id) ?? [];
|
|
283
|
-
existing.push(source);
|
|
284
|
-
byAttempt.set(id, existing);
|
|
285
|
-
}
|
|
286
|
-
const sortedAttempts = [...byAttempt.keys()].sort();
|
|
287
|
-
const canonicalAttemptId = sortedAttempts[sortedAttempts.length - 1];
|
|
288
|
-
return byAttempt.get(canonicalAttemptId);
|
|
289
|
-
}
|
|
290
|
-
export function resolveRecoveryTruth(context, projectRoot, policy = DEFAULT_RECOVERY_POLICY) {
|
|
291
|
-
const sources = collectAllSources(context);
|
|
292
|
-
if (sources.length === 0) {
|
|
293
|
-
return { kind: "no_recovery_data" };
|
|
294
|
-
}
|
|
295
|
-
const attemptIds = new Set(sources.map((s) => getFreshness(s).attempt_id));
|
|
296
|
-
if (attemptIds.size > 1) {
|
|
297
|
-
if (policy.cross_attempt_conflict === "manual_escalation") {
|
|
298
|
-
// DD-23: check existing operator resolution first
|
|
299
|
-
const existing = loadRecoveryResolution(projectRoot, context.session_id);
|
|
300
|
-
if (existing !== null) {
|
|
301
|
-
const selectedSources = sources.filter((s) => getFreshness(s).attempt_id === existing.selected_attempt_id);
|
|
302
|
-
if (selectedSources.length === 0) {
|
|
303
|
-
// Resolution refers to an attempt that no longer has any sources.
|
|
304
|
-
// Surface as escalation again so operator can re-decide.
|
|
305
|
-
return {
|
|
306
|
-
kind: "manual_escalation_required",
|
|
307
|
-
conflicting_attempts: sources.map(toAttemptInfo),
|
|
308
|
-
escalation_reason: `Existing recovery-resolution.yaml references attempt_id ` +
|
|
309
|
-
`${existing.selected_attempt_id}, but no source matches that ` +
|
|
310
|
-
`attempt anymore. Re-record the recovery decision.`,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
const within = resolveWithinAttempt(selectedSources);
|
|
314
|
-
return {
|
|
315
|
-
kind: "resolved",
|
|
316
|
-
source_of_truth: "operator_resolution",
|
|
317
|
-
latest_source: within.latest_source,
|
|
318
|
-
older_sources: within.older_sources,
|
|
319
|
-
has_conflict: true,
|
|
320
|
-
resolution_artifact_path: getRecoveryResolutionPath(projectRoot, context.session_id),
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
return {
|
|
324
|
-
kind: "manual_escalation_required",
|
|
325
|
-
conflicting_attempts: sources.map(toAttemptInfo),
|
|
326
|
-
escalation_reason: `Multiple attempt_ids detected (${attemptIds.size}). Manual ` +
|
|
327
|
-
`operator decision required to select canonical recovery source. ` +
|
|
328
|
-
`Record a recovery decision selecting the canonical attempt id.`,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
// auto_resolve_latest_generation
|
|
332
|
-
const canonicalSources = selectCanonicalAttemptAuto(sources);
|
|
333
|
-
const within = resolveWithinAttempt(canonicalSources);
|
|
334
|
-
return {
|
|
335
|
-
kind: "resolved",
|
|
336
|
-
source_of_truth: "auto_resolved",
|
|
337
|
-
latest_source: within.latest_source,
|
|
338
|
-
older_sources: within.older_sources,
|
|
339
|
-
has_conflict: true,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
// Single attempt path
|
|
343
|
-
const within = resolveWithinAttempt(sources);
|
|
344
|
-
return {
|
|
345
|
-
kind: "resolved",
|
|
346
|
-
source_of_truth: "single_attempt",
|
|
347
|
-
latest_source: within.latest_source,
|
|
348
|
-
older_sources: within.older_sources,
|
|
349
|
-
has_conflict: false,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
export function getResolvedFreshness(truth) {
|
|
353
|
-
if (truth.kind !== "resolved")
|
|
354
|
-
return null;
|
|
355
|
-
return getFreshness(truth.latest_source);
|
|
356
|
-
}
|
|
357
|
-
// ---------------------------------------------------------------------------
|
|
358
|
-
// Operator-facing message
|
|
359
|
-
// ---------------------------------------------------------------------------
|
|
360
|
-
export function buildEscalationMessage(resolved) {
|
|
361
|
-
const lines = [
|
|
362
|
-
"Recovery Manual Escalation Required",
|
|
363
|
-
"====================================",
|
|
364
|
-
"",
|
|
365
|
-
`Reason: ${resolved.escalation_reason}`,
|
|
366
|
-
"",
|
|
367
|
-
"Conflicting attempts:",
|
|
368
|
-
];
|
|
369
|
-
resolved.conflicting_attempts.forEach((c, i) => {
|
|
370
|
-
lines.push(` ${i + 1}. attempt_id=${c.attempt_id}`, ` source=${c.source_kind}`, ` generation=${c.generation}`, ` recorded_at=${c.source_recorded_at}`, ` artifact_path=${c.artifact_path}`);
|
|
371
|
-
});
|
|
372
|
-
lines.push("", "Resolution options:", " A) Record recovery-resolution selection for <attempt-id>", " B) Edit decisions file with 'recovery_resolution' section", " C) Re-run apply with auto-resolve-attempt-conflict", "", "Note: option C bypasses manual review. Use only when trade-offs are understood.");
|
|
373
|
-
return lines.join("\n");
|
|
374
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic classifier — A-11 (Phase 2).
|
|
3
|
-
*
|
|
4
|
-
* LLM-based semantic classification of new learning items against existing items.
|
|
5
|
-
* U4 해소: single decision enum + optional conflict_kind.
|
|
6
|
-
* R4-IA1: LLM 실패 → unclassified_pending (저장 안 함).
|
|
7
|
-
*/
|
|
8
|
-
import { callLlm, hashPrompt } from "./llm-caller.js";
|
|
9
|
-
/** Canonical single definition — CONS-5: all consumers import from here. */
|
|
10
|
-
export const SEMANTIC_DECISIONS = [
|
|
11
|
-
"save",
|
|
12
|
-
"duplicate_skip",
|
|
13
|
-
"conflict_propose_replace",
|
|
14
|
-
"conflict_propose_keep",
|
|
15
|
-
"conflict_propose_coexist",
|
|
16
|
-
"unclassified_pending",
|
|
17
|
-
];
|
|
18
|
-
export const CONFLICT_KINDS = [
|
|
19
|
-
"contradiction",
|
|
20
|
-
"supersession",
|
|
21
|
-
"disambiguation",
|
|
22
|
-
];
|
|
23
|
-
const SYSTEM_PROMPT = `You are a semantic classifier for a learning management system.
|
|
24
|
-
Given a NEW learning item and a list of EXISTING learning items, determine:
|
|
25
|
-
|
|
26
|
-
1. Is the new item semantically equivalent to any existing item? → "duplicate_skip"
|
|
27
|
-
2. Does the new item conflict with an existing item?
|
|
28
|
-
- Contradiction (opposite claims) → "conflict_propose_replace"
|
|
29
|
-
- Supersession (new item updates/replaces) → "conflict_propose_replace"
|
|
30
|
-
- Disambiguation (both valid in different contexts) → "conflict_propose_coexist"
|
|
31
|
-
- If unsure whether new or existing is better → "conflict_propose_keep"
|
|
32
|
-
3. No semantic overlap → "save"
|
|
33
|
-
|
|
34
|
-
Respond ONLY with valid JSON (no markdown fences):
|
|
35
|
-
{
|
|
36
|
-
"decision": "<one of: save, duplicate_skip, conflict_propose_replace, conflict_propose_keep, conflict_propose_coexist>",
|
|
37
|
-
"conflict_kind": "<one of: contradiction, supersession, disambiguation> or null",
|
|
38
|
-
"matched_existing_line": "<the existing line that matches/conflicts, or null>",
|
|
39
|
-
"reason": "<brief explanation>"
|
|
40
|
-
}`;
|
|
41
|
-
/**
|
|
42
|
-
* Classify a new learning item against existing items.
|
|
43
|
-
* A-11: LLM semantic classification.
|
|
44
|
-
*/
|
|
45
|
-
export async function classifyLearningItem(newLine, existingLines, modelId) {
|
|
46
|
-
if (existingLines.length === 0) {
|
|
47
|
-
return {
|
|
48
|
-
decision: "save",
|
|
49
|
-
reason: "No existing items to compare against.",
|
|
50
|
-
model_id: "none",
|
|
51
|
-
prompt_hash: "none",
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const userPrompt = `NEW ITEM:
|
|
55
|
-
${newLine}
|
|
56
|
-
|
|
57
|
-
EXISTING ITEMS (${existingLines.length}):
|
|
58
|
-
${existingLines.map((l, i) => `${i + 1}. ${l}`).join("\n")}`;
|
|
59
|
-
const promptHash = hashPrompt(SYSTEM_PROMPT + userPrompt);
|
|
60
|
-
try {
|
|
61
|
-
const callConfig = { max_tokens: 512 };
|
|
62
|
-
if (modelId)
|
|
63
|
-
callConfig.model_id = modelId;
|
|
64
|
-
const result = await callLlm(SYSTEM_PROMPT, userPrompt, callConfig);
|
|
65
|
-
const parsed = JSON.parse(result.text.trim());
|
|
66
|
-
const decision = parsed.decision;
|
|
67
|
-
// Exclude unclassified_pending — it's a fallback, not a valid LLM output
|
|
68
|
-
const validLlmDecisions = SEMANTIC_DECISIONS.filter((d) => d !== "unclassified_pending");
|
|
69
|
-
if (!validLlmDecisions.includes(decision)) {
|
|
70
|
-
return {
|
|
71
|
-
decision: "unclassified_pending",
|
|
72
|
-
reason: `Invalid decision from LLM: "${decision}"`,
|
|
73
|
-
model_id: result.model_id,
|
|
74
|
-
prompt_hash: promptHash,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
decision: decision,
|
|
79
|
-
conflict_kind: parsed.conflict_kind ?? undefined,
|
|
80
|
-
matched_existing_line: parsed.matched_existing_line ?? undefined,
|
|
81
|
-
reason: parsed.reason ?? "",
|
|
82
|
-
model_id: result.model_id,
|
|
83
|
-
prompt_hash: promptHash,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
return {
|
|
88
|
-
decision: "unclassified_pending",
|
|
89
|
-
reason: `LLM call failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
90
|
-
model_id: modelId ?? "claude-sonnet-4-20250514",
|
|
91
|
-
prompt_hash: promptHash,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ApplyExecutionState spec — DD-15 + DD-22.
|
|
3
|
-
*
|
|
4
|
-
* Persisted JSON at {sessionRoot}/promote-execution-result.json. Phase B
|
|
5
|
-
* persists this state on every meaningful step so failed_resumable runs can
|
|
6
|
-
* pick up where they left off.
|
|
7
|
-
*/
|
|
8
|
-
import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, checkNumber, checkArray, } from "./spec-helpers.js";
|
|
9
|
-
const KIND = "apply_execution_state";
|
|
10
|
-
const CURRENT_VERSION = "1";
|
|
11
|
-
const SUPPORTED = ["1"];
|
|
12
|
-
export const ApplyExecutionStateSpec = {
|
|
13
|
-
kind: KIND,
|
|
14
|
-
current_schema_version: CURRENT_VERSION,
|
|
15
|
-
supported_schema_versions: SUPPORTED,
|
|
16
|
-
supported_formats: ["json"],
|
|
17
|
-
parse(content, format) {
|
|
18
|
-
const raw = parseRaw(content, format);
|
|
19
|
-
return rejectPreV7(raw, KIND, SUPPORTED);
|
|
20
|
-
},
|
|
21
|
-
serialize(data, format) {
|
|
22
|
-
return serializeRaw(data, format);
|
|
23
|
-
},
|
|
24
|
-
validate(data) {
|
|
25
|
-
const errors = [];
|
|
26
|
-
if (typeof data !== "object" || data === null) {
|
|
27
|
-
return { valid: false, errors: ["data is not an object"] };
|
|
28
|
-
}
|
|
29
|
-
const obj = data;
|
|
30
|
-
checkSchemaVersion(obj, CURRENT_VERSION, errors);
|
|
31
|
-
checkString(obj, "session_id", errors);
|
|
32
|
-
checkString(obj, "attempt_id", errors);
|
|
33
|
-
checkString(obj, "attempt_started_at", errors);
|
|
34
|
-
checkNumber(obj, "generation", errors);
|
|
35
|
-
checkString(obj, "last_updated_at", errors);
|
|
36
|
-
checkString(obj, "status", errors);
|
|
37
|
-
checkArray(obj, "applied_decisions", errors);
|
|
38
|
-
checkArray(obj, "failed_decisions", errors);
|
|
39
|
-
checkArray(obj, "pending_decisions", errors);
|
|
40
|
-
return { valid: errors.length === 0, errors };
|
|
41
|
-
},
|
|
42
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AuditState spec — DD-17 + DD-21.
|
|
3
|
-
*
|
|
4
|
-
* Persisted YAML at ~/.onto/audit-state.yaml.
|
|
5
|
-
*
|
|
6
|
-
* Class boundary: parse() returns plain JSON; consumers reconstruct
|
|
7
|
-
* AuditObligation class instances via AuditObligation.fromJSON(). The spec
|
|
8
|
-
* intentionally does NOT import the class so this module stays in the kernel
|
|
9
|
-
* dependency layer.
|
|
10
|
-
*/
|
|
11
|
-
import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkArray, } from "./spec-helpers.js";
|
|
12
|
-
const KIND = "audit_state";
|
|
13
|
-
const CURRENT_VERSION = "1";
|
|
14
|
-
const SUPPORTED = ["1"];
|
|
15
|
-
export const AuditStateSpec = {
|
|
16
|
-
kind: KIND,
|
|
17
|
-
current_schema_version: CURRENT_VERSION,
|
|
18
|
-
supported_schema_versions: SUPPORTED,
|
|
19
|
-
supported_formats: ["yaml"],
|
|
20
|
-
parse(content, format) {
|
|
21
|
-
const raw = parseRaw(content, format);
|
|
22
|
-
return rejectPreV7(raw, KIND, SUPPORTED);
|
|
23
|
-
},
|
|
24
|
-
serialize(data, format) {
|
|
25
|
-
return serializeRaw(data, format);
|
|
26
|
-
},
|
|
27
|
-
validate(data) {
|
|
28
|
-
const errors = [];
|
|
29
|
-
if (typeof data !== "object" || data === null) {
|
|
30
|
-
return { valid: false, errors: ["data is not an object"] };
|
|
31
|
-
}
|
|
32
|
-
const obj = data;
|
|
33
|
-
checkSchemaVersion(obj, CURRENT_VERSION, errors);
|
|
34
|
-
checkArray(obj, "obligations", errors);
|
|
35
|
-
return { valid: errors.length === 0, errors };
|
|
36
|
-
},
|
|
37
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BackupMetadata spec — DD-16 (BACKUP-PROTECTION-01).
|
|
3
|
-
*
|
|
4
|
-
* Persisted YAML at ~/.onto/backups/{session-id}/backup-metadata.yaml.
|
|
5
|
-
* Tracks protection state so prune respects active sessions and unrecoverable
|
|
6
|
-
* failures.
|
|
7
|
-
*/
|
|
8
|
-
import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, checkNumber, } from "./spec-helpers.js";
|
|
9
|
-
const KIND = "backup_metadata";
|
|
10
|
-
const CURRENT_VERSION = "1";
|
|
11
|
-
const SUPPORTED = ["1"];
|
|
12
|
-
export const BackupMetadataSpec = {
|
|
13
|
-
kind: KIND,
|
|
14
|
-
current_schema_version: CURRENT_VERSION,
|
|
15
|
-
supported_schema_versions: SUPPORTED,
|
|
16
|
-
supported_formats: ["yaml"],
|
|
17
|
-
parse(content, format) {
|
|
18
|
-
const raw = parseRaw(content, format);
|
|
19
|
-
return rejectPreV7(raw, KIND, SUPPORTED);
|
|
20
|
-
},
|
|
21
|
-
serialize(data, format) {
|
|
22
|
-
return serializeRaw(data, format);
|
|
23
|
-
},
|
|
24
|
-
validate(data) {
|
|
25
|
-
const errors = [];
|
|
26
|
-
if (typeof data !== "object" || data === null) {
|
|
27
|
-
return { valid: false, errors: ["data is not an object"] };
|
|
28
|
-
}
|
|
29
|
-
const obj = data;
|
|
30
|
-
checkSchemaVersion(obj, CURRENT_VERSION, errors);
|
|
31
|
-
checkString(obj, "session_id", errors);
|
|
32
|
-
checkString(obj, "created_at", errors);
|
|
33
|
-
checkNumber(obj, "total_bytes", errors);
|
|
34
|
-
if (typeof obj.protected !== "boolean") {
|
|
35
|
-
errors.push("protected must be a boolean");
|
|
36
|
-
}
|
|
37
|
-
return { valid: errors.length === 0, errors };
|
|
38
|
-
},
|
|
39
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EmergencyLogEntry spec — DD-15.
|
|
3
|
-
*
|
|
4
|
-
* Append-only JSONL at ~/.onto/emergency-log.jsonl. Each entry is one JSON
|
|
5
|
-
* object on a single line. Spec.serialize emits a single object (no trailing
|
|
6
|
-
* newline); the registry's appendToFile() adds the newline.
|
|
7
|
-
*/
|
|
8
|
-
import { rejectPreV7, checkSchemaVersion, checkString, checkNumber, } from "./spec-helpers.js";
|
|
9
|
-
const KIND = "emergency_log_entry";
|
|
10
|
-
const CURRENT_VERSION = "1";
|
|
11
|
-
const SUPPORTED = ["1"];
|
|
12
|
-
export const EmergencyLogSpec = {
|
|
13
|
-
kind: KIND,
|
|
14
|
-
current_schema_version: CURRENT_VERSION,
|
|
15
|
-
supported_schema_versions: SUPPORTED,
|
|
16
|
-
supported_formats: ["json"],
|
|
17
|
-
parse(content, _format) {
|
|
18
|
-
const raw = JSON.parse(content);
|
|
19
|
-
return rejectPreV7(raw, KIND, SUPPORTED);
|
|
20
|
-
},
|
|
21
|
-
serialize(data, _format) {
|
|
22
|
-
return JSON.stringify(data);
|
|
23
|
-
},
|
|
24
|
-
validate(data) {
|
|
25
|
-
const errors = [];
|
|
26
|
-
if (typeof data !== "object" || data === null) {
|
|
27
|
-
return { valid: false, errors: ["data is not an object"] };
|
|
28
|
-
}
|
|
29
|
-
const obj = data;
|
|
30
|
-
checkSchemaVersion(obj, CURRENT_VERSION, errors);
|
|
31
|
-
checkString(obj, "entry_id", errors);
|
|
32
|
-
checkString(obj, "session_id", errors);
|
|
33
|
-
checkString(obj, "written_at", errors);
|
|
34
|
-
checkString(obj, "attempt_id", errors);
|
|
35
|
-
checkNumber(obj, "generation", errors);
|
|
36
|
-
checkString(obj, "fatal_error_kind", errors);
|
|
37
|
-
checkString(obj, "fatal_error_message", errors);
|
|
38
|
-
checkString(obj, "session_root", errors);
|
|
39
|
-
return { valid: errors.length === 0, errors };
|
|
40
|
-
},
|
|
41
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LayoutVersion spec — DD-8.
|
|
3
|
-
*
|
|
4
|
-
* Persisted at {projectRoot}/.onto/.layout-version.yaml. Identifies the
|
|
5
|
-
* session-root layout version so old layouts trigger migration before any
|
|
6
|
-
* promote command touches files.
|
|
7
|
-
*/
|
|
8
|
-
import { parseRaw, serializeRaw, rejectPreV7, checkSchemaVersion, checkString, } from "./spec-helpers.js";
|
|
9
|
-
const KIND = "layout_version";
|
|
10
|
-
const CURRENT_VERSION = "1";
|
|
11
|
-
const SUPPORTED = ["1"];
|
|
12
|
-
export const LayoutVersionSpec = {
|
|
13
|
-
kind: KIND,
|
|
14
|
-
current_schema_version: CURRENT_VERSION,
|
|
15
|
-
supported_schema_versions: SUPPORTED,
|
|
16
|
-
supported_formats: ["yaml"],
|
|
17
|
-
parse(content, format) {
|
|
18
|
-
const raw = parseRaw(content, format);
|
|
19
|
-
return rejectPreV7(raw, KIND, SUPPORTED);
|
|
20
|
-
},
|
|
21
|
-
serialize(data, format) {
|
|
22
|
-
return serializeRaw(data, format);
|
|
23
|
-
},
|
|
24
|
-
validate(data) {
|
|
25
|
-
const errors = [];
|
|
26
|
-
if (typeof data !== "object" || data === null) {
|
|
27
|
-
return { valid: false, errors: ["data is not an object"] };
|
|
28
|
-
}
|
|
29
|
-
const obj = data;
|
|
30
|
-
checkSchemaVersion(obj, CURRENT_VERSION, errors);
|
|
31
|
-
checkString(obj, "layout_version", errors);
|
|
32
|
-
if (obj.layout_version !== "v3") {
|
|
33
|
-
errors.push(`layout_version must be "v3"`);
|
|
34
|
-
}
|
|
35
|
-
checkString(obj, "written_at", errors);
|
|
36
|
-
return { valid: errors.length === 0, errors };
|
|
37
|
-
},
|
|
38
|
-
};
|