@cassiomc1/forgeloop 1.13.0 → 2.0.0-rc.2
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/AGENT_COMPATIBILITY.md +8 -0
- package/CONTRIBUTING.md +11 -7
- package/DOCS_INDEX.md +37 -4
- package/ENG/c-development-eng.md +2 -2
- package/ENG/cpp-development-eng.md +2 -2
- package/ENG/dotnet-aspnetcore-development-eng.md +7 -1
- package/ENG/flutter-development-eng.md +4 -2
- package/ENG/go-development-eng.md +2 -2
- package/ENG/java-development-eng.md +3 -3
- package/ENG/nodejs-backend-development-eng.md +10 -6
- package/ENG/php-development-eng.md +3 -3
- package/ENG/python-development-eng.md +205 -0
- package/ENG/rust-development-eng.md +42 -1
- package/ENG/sec-code-eng.md +7 -7
- package/ENG/sql-development-eng.md +4 -4
- package/ENG/swift-development-eng.md +5 -4
- package/ENG/test-code-eng.md +1 -1
- package/ENG/typescript-development-eng.md +4 -4
- package/EXECUTION_STATE.md +12 -0
- package/GUIDE_ROUTER.md +6 -0
- package/LICENSE +133 -21
- package/LOOP_ENGINEERING.md +28 -2
- package/LOOP_SYSTEM_DESIGN.md +10 -10
- package/ORCHESTRATOR_INTEGRATION.md +9 -5
- package/PROTOCOL_INTEGRATION.md +55 -2
- package/README.md +63 -59
- package/TERMINOLOGY.md +2 -0
- package/THIRD_PARTY_NOTICES.md +3 -4
- package/THREAT_MODEL.md +140 -1
- package/completions/_forgeloop +29 -3
- package/completions/forgeloop.bash +55 -3
- package/completions/forgeloop.fish +183 -1
- package/docs/ADVISORY_CONTEXT.md +25 -0
- package/docs/AGENT_BROWSER_ADAPTER.md +81 -0
- package/docs/AGENT_BROWSER_VERIFICATION.md +6 -0
- package/docs/AGENT_PROTOCOL_SUMMARY.md +74 -39
- package/docs/AGENT_SKILL.md +66 -0
- package/docs/ARTIFACT_REFERENCE.md +171 -35
- package/docs/AUDIT_UX.md +46 -0
- package/docs/BROWSER_VERIFICATION.md +136 -0
- package/docs/CLI_REFERENCE.md +512 -8
- package/docs/CODE_ATTESTATION.md +2 -2
- package/docs/DOCUMENTATION_GUIDE.md +34 -11
- package/docs/GETTING_STARTED.md +3 -3
- package/docs/JEV_BENCHMARKS.md +31 -0
- package/docs/MODEL_ROUTING.md +37 -0
- package/docs/OPENSRC_ADAPTER.md +241 -0
- package/docs/PACKAGE_CONTENTS.md +46 -18
- package/docs/PROVIDERS.md +126 -0
- package/docs/PROVIDER_ARCHITECTURE.md +199 -0
- package/docs/RECIPES.md +9 -0
- package/docs/RELEASE_CHECKLIST.md +116 -12
- package/docs/SECURITY_REVIEW.md +71 -0
- package/docs/SELF_HOSTED_TESTS.md +121 -0
- package/docs/SEMANTIC_DECISION_PLANE.md +71 -0
- package/docs/TEST_INTELLIGENCE.md +29 -0
- package/docs/TEST_PRUNING.md +14 -0
- package/docs/TROUBLESHOOTING.md +198 -1
- package/docs/UNIVERSAL_INTEGRATION.md +31 -0
- package/docs/assets/diagrams/forgeloop-code-attestation-flow.html +2 -2
- package/docs/assets/diagrams/forgeloop-code-attestation-flow.receipt.json +5 -5
- package/docs/assets/diagrams/forgeloop-code-attestation-flow.svg +1 -1
- package/docs/assets/diagrams/forgeloop-engineering-flow.html +39 -26
- package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +6 -6
- package/docs/assets/diagrams/forgeloop-engineering-flow.svg +26 -26
- package/docs/assets/diagrams/forgeloop-verification-trust-flow.html +2 -1
- package/docs/assets/diagrams/forgeloop-verification-trust-flow.receipt.json +5 -5
- package/docs/assets/diagrams/forgeloop-verification-trust-flow.svg +1 -1
- package/docs/diagrams/README.md +13 -9
- package/docs/diagrams/forgeloop-code-attestation-flow.workflow.json +1 -1
- package/docs/diagrams/forgeloop-engineering-flow.workflow.json +24 -19
- package/docs/diagrams/forgeloop-verification-trust-flow.workflow.json +1 -0
- package/docs/diagrams/reviews/forgeloop-code-attestation-flow.review.json +4 -4
- package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +4 -4
- package/docs/diagrams/reviews/forgeloop-verification-trust-flow.review.json +4 -4
- package/docs/documentation-manifest.json +774 -16
- package/docs/protocol-requirements.json +24 -0
- package/package.json +43 -11
- package/schemas/config.schema.json +14 -0
- package/schemas/context-plan.schema.json +18 -0
- package/schemas/semantic-decision.schema.json +46 -0
- package/schemas/task-bundle.schema.json +7 -2
- package/schemas/test-utility.schema.json +44 -0
- package/scripts/CI_VALIDATORS.md +6 -6
- package/scripts/benchmark-jev.mjs +5 -0
- package/scripts/benchmark-test-intelligence.mjs +4 -0
- package/scripts/generate-agent-protocol-summary.mjs +6 -3
- package/scripts/generate-forgeloop-skill.mjs +133 -0
- package/scripts/jev-smoke.mjs +19 -0
- package/scripts/run-mcp-clean-tests.mjs +30 -0
- package/skills/forgeloop/README.md +9 -0
- package/skills/forgeloop/SKILL.md +77 -0
- package/skills/forgeloop/references/lifecycle.md +9 -0
- package/skills/forgeloop/references/recovery.md +7 -0
- package/skills/forgeloop/references/verification.md +7 -0
- package/src/adapters/agent-browser/assertions.js +47 -0
- package/src/adapters/agent-browser/commands.js +54 -0
- package/src/adapters/agent-browser/index.js +3 -0
- package/src/adapters/agent-browser/locator.js +40 -0
- package/src/adapters/agent-browser/process.js +215 -0
- package/src/adapters/agent-browser/provider.js +316 -0
- package/src/adapters/emulated-services/constants.js +24 -0
- package/src/adapters/emulated-services/index.js +7 -0
- package/src/adapters/emulated-services/process.js +162 -0
- package/src/adapters/emulated-services/provider.js +289 -0
- package/src/adapters/opensrc/normalize.js +90 -0
- package/src/adapters/opensrc/process.js +248 -0
- package/src/adapters/opensrc/provider.js +338 -0
- package/src/adapters/opensrc/search.js +264 -0
- package/src/adapters/temporary-paths.js +18 -0
- package/src/adapters/typesafe/client.js +28 -0
- package/src/adapters/typesafe/engine.js +63 -0
- package/src/adapters/typesafe/normalize.js +41 -0
- package/src/cli.js +218 -174
- package/src/commands/action-show.js +5 -2
- package/src/commands/advance.js +5 -1
- package/src/commands/baseline.js +13 -11
- package/src/commands/checkpoint-revalidate.js +192 -0
- package/src/commands/complete.js +19 -3
- package/src/commands/context-plan.js +38 -0
- package/src/commands/contract-create.js +266 -0
- package/src/commands/contract-revise.js +236 -0
- package/src/commands/decision-show.js +14 -0
- package/src/commands/decision-status.js +22 -0
- package/src/commands/discover.js +41 -0
- package/src/commands/doctor.js +51 -13
- package/src/commands/gate-record.js +194 -0
- package/src/commands/gate-revalidate.js +135 -0
- package/src/commands/handoff-list.js +6 -1
- package/src/commands/handoff-show.js +6 -1
- package/src/commands/migrate-protocol.js +2 -2
- package/src/commands/model-route.js +40 -0
- package/src/commands/next.js +7 -1
- package/src/commands/policy-diff.js +25 -4
- package/src/commands/progress.js +17 -11
- package/src/commands/record-diagnosis.js +3 -0
- package/src/commands/route.js +146 -18
- package/src/commands/semantic-plan.js +41 -0
- package/src/commands/status.js +6 -1
- package/src/commands/storage-backup.js +15 -0
- package/src/commands/storage-migrate.js +5 -0
- package/src/commands/storage-migration-resume.js +5 -0
- package/src/commands/storage-migration-status.js +44 -0
- package/src/commands/storage-restore-resume.js +7 -0
- package/src/commands/storage-restore.js +8 -0
- package/src/commands/task-abandon.js +224 -0
- package/src/commands/task-list.js +8 -43
- package/src/commands/task-migrate-contract-bootstrap-repair.js +288 -0
- package/src/commands/task-migrate.js +3 -3
- package/src/commands/task-recover.js +10 -2
- package/src/commands/task-repair-contract-bootstrap.js +263 -0
- package/src/commands/task-scope.js +18 -2
- package/src/commands/task-show.js +16 -2
- package/src/commands/test-inventory.js +5 -0
- package/src/commands/test-prune-plan.js +5 -0
- package/src/commands/test-prune-probe.js +5 -0
- package/src/commands/test-utility.js +5 -0
- package/src/commands/validate-protocol.js +39 -15
- package/src/commands/validate-receipt.js +8 -1
- package/src/config/guides.json +4 -0
- package/src/core/action-ledger-projection.js +10 -3
- package/src/core/actions.js +38 -75
- package/src/core/activation.js +11 -3
- package/src/core/approvals.js +17 -51
- package/src/core/artifact-registry.js +83 -2
- package/src/core/artifacts.js +81 -27
- package/src/core/attachment-paths.js +45 -0
- package/src/core/attestation-coverage.js +6 -1
- package/src/core/attestation-verifier.js +21 -2
- package/src/core/attestation.js +17 -6
- package/src/core/audit-ux.js +514 -0
- package/src/core/audit.js +6 -1
- package/src/core/browser-verification/constants.js +149 -0
- package/src/core/browser-verification/normalize.js +254 -0
- package/src/core/browser-verification/provider.js +519 -0
- package/src/core/browser-verification/service.js +115 -0
- package/src/core/bundles.js +160 -66
- package/src/core/checkpoint-revalidation.js +321 -0
- package/src/core/cli-command-definitions.js +350 -7
- package/src/core/code-manifest.js +9 -3
- package/src/core/command-executors.js +274 -108
- package/src/core/command-input.js +136 -44
- package/src/core/completion-artifacts.js +85 -34
- package/src/core/completion-ownership.js +19 -8
- package/src/core/completion-recovery-rebind.js +11 -1
- package/src/core/completion.js +64 -15
- package/src/core/config.js +3 -0
- package/src/core/conformance.js +2 -1
- package/src/core/context-compiler/budget.js +9 -0
- package/src/core/context-compiler/candidates.js +39 -0
- package/src/core/context-compiler/compiler.js +63 -0
- package/src/core/context-compiler/fingerprint.js +11 -0
- package/src/core/context-compiler/policy.js +13 -0
- package/src/core/context-compiler/result.js +23 -0
- package/src/core/continuity-lint.js +13 -2
- package/src/core/continuity-reconciliation.js +16 -3
- package/src/core/continuity.js +16 -8
- package/src/core/contract-bootstrap-recovery.js +656 -0
- package/src/core/contract-revision.js +209 -0
- package/src/core/decision/artifact.js +70 -0
- package/src/core/decision/benchmarks.js +103 -0
- package/src/core/decision/cache.js +27 -0
- package/src/core/decision/constants.js +58 -0
- package/src/core/decision/cutover.js +34 -0
- package/src/core/decision/engine.js +22 -0
- package/src/core/decision/errors.js +68 -0
- package/src/core/decision/events.js +104 -0
- package/src/core/decision/freshness.js +19 -0
- package/src/core/decision/normalizers/index.js +115 -0
- package/src/core/decision/policy.js +18 -0
- package/src/core/decision/projection.js +16 -0
- package/src/core/decision/question-registry.js +201 -0
- package/src/core/decision/request.js +26 -0
- package/src/core/decision/resolver.js +138 -0
- package/src/core/decision/result.js +58 -0
- package/src/core/decision/service.js +181 -0
- package/src/core/decision/state-builder.js +65 -0
- package/src/core/decision/task-bindings.js +35 -0
- package/src/core/decision/test-provider.js +32 -0
- package/src/core/decision/thresholds.js +15 -0
- package/src/core/diagnosis-model.js +11 -0
- package/src/core/diagnosis.js +10 -1
- package/src/core/diagnostic-projection.js +29 -12
- package/src/core/diagnostic-record.js +28 -3
- package/src/core/efficiency.js +6 -1
- package/src/core/error-codes.js +278 -0
- package/src/core/events.js +535 -147
- package/src/core/evidence-readiness.js +9 -0
- package/src/core/execution-prerequisites.js +36 -13
- package/src/core/execution-profile.js +63 -38
- package/src/core/execution.js +26 -40
- package/src/core/filesystem.js +11 -0
- package/src/core/gate-artifact.js +105 -19
- package/src/core/gate-provenance.js +125 -0
- package/src/core/handoff.js +26 -14
- package/src/core/history.js +39 -35
- package/src/core/hypothesis-projection.js +32 -0
- package/src/core/information-gain-projection.js +104 -100
- package/src/core/inspect.js +12 -3
- package/src/core/integration-invocation-policy.js +37 -4
- package/src/core/integration-resources.js +119 -87
- package/src/core/ledger-event-collection.js +189 -0
- package/src/core/ledger-relations.js +23 -0
- package/src/core/model-router/constants.js +10 -0
- package/src/core/model-router/policy.js +103 -0
- package/src/core/model-router/router.js +37 -0
- package/src/core/native-storage.js +12 -0
- package/src/core/next-action-continuity.js +31 -9
- package/src/core/next-action-model.js +58 -0
- package/src/core/next-action-phases.js +131 -43
- package/src/core/next-action-refresh.js +43 -9
- package/src/core/next-action-review-phase.js +9 -4
- package/src/core/next-action-verification-phase.js +2 -1
- package/src/core/next-action.js +56 -9
- package/src/core/phase.js +266 -103
- package/src/core/policy-engine.js +12 -13
- package/src/core/preflight-consistency.js +89 -62
- package/src/core/preflight-loaders.js +48 -9
- package/src/core/preflight-model.js +6 -1
- package/src/core/preflight.js +29 -12
- package/src/core/progress.js +21 -10
- package/src/core/protocol-info.js +68 -0
- package/src/core/protocol-migration.js +7 -6
- package/src/core/protocol.js +20 -0
- package/src/core/reconcile-closure.js +281 -67
- package/src/core/recovery-history.js +67 -47
- package/src/core/reflection.js +72 -77
- package/src/core/responsibility.js +25 -13
- package/src/core/resumability.js +154 -44
- package/src/core/route-artifact.js +28 -4
- package/src/core/router.js +67 -1
- package/src/core/runtime-context.js +123 -61
- package/src/core/schema-validation.js +11 -3
- package/src/core/security-review/constants.js +64 -0
- package/src/core/security-review/normalize.js +245 -0
- package/src/core/security-review/provider.js +204 -0
- package/src/core/security-review/service.js +134 -0
- package/src/core/semantic-planning/constants.js +19 -0
- package/src/core/semantic-planning/projection.js +94 -0
- package/src/core/semantic-planning/service.js +15 -0
- package/src/core/settlement.js +12 -1
- package/src/core/signing/bundle-file.js +53 -0
- package/src/core/signing/bundle-reference.js +15 -0
- package/src/core/signing/sigstore.js +60 -33
- package/src/core/signing/statement-file.js +27 -0
- package/src/core/sources.js +37 -0
- package/src/core/storage-runtime-registry.js +41 -0
- package/src/core/structural-quality/artifacts.js +20 -14
- package/src/core/structural-quality/service.js +81 -56
- package/src/core/target-layout.js +1 -1
- package/src/core/task-claim-state.js +249 -15
- package/src/core/task-command.js +21 -1
- package/src/core/task-conflict-inspection.js +133 -102
- package/src/core/task-descriptor.js +29 -22
- package/src/core/task-discovery.js +288 -90
- package/src/core/task-lock.js +66 -306
- package/src/core/task-migration-validation.js +5 -5
- package/src/core/task-migration.js +17 -287
- package/src/core/task-paths.js +13 -0
- package/src/core/task-recovery.js +1 -0
- package/src/core/task-snapshot.js +51 -8
- package/src/core/task-storage-migration.js +18 -0
- package/src/core/templates.js +23 -8
- package/src/core/test-intelligence/benchmarks.js +68 -0
- package/src/core/test-intelligence/inventory.js +73 -0
- package/src/core/test-intelligence/prune.js +94 -0
- package/src/core/test-intelligence/semantic-state.js +15 -0
- package/src/core/test-intelligence/service.js +40 -0
- package/src/core/test-intelligence/utility.js +50 -0
- package/src/core/trace.js +164 -105
- package/src/core/trajectory-evaluation.js +15 -3
- package/src/core/trajectory-metrics.js +47 -32
- package/src/core/transaction.js +16 -287
- package/src/core/verification-scope.js +20 -12
- package/src/core/work-state.js +100 -59
- package/src/integration.d.ts +492 -0
- package/src/integration.js +54 -0
- package/src/providers/README.md +47 -0
- package/src/providers/capabilities.js +46 -0
- package/src/providers/errors.js +15 -0
- package/src/providers/index.js +29 -0
- package/src/providers/json-snapshot.js +105 -0
- package/src/providers/registry.js +152 -0
- package/src/repository-index/binary-manager.js +7 -5
- package/src/storage/artifact-bytes.js +22 -0
- package/src/storage/attachment-binding.js +11 -0
- package/src/storage/attachment-files.js +82 -0
- package/src/storage/attachment-references.js +36 -0
- package/src/storage/backup.js +53 -0
- package/src/storage/capabilities.js +31 -0
- package/src/storage/connection-owner.js +119 -0
- package/src/storage/connection.js +376 -0
- package/src/storage/existing-project-scope.js +45 -0
- package/src/storage/export-destination.js +44 -0
- package/src/storage/exporter.js +284 -0
- package/src/storage/file-durability.js +46 -0
- package/src/storage/importer.js +461 -0
- package/src/storage/index.js +74 -0
- package/src/storage/leases.js +63 -0
- package/src/storage/ledger-event-snapshot.js +150 -0
- package/src/storage/ledger-relations.js +220 -0
- package/src/storage/legacy-maintenance-boundary.js +18 -0
- package/src/storage/legacy-signature.js +115 -0
- package/src/storage/maintenance-handoff.js +129 -0
- package/src/storage/maintenance-owner.js +42 -0
- package/src/storage/maintenance.js +310 -0
- package/src/storage/metadata-json.js +35 -0
- package/src/storage/migration-activate.js +59 -0
- package/src/storage/migration-archive.js +57 -0
- package/src/storage/migration-attachment-root.js +61 -0
- package/src/storage/migration-candidate.js +398 -0
- package/src/storage/migration-publication.js +143 -0
- package/src/storage/migration-rollback-admission.js +54 -0
- package/src/storage/migration-rollback-preparation.js +132 -0
- package/src/storage/migration-rollback-publication.js +183 -0
- package/src/storage/migration-rollback-release.js +66 -0
- package/src/storage/migration-rollback-source-stage.js +103 -0
- package/src/storage/migration-rollback.js +43 -0
- package/src/storage/migration-source-partition.js +56 -0
- package/src/storage/migration-source.js +255 -0
- package/src/storage/migration-terminal.js +39 -0
- package/src/storage/migration-validation.js +75 -0
- package/src/storage/migration.js +43 -0
- package/src/storage/operational-attachments.js +49 -0
- package/src/storage/operational-context.js +50 -0
- package/src/storage/project-backup.js +98 -0
- package/src/storage/project-bootstrap.js +24 -0
- package/src/storage/project-boundary.js +79 -0
- package/src/storage/project-read-snapshot.js +18 -0
- package/src/storage/project-replacement.js +137 -0
- package/src/storage/project-restore.js +203 -0
- package/src/storage/record-definitions.js +45 -0
- package/src/storage/repository.js +507 -0
- package/src/storage/restore-journal.js +62 -0
- package/src/storage/restore-layout.js +30 -0
- package/src/storage/restore-preparation.js +84 -0
- package/src/storage/restore-replacement-archive.js +162 -0
- package/src/storage/restore-replacement-owner.js +31 -0
- package/src/storage/restore-replacement-preparation.js +128 -0
- package/src/storage/restore-replacement.js +142 -0
- package/src/storage/restore-terminal.js +32 -0
- package/src/storage/runtime.js +31 -0
- package/src/storage/schema.js +214 -0
- package/src/storage/singleton-import.js +84 -0
- package/src/storage/snapshot-continuity.js +16 -0
- package/src/storage/snapshot.js +36 -0
- package/src/storage/storage-marker.js +79 -0
- package/src/storage/task-guards.js +107 -0
- package/src/storage/topology.js +42 -0
- package/src/storage/transaction.js +179 -0
- package/src/storage/unit-of-work.js +663 -0
- package/src/storage/windows-process-incarnation.js +206 -0
- package/.forgeloop/forgeloop.gitignore +0 -4
- package/LICENSE-DOCS.md +0 -13
- package/src/core/transaction-maintenance.js +0 -70
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { optionalConfig } from "../core/preflight-loaders.js";
|
|
2
|
+
import { readContract } from "../core/contract.js";
|
|
3
|
+
import { appendProtocolEvent, validateEventLedger, validateStateLedgerCoherence } from "../core/events.js";
|
|
4
|
+
import { assertSafePath, ensureWithin } from "../core/filesystem.js";
|
|
5
|
+
import { requiredGatesForGuides } from "../core/guide-metadata.js";
|
|
6
|
+
import { readPersistedRoute } from "../core/route-artifact.js";
|
|
7
|
+
import { staleReasons } from "../core/next-action-artifacts.js";
|
|
8
|
+
import { resolveTaskClaimState } from "../core/task-claim-state.js";
|
|
9
|
+
import { taskGatePath, taskArtifactPath } from "../core/task-paths.js";
|
|
10
|
+
import { withTaskMutation } from "../core/task-command.js";
|
|
11
|
+
import { readWorkState } from "../core/work-state.js";
|
|
12
|
+
import { stateIdentityErrors } from "../core/completion-relationships.js";
|
|
13
|
+
import { persistGate, readCanonicalGateArtifactBinding, hashGateFile, readGateIfPresent, validateGateArtifacts } from "../core/gate-artifact.js";
|
|
14
|
+
import {
|
|
15
|
+
GATE_REVALIDATED_EVENT,
|
|
16
|
+
assertGateRevalidatedDetails,
|
|
17
|
+
} from "../core/gate-provenance.js";
|
|
18
|
+
|
|
19
|
+
const POST_EXECUTION_PHASES = new Set([
|
|
20
|
+
"EXECUTING", "VERIFYING", "DIAGNOSING", "CORRECTING", "REVIEWING",
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
function revalidationError(message, code = "E_GATE_REVALIDATION_UNSAFE", artifacts = []) {
|
|
24
|
+
const error = new Error(message);
|
|
25
|
+
error.code = code;
|
|
26
|
+
error.artifacts = artifacts;
|
|
27
|
+
return error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function hashGateArtifact(target, relativePath) {
|
|
31
|
+
try {
|
|
32
|
+
ensureWithin(target, relativePath);
|
|
33
|
+
const canonical = readCanonicalGateArtifactBinding(target, relativePath);
|
|
34
|
+
if (canonical) {
|
|
35
|
+
await assertSafePath(target, relativePath);
|
|
36
|
+
if (canonical.sha256 === null) throw new Error("artifact is missing from canonical storage");
|
|
37
|
+
return { path: relativePath, sha256: canonical.sha256 };
|
|
38
|
+
}
|
|
39
|
+
const binding = await hashGateFile(target, relativePath);
|
|
40
|
+
return { path: relativePath, sha256: binding.sha256 };
|
|
41
|
+
} catch (cause) {
|
|
42
|
+
throw revalidationError(`Cannot refresh gate artifact ${relativePath}: ${cause.message}`, "E_GATE_REVALIDATION_UNSAFE", [relativePath]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function assertCurrentGateBinding(target, packageRoot, taskId, state, gate) {
|
|
47
|
+
const contract = await readContract(target, packageRoot, { taskId });
|
|
48
|
+
const route = await readPersistedRoute(target, packageRoot, { taskId });
|
|
49
|
+
const identityErrors = stateIdentityErrors({ contract, route, state });
|
|
50
|
+
if (identityErrors.length > 0) {
|
|
51
|
+
throw revalidationError(
|
|
52
|
+
"Gate revalidation requires coherent current contract, route, state, and selected guides",
|
|
53
|
+
"E_GATE_REVALIDATION_UNSAFE",
|
|
54
|
+
[taskArtifactPath(taskId, "contract"), taskArtifactPath(taskId, "route"), taskArtifactPath(taskId, "state")],
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const routeStale = staleReasons(state, contract, route);
|
|
58
|
+
if (routeStale.length > 0) {
|
|
59
|
+
throw revalidationError("Gate revalidation cannot repair stale contract or route identity", "E_GATE_REVALIDATION_UNSAFE", routeStale.flatMap((reason) => reason.artifacts));
|
|
60
|
+
}
|
|
61
|
+
const config = await optionalConfig(target, packageRoot, []);
|
|
62
|
+
const required = [...new Set([
|
|
63
|
+
...(await requiredGatesForGuides(route.value.guides, packageRoot)),
|
|
64
|
+
...(config.requiredGates ?? []),
|
|
65
|
+
])];
|
|
66
|
+
if (!required.includes(gate)) {
|
|
67
|
+
throw revalidationError(`Gate is not required by the active route: ${gate}`, "E_GATE_NOT_REQUIRED", [taskArtifactPath(taskId, "route")]);
|
|
68
|
+
}
|
|
69
|
+
return { contract, route };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function runGateRevalidate({ target, packageRoot, taskId, gate, acknowledgeStale = false } = {}) {
|
|
73
|
+
if (!acknowledgeStale) {
|
|
74
|
+
throw revalidationError("gate-revalidate requires --acknowledge-stale", "E_GATE_REVALIDATION_ACK_REQUIRED");
|
|
75
|
+
}
|
|
76
|
+
if (typeof gate !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(gate)) {
|
|
77
|
+
throw revalidationError(`Invalid gate name: ${gate}`, "E_GATE_INVALID");
|
|
78
|
+
}
|
|
79
|
+
return withTaskMutation(target, { taskId, packageRoot }, "gate-revalidate", async (ctx) => {
|
|
80
|
+
const state = await readWorkState(target, { packageRoot, taskId: ctx.taskId });
|
|
81
|
+
if (!state || !POST_EXECUTION_PHASES.has(state.phase)) {
|
|
82
|
+
throw revalidationError(
|
|
83
|
+
`gate-revalidate is only available for post-execution repair phases; found ${state?.phase ?? "no phase"}`,
|
|
84
|
+
"E_GATE_REVALIDATION_PHASE_INVALID",
|
|
85
|
+
[taskArtifactPath(ctx.taskId, "state")],
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
const ledger = await validateEventLedger(target, packageRoot, { taskId: ctx.taskId });
|
|
89
|
+
if (!ledger.valid) throw revalidationError("Gate revalidation requires a valid append-only event ledger", "E_EVENT_INVALID", ledger.errors);
|
|
90
|
+
const coherenceErrors = validateStateLedgerCoherence(state, ledger.events);
|
|
91
|
+
if (coherenceErrors.length > 0) throw revalidationError("Gate revalidation requires coherent state and ledger", "E_PHASE_CHRONOLOGY_INVALID", coherenceErrors);
|
|
92
|
+
const ownership = await resolveTaskClaimState(target, { taskId: ctx.taskId, packageRoot });
|
|
93
|
+
if (!ownership.ownershipValid || !ownership.mutationAllowed || ownership.claimState !== "ACTIVE") {
|
|
94
|
+
throw revalidationError("Gate revalidation cannot bypass active task claim ownership", "E_TASK_CLAIM_OWNERSHIP_INCONSISTENT", ownership.ownershipErrors);
|
|
95
|
+
}
|
|
96
|
+
await assertCurrentGateBinding(target, packageRoot, ctx.taskId, state, gate);
|
|
97
|
+
const existing = await readGateIfPresent(target, gate, packageRoot, { taskId: ctx.taskId });
|
|
98
|
+
if (!existing || existing.value.status !== "satisfied") {
|
|
99
|
+
throw revalidationError("Only an existing satisfied gate can be revalidated", "E_GATE_UNVERIFIED", [taskGatePath(ctx.taskId, gate)]);
|
|
100
|
+
}
|
|
101
|
+
const stale = await validateGateArtifacts(target, existing.value, packageRoot);
|
|
102
|
+
if (stale.length === 0) {
|
|
103
|
+
throw revalidationError("Gate artifacts are already fresh; no revalidation event is required", "E_GATE_REVALIDATION_NOT_STALE", [existing.path]);
|
|
104
|
+
}
|
|
105
|
+
const refreshedArtifacts = [];
|
|
106
|
+
for (const artifact of existing.value.artifacts ?? []) refreshedArtifacts.push(await hashGateArtifact(target, artifact.path));
|
|
107
|
+
const refreshedGate = { ...existing.value, artifacts: refreshedArtifacts };
|
|
108
|
+
const persisted = await persistGate(target, refreshedGate, packageRoot, { taskId: ctx.taskId });
|
|
109
|
+
const details = {
|
|
110
|
+
gate,
|
|
111
|
+
previousGateFingerprint: existing.fingerprint,
|
|
112
|
+
gateFingerprint: persisted.fingerprint,
|
|
113
|
+
stalePaths: stale.map((entry) => entry.path).sort(),
|
|
114
|
+
};
|
|
115
|
+
assertGateRevalidatedDetails(details);
|
|
116
|
+
const event = await appendProtocolEvent(target, {
|
|
117
|
+
taskId: ctx.taskId,
|
|
118
|
+
event: GATE_REVALIDATED_EVENT,
|
|
119
|
+
details,
|
|
120
|
+
}, packageRoot, { taskId: ctx.taskId });
|
|
121
|
+
return {
|
|
122
|
+
taskId: ctx.taskId,
|
|
123
|
+
gate,
|
|
124
|
+
stalePaths: details.stalePaths,
|
|
125
|
+
gateFingerprint: persisted.fingerprint,
|
|
126
|
+
eventSeq: event.seq,
|
|
127
|
+
transactionCommitSeq: event.seq + 1,
|
|
128
|
+
path: persisted.path ?? persisted.relativePath ?? taskGatePath(ctx.taskId, gate),
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function formatGateRevalidateResult(result) {
|
|
134
|
+
return `${JSON.stringify(result, null, 2)}\n`;
|
|
135
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
1
2
|
import { listCanonicalHandoffs } from "../core/handoff.js";
|
|
2
3
|
import {
|
|
3
4
|
readHandoffAcceptanceLedger,
|
|
4
5
|
resolveHandoffAcceptance,
|
|
5
6
|
} from "../core/handoff-acceptance.js";
|
|
6
7
|
|
|
7
|
-
export async function runHandoffList(
|
|
8
|
+
export async function runHandoffList(options = {}) {
|
|
9
|
+
return withProjectReadSnapshot(options.target, () => projectHandoffList(options));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function projectHandoffList({ target, packageRoot, taskId } = {}) {
|
|
8
13
|
const handoffs = await listCanonicalHandoffs(target, { packageRoot, taskId });
|
|
9
14
|
const ledger = await readHandoffAcceptanceLedger(target, packageRoot, { taskId });
|
|
10
15
|
const handoffsWithAcceptance = handoffs.map((handoff) => {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
1
2
|
import { readCanonicalHandoff } from "../core/handoff.js";
|
|
2
3
|
import {
|
|
3
4
|
readHandoffAcceptanceLedger,
|
|
4
5
|
resolveHandoffAcceptance,
|
|
5
6
|
} from "../core/handoff-acceptance.js";
|
|
6
7
|
|
|
7
|
-
export async function runHandoffShow(
|
|
8
|
+
export async function runHandoffShow(options = {}) {
|
|
9
|
+
return withProjectReadSnapshot(options.target, () => projectHandoffShow(options));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function projectHandoffShow({ target, packageRoot, taskId, handoffId } = {}) {
|
|
8
13
|
const artifact = await readCanonicalHandoff(target, { packageRoot, taskId, handoffId });
|
|
9
14
|
const ledger = await readHandoffAcceptanceLedger(target, packageRoot, { taskId });
|
|
10
15
|
const resolved = resolveHandoffAcceptance({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { migrateProtocol } from "../core/protocol-migration.js";
|
|
2
2
|
|
|
3
|
-
export async function runMigrateProtocol({ target, packageRoot, to, dryRun = false } = {}) {
|
|
4
|
-
return migrateProtocol(target, { to, dryRun, packageRoot });
|
|
3
|
+
export async function runMigrateProtocol({ target, packageRoot, to, dryRun = false, destination, writersQuiesced = false } = {}) {
|
|
4
|
+
return migrateProtocol(target, { to, dryRun, packageRoot, destination, writersQuiesced });
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export function formatMigrateProtocolResult(result) {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { projectModelRoute } from "../core/model-router/router.js";
|
|
2
|
+
import { resolveRequiredSemanticDecision } from "../core/decision/resolver.js";
|
|
3
|
+
import { readCurrentDecisionBindings } from "../core/decision/task-bindings.js";
|
|
4
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
5
|
+
|
|
6
|
+
export async function runModelRoute(options = {}) {
|
|
7
|
+
if (options.target && options.taskId) return withProjectReadSnapshot(options.target, () => projectSnapshotModelRoute(options));
|
|
8
|
+
return projectSnapshotModelRoute(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async function projectSnapshotModelRoute({ target, packageRoot, taskId, decisionId, workType, surfaces, risks, platforms, behaviorChange, executableChange, generationRequired, architectureChange, ambiguity, semanticRecommendation, contract }) {
|
|
12
|
+
if (target && taskId) {
|
|
13
|
+
const bindings = await readCurrentDecisionBindings(target, packageRoot, taskId);
|
|
14
|
+
// Decision stateFingerprint includes semantic inputs; this reader proves the lifecycle via taskStateFingerprint.
|
|
15
|
+
delete bindings.stateFingerprint;
|
|
16
|
+
const decision = await resolveRequiredSemanticDecision({
|
|
17
|
+
target, packageRoot, taskId, decisionId, decisionKind: "MODEL_ROUTE", currentBindings: bindings,
|
|
18
|
+
});
|
|
19
|
+
semanticRecommendation = decision.decision;
|
|
20
|
+
}
|
|
21
|
+
return projectModelRoute({
|
|
22
|
+
input: {
|
|
23
|
+
workType,
|
|
24
|
+
surfaces,
|
|
25
|
+
risks,
|
|
26
|
+
platforms,
|
|
27
|
+
behaviorChange,
|
|
28
|
+
executableChange,
|
|
29
|
+
generationRequired,
|
|
30
|
+
architectureChange,
|
|
31
|
+
ambiguity,
|
|
32
|
+
contract,
|
|
33
|
+
},
|
|
34
|
+
semanticRecommendation,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function formatModelRouteResult(result) {
|
|
39
|
+
return `${JSON.stringify(result, null, 2)}\n`;
|
|
40
|
+
}
|
package/src/commands/next.js
CHANGED
|
@@ -3,8 +3,14 @@ import { withResolvedTask } from "../core/task-command.js";
|
|
|
3
3
|
import { readPersistedRoute } from "../core/route-artifact.js";
|
|
4
4
|
import { projectExecutionProfile } from "../core/execution-profile.js";
|
|
5
5
|
import { explainNextAction } from "../core/next-explanation.js";
|
|
6
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
6
7
|
|
|
7
|
-
export async function runNext(
|
|
8
|
+
export async function runNext(options) {
|
|
9
|
+
const read = () => projectNext(options);
|
|
10
|
+
return options.target ? withProjectReadSnapshot(options.target, read) : read();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function projectNext({ target, packageRoot, taskId, task, authorityContext, runtimeContext, compact = false, explain = false }) {
|
|
8
14
|
return withResolvedTask(target, { taskId: taskId ?? task, packageRoot }, async (ctx) => {
|
|
9
15
|
const result = await getNextAction({
|
|
10
16
|
target,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { isOperationalArtifactPath, needsExistingProjectScope, withExistingProjectScope } from "../storage/existing-project-scope.js";
|
|
4
|
+
import { getOperationalStore, readOperationalText } from "../storage/operational-context.js";
|
|
3
5
|
import { diffPolicies } from "../core/policy-diff.js";
|
|
4
6
|
import {
|
|
5
7
|
loadEffectiveRules,
|
|
@@ -7,6 +9,23 @@ import {
|
|
|
7
9
|
readTaskPolicySnapshot,
|
|
8
10
|
} from "../core/policy-engine.js";
|
|
9
11
|
|
|
12
|
+
function canonicalInputPath(target, file) {
|
|
13
|
+
return path.relative(target, path.resolve(target, file)).replaceAll("\\", "/");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function readPolicyInput(target, file) {
|
|
17
|
+
const relative = canonicalInputPath(target, file);
|
|
18
|
+
const native = readOperationalText(target, relative);
|
|
19
|
+
if (native.selected) {
|
|
20
|
+
if (native.text === null) throw Object.assign(new Error(`Policy input does not exist: ${relative}`), { code: "ENOENT" });
|
|
21
|
+
return JSON.parse(native.text);
|
|
22
|
+
}
|
|
23
|
+
if (getOperationalStore(target) && isOperationalArtifactPath(relative)) {
|
|
24
|
+
throw Object.assign(new Error(`Unsupported canonical policy input: ${relative}`), { code: "E_STORAGE_OPERATION_UNSUPPORTED" });
|
|
25
|
+
}
|
|
26
|
+
return JSON.parse(await readFile(path.resolve(target, file), "utf8"));
|
|
27
|
+
}
|
|
28
|
+
|
|
10
29
|
export async function runPolicyDiff({
|
|
11
30
|
target = process.cwd(),
|
|
12
31
|
packageRoot,
|
|
@@ -14,12 +33,15 @@ export async function runPolicyDiff({
|
|
|
14
33
|
before = null,
|
|
15
34
|
after = null,
|
|
16
35
|
} = {}) {
|
|
36
|
+
if ([before, after].some(file => file && isOperationalArtifactPath(canonicalInputPath(target, file)))
|
|
37
|
+
&& await needsExistingProjectScope(target)) {
|
|
38
|
+
return withExistingProjectScope(target, () => runPolicyDiff({ target, packageRoot, taskId, before, after }), { readOnly: true });
|
|
39
|
+
}
|
|
17
40
|
let beforePolicy;
|
|
18
41
|
let afterPolicy;
|
|
19
42
|
|
|
20
43
|
if (before) {
|
|
21
|
-
|
|
22
|
-
beforePolicy = JSON.parse(rawBefore);
|
|
44
|
+
beforePolicy = await readPolicyInput(target, before);
|
|
23
45
|
} else if (taskId) {
|
|
24
46
|
const snapshot = await readTaskPolicySnapshot(target, taskId, packageRoot);
|
|
25
47
|
beforePolicy = snapshot ? { rules: snapshot.rules, baseline: { entries: [] } } : { rules: [], baseline: { entries: [] } };
|
|
@@ -28,8 +50,7 @@ export async function runPolicyDiff({
|
|
|
28
50
|
}
|
|
29
51
|
|
|
30
52
|
if (after) {
|
|
31
|
-
|
|
32
|
-
afterPolicy = JSON.parse(rawAfter);
|
|
53
|
+
afterPolicy = await readPolicyInput(target, after);
|
|
33
54
|
} else {
|
|
34
55
|
const rules = await loadEffectiveRules(target, packageRoot);
|
|
35
56
|
const baseline = await readBaseline(target, packageRoot);
|
package/src/commands/progress.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { evaluateProgress, PROGRESS_STATUS } from "../core/progress.js";
|
|
2
|
-
import {
|
|
2
|
+
import { withEventLedgerAudit } from "../core/events.js";
|
|
3
3
|
import { readWorkState } from "../core/work-state.js";
|
|
4
4
|
import { resolveTaskContext, TASK_SELECTION_MODES } from "../core/task-context.js";
|
|
5
5
|
|
|
@@ -13,16 +13,22 @@ export async function runProgress({ target, packageRoot, taskId, task }) {
|
|
|
13
13
|
});
|
|
14
14
|
const activeTaskId = resolved.taskId;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
return withEventLedgerAudit(target, packageRoot, { taskId: activeTaskId }, async ledger => {
|
|
17
|
+
if (!ledger.valid) {
|
|
18
|
+
const first = ledger.errors[0] ?? { code: "E_LEDGER_INVALID", message: "Progress requires a valid event ledger" };
|
|
19
|
+
throw Object.assign(new Error(first.message), { code: first.code });
|
|
20
|
+
}
|
|
21
|
+
const state = await readWorkState(target, { packageRoot, taskId: activeTaskId });
|
|
22
|
+
const events = ledger.events;
|
|
23
|
+
|
|
24
|
+
const progress = evaluateProgress({ state, events });
|
|
25
|
+
return {
|
|
26
|
+
taskId: activeTaskId ?? state?.taskId ?? "unknown",
|
|
27
|
+
phase: state?.phase ?? "UNKNOWN",
|
|
28
|
+
verificationCycle: state?.verificationCycle ?? 1,
|
|
29
|
+
...progress,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
export function formatProgressResult(result) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertCanonicalPersistence } from "../storage/operational-context.js";
|
|
1
2
|
import { recordDiagnosis } from "../core/diagnosis.js";
|
|
2
3
|
import { recordStructuredDiagnosticCase } from "../core/diagnostic-record.js";
|
|
3
4
|
import { withTaskMutation } from "../core/task-command.js";
|
|
@@ -16,7 +17,9 @@ export async function runRecordDiagnosis({
|
|
|
16
17
|
nextSafeAction,
|
|
17
18
|
taskId,
|
|
18
19
|
task,
|
|
20
|
+
persistence = null,
|
|
19
21
|
}) {
|
|
22
|
+
assertCanonicalPersistence(persistence);
|
|
20
23
|
if (file) {
|
|
21
24
|
const legacyFields = [hypothesis, failureClass, settledBy, nextSafeAction].some((value) => value !== undefined && value !== null)
|
|
22
25
|
|| (Array.isArray(evidenceRefs) && evidenceRefs.length > 0)
|
package/src/commands/route.js
CHANGED
|
@@ -1,13 +1,104 @@
|
|
|
1
1
|
import { evaluateRoute } from "../core/router.js";
|
|
2
|
-
import { persistRoute } from "../core/route-artifact.js";
|
|
2
|
+
import { persistRoute, readPersistedRoute } from "../core/route-artifact.js";
|
|
3
3
|
import { readContract } from "../core/contract.js";
|
|
4
4
|
import { readConfig } from "../core/config.js";
|
|
5
|
+
import { appendProtocolEvent, readEvents } from "../core/events.js";
|
|
5
6
|
import { detectProjectEvidence } from "../core/project-detection.js";
|
|
6
|
-
import { withTaskMutation } from "../core/task-command.js";
|
|
7
|
+
import { withResolvedTask, withTaskMutation } from "../core/task-command.js";
|
|
8
|
+
import { advanceWorkState } from "../core/phase.js";
|
|
9
|
+
import { mutateWorkState, readWorkState } from "../core/work-state.js";
|
|
10
|
+
import { buildExecutionProfileQuestionSet, buildRouteQuestionSet } from "../core/decision/question-registry.js";
|
|
11
|
+
import { ensureSemanticDecision } from "../core/decision/service.js";
|
|
12
|
+
import { canonicalFingerprint } from "../core/artifacts.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveEffectiveContractBootstrapRepairAnchor,
|
|
15
|
+
} from "../core/contract-bootstrap-recovery.js";
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
function canAppendRepairedRouteWitness({ stateBefore, marker, previousPersistedRouteFingerprint, persistedRoute }) {
|
|
18
|
+
if (previousPersistedRouteFingerprint === null) {
|
|
19
|
+
return stateBefore.phase === "CONTRACT_READY"
|
|
20
|
+
&& marker.details.reconstructedPhase === "CONTRACT_READY"
|
|
21
|
+
&& marker.details.routeFingerprint === null;
|
|
22
|
+
}
|
|
23
|
+
return persistedRoute.fingerprint !== previousPersistedRouteFingerprint
|
|
24
|
+
&& persistedRoute.value.contractFingerprint === marker.details.contractFingerprint;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function canAppendCanonicalRouteWitness({ stateBefore, previousPersistedRouteFingerprint, persistedRoute }) {
|
|
28
|
+
return stateBefore?.phase === "ROUTED"
|
|
29
|
+
&& previousPersistedRouteFingerprint !== null
|
|
30
|
+
&& persistedRoute.fingerprint !== previousPersistedRouteFingerprint
|
|
31
|
+
&& stateBefore.contractFingerprint === persistedRoute.value.contractFingerprint;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function appendRouteWitness({ target, packageRoot, taskId, stateBefore, previousPersistedRouteFingerprint, persistedRoute }) {
|
|
35
|
+
if (!stateBefore) return;
|
|
36
|
+
const events = await readEvents(target, packageRoot, { taskId });
|
|
37
|
+
const anchor = resolveEffectiveContractBootstrapRepairAnchor(events);
|
|
38
|
+
const canAppend = anchor
|
|
39
|
+
? canAppendRepairedRouteWitness({
|
|
40
|
+
stateBefore,
|
|
41
|
+
marker: anchor.sourceMarker,
|
|
42
|
+
previousPersistedRouteFingerprint,
|
|
43
|
+
persistedRoute,
|
|
44
|
+
})
|
|
45
|
+
: canAppendCanonicalRouteWitness({ stateBefore, previousPersistedRouteFingerprint, persistedRoute });
|
|
46
|
+
if (!canAppend) return;
|
|
47
|
+
await appendProtocolEvent(target, {
|
|
48
|
+
taskId,
|
|
49
|
+
event: "ROUTE_REBOUND",
|
|
50
|
+
details: {
|
|
51
|
+
routeFingerprint: persistedRoute.fingerprint,
|
|
52
|
+
contractFingerprint: persistedRoute.value.contractFingerprint,
|
|
53
|
+
previousRouteFingerprint: previousPersistedRouteFingerprint,
|
|
54
|
+
},
|
|
55
|
+
}, packageRoot, { taskId });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function persistRoutedState({ target, packageRoot, taskId, route, transaction }) {
|
|
59
|
+
const stateBefore = await readWorkState(target, { packageRoot, taskId });
|
|
60
|
+
let previousPersistedRouteFingerprint = null;
|
|
61
|
+
try {
|
|
62
|
+
previousPersistedRouteFingerprint = (await readPersistedRoute(target, packageRoot, { taskId })).fingerprint;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (error.code !== "ARTIFACT_MISSING") throw error;
|
|
65
|
+
}
|
|
66
|
+
let contractFingerprint;
|
|
67
|
+
try {
|
|
68
|
+
contractFingerprint = (await readContract(target, packageRoot, { taskId })).fingerprint;
|
|
69
|
+
} catch {
|
|
70
|
+
contractFingerprint = undefined;
|
|
71
|
+
}
|
|
72
|
+
const persistedRoute = await persistRoute(target, route, packageRoot, { contractFingerprint, taskId });
|
|
73
|
+
const state = await readWorkState(target, { packageRoot, taskId });
|
|
74
|
+
if (state?.phase === "CONTRACT_READY") {
|
|
75
|
+
await mutateWorkState(target, {
|
|
76
|
+
packageRoot,
|
|
77
|
+
taskId,
|
|
78
|
+
expectedRevision: state.revision ?? 0,
|
|
79
|
+
}, () => ({
|
|
80
|
+
...state,
|
|
81
|
+
routeFingerprint: persistedRoute.fingerprint,
|
|
82
|
+
selectedGuides: [...persistedRoute.value.guides],
|
|
83
|
+
}));
|
|
84
|
+
await advanceWorkState(target, "ROUTED", { packageRoot, taskId });
|
|
85
|
+
}
|
|
86
|
+
if (transaction?.operation === "route") {
|
|
87
|
+
await appendRouteWitness({
|
|
88
|
+
target,
|
|
89
|
+
packageRoot,
|
|
90
|
+
taskId,
|
|
91
|
+
stateBefore,
|
|
92
|
+
previousPersistedRouteFingerprint,
|
|
93
|
+
persistedRoute,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function runRoute({ target, packageRoot, workType, surfaces, risks, platforms, behaviorChange, executableChange, executionProfile = null, taskId, task, semanticProvider = null, provider = null }) {
|
|
99
|
+
return withResolvedTask(target, { taskId: taskId ?? task, packageRoot }, async (context) => {
|
|
100
|
+
const effectiveTaskId = context?.taskId ?? null;
|
|
101
|
+
const effectiveSemanticProvider = semanticProvider ?? provider;
|
|
11
102
|
let contract = null;
|
|
12
103
|
try {
|
|
13
104
|
contract = (await readContract(target, packageRoot, { taskId: effectiveTaskId })).value;
|
|
@@ -21,9 +112,9 @@ export async function runRoute({ target, packageRoot, workType, surfaces, risks,
|
|
|
21
112
|
if (error.code !== "ARTIFACT_MISSING") throw error;
|
|
22
113
|
}
|
|
23
114
|
const projectEvidence = target
|
|
24
|
-
? await detectProjectEvidence(target, { claims:
|
|
115
|
+
? await detectProjectEvidence(target, { claims: context?.descriptor?.writeClaims ?? [] })
|
|
25
116
|
: null;
|
|
26
|
-
const
|
|
117
|
+
const routeInput = {
|
|
27
118
|
workType,
|
|
28
119
|
surfaces,
|
|
29
120
|
risks,
|
|
@@ -31,22 +122,59 @@ export async function runRoute({ target, packageRoot, workType, surfaces, risks,
|
|
|
31
122
|
behaviorChange,
|
|
32
123
|
executableChange,
|
|
33
124
|
...(projectEvidence ? { projectEvidence } : {}),
|
|
34
|
-
}
|
|
125
|
+
};
|
|
126
|
+
const deterministicRoute = evaluateRoute(routeInput, {
|
|
35
127
|
contract,
|
|
36
|
-
taskDescriptor:
|
|
128
|
+
taskDescriptor: context?.descriptor ?? null,
|
|
37
129
|
configuredProfile,
|
|
38
130
|
requestedProfile: executionProfile,
|
|
39
131
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
132
|
+
let semanticRecommendation = null;
|
|
133
|
+
if (target && packageRoot && effectiveTaskId) {
|
|
134
|
+
await ensureSemanticDecision({
|
|
135
|
+
target, packageRoot, taskId: effectiveTaskId, provider: effectiveSemanticProvider,
|
|
136
|
+
request: { decisionKind: "INTAKE", questionSetId: "intake-v1", state: { routeInput: deterministicRoute.input } },
|
|
137
|
+
});
|
|
138
|
+
const questionSet = buildRouteQuestionSet(deterministicRoute.guides);
|
|
139
|
+
const routeDecision = await ensureSemanticDecision({
|
|
140
|
+
target, packageRoot, taskId: effectiveTaskId, provider: effectiveSemanticProvider,
|
|
141
|
+
request: {
|
|
142
|
+
decisionKind: "ROUTE", questionSetId: questionSet.id, questionSet,
|
|
143
|
+
state: { routeInput: deterministicRoute.input, eligibleGuides: deterministicRoute.guides.map((guide) => ({ id: guide, reasons: deterministicRoute.reasons[guide] })) },
|
|
144
|
+
candidateIds: deterministicRoute.guides,
|
|
145
|
+
candidateSetFingerprint: canonicalFingerprint(deterministicRoute.guides),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
const profileQuestionSet = buildExecutionProfileQuestionSet();
|
|
149
|
+
const profileDecision = await ensureSemanticDecision({
|
|
150
|
+
target, packageRoot, taskId: effectiveTaskId, provider: effectiveSemanticProvider,
|
|
151
|
+
request: {
|
|
152
|
+
decisionKind: "EXECUTION_PROFILE", questionSetId: profileQuestionSet.id, questionSet: profileQuestionSet,
|
|
153
|
+
state: {
|
|
154
|
+
routeInput: deterministicRoute.input,
|
|
155
|
+
deterministicFloor: deterministicRoute.executionProfile.floor,
|
|
156
|
+
requestedProfile: deterministicRoute.executionProfile.requested,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
semanticRecommendation = {
|
|
161
|
+
guideRelevance: routeDecision.artifact.decision,
|
|
162
|
+
executionProfile: profileDecision.artifact.decision,
|
|
163
|
+
};
|
|
48
164
|
}
|
|
49
|
-
|
|
165
|
+
const route = evaluateRoute(routeInput, {
|
|
166
|
+
contract,
|
|
167
|
+
taskDescriptor: context?.descriptor ?? null,
|
|
168
|
+
configuredProfile,
|
|
169
|
+
requestedProfile: executionProfile,
|
|
170
|
+
semanticRecommendation,
|
|
171
|
+
});
|
|
172
|
+
return withTaskMutation(target, { taskId: effectiveTaskId, packageRoot }, "route", async (ctx) => {
|
|
173
|
+
if (target && packageRoot) {
|
|
174
|
+
await persistRoutedState({ target, packageRoot, taskId: effectiveTaskId, route, transaction: ctx?.transaction });
|
|
175
|
+
}
|
|
176
|
+
return route;
|
|
177
|
+
});
|
|
50
178
|
});
|
|
51
179
|
}
|
|
52
180
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { runSemanticPlan as projectPlan } from "../core/semantic-planning/service.js";
|
|
2
|
+
import { resolveRequiredSemanticDecision } from "../core/decision/resolver.js";
|
|
3
|
+
import { readCurrentDecisionBindings } from "../core/decision/task-bindings.js";
|
|
4
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
5
|
+
|
|
6
|
+
const PROJECTION_VALUES = Object.freeze({
|
|
7
|
+
failure: Object.freeze({ implementation: "incorrect implementation", expectation: "stale expectation",
|
|
8
|
+
state: "state divergence", dependency: "dependency incompatibility", environment: "network/environment" }),
|
|
9
|
+
diagnosis: Object.freeze({ inspect_state: "inspect state transition", inspect_caller: "inspect caller",
|
|
10
|
+
inspect_dependency: "inspect dependency behavior", narrow_experiment: "run narrower experiment" }),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
function projectionRecommendation(kind, decision) {
|
|
14
|
+
const values = PROJECTION_VALUES[kind];
|
|
15
|
+
if (!values) return decision;
|
|
16
|
+
const field = kind === "failure" ? "failureClass" : "priority";
|
|
17
|
+
const value = decision[field];
|
|
18
|
+
if (value === "unknown") return null;
|
|
19
|
+
return { ...decision, [field]: Object.hasOwn(values, value) ? values[value] : value };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function runSemanticPlan(options = {}) {
|
|
23
|
+
if (options.target && options.taskId) return withProjectReadSnapshot(options.target, () => projectSnapshotSemanticPlan(options));
|
|
24
|
+
return projectSnapshotSemanticPlan(options);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function projectSnapshotSemanticPlan({ target, packageRoot, taskId, decisionId, kind, input, semanticRecommendation }) {
|
|
28
|
+
if (target && taskId) {
|
|
29
|
+
const decisionKind = { failure: "FAILURE_TRIAGE", diagnosis: "DIAGNOSIS_PRIORITY", review: "REVIEW_PLAN" }[kind];
|
|
30
|
+
const bindings = await readCurrentDecisionBindings(target, packageRoot, taskId);
|
|
31
|
+
// Decision stateFingerprint includes semantic inputs; this reader proves the lifecycle via taskStateFingerprint.
|
|
32
|
+
delete bindings.stateFingerprint;
|
|
33
|
+
const decision = await resolveRequiredSemanticDecision({ target, packageRoot, taskId, decisionId, decisionKind, currentBindings: bindings });
|
|
34
|
+
semanticRecommendation = projectionRecommendation(kind, decision.decision);
|
|
35
|
+
}
|
|
36
|
+
return projectPlan({ kind, input, semanticRecommendation });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function formatSemanticPlanResult(result) {
|
|
40
|
+
return `${JSON.stringify(result, null, 2)}\n`;
|
|
41
|
+
}
|
package/src/commands/status.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { withProjectReadSnapshot } from "../storage/project-read-snapshot.js";
|
|
1
2
|
import { readAndClassifyWorkState } from "../core/work-state.js";
|
|
2
3
|
import { inspectSchemaHealth } from "../core/schema-validation.js";
|
|
3
4
|
import { reconcileContinuity } from "../core/continuity-reconciliation.js";
|
|
4
5
|
import { withResolvedTask } from "../core/task-command.js";
|
|
5
6
|
import { findTaskById } from "../core/task-discovery.js";
|
|
6
7
|
|
|
7
|
-
export async function runStatus(
|
|
8
|
+
export async function runStatus(options = {}) {
|
|
9
|
+
return withProjectReadSnapshot(options.target, () => runSelectedStatus(options));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function runSelectedStatus({ target, packageRoot, contractFile = null, taskId, task } = {}) {
|
|
8
13
|
return withResolvedTask(target, { taskId: taskId ?? task, packageRoot }, async (ctx) => {
|
|
9
14
|
const effectiveTaskId = ctx?.taskId ?? null;
|
|
10
15
|
const state = await readAndClassifyWorkState({ target, packageRoot, contractFile, taskId: effectiveTaskId });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getOperationalStore } from "../storage/operational-context.js";
|
|
2
|
+
import { assertSafePath } from "../core/filesystem.js";
|
|
3
|
+
|
|
4
|
+
export async function runStorageBackup({ target, destination, includeAttachments = false } = {}) {
|
|
5
|
+
if (typeof destination !== "string" || !destination) throw Object.assign(new Error("storage-backup requires --destination"), { code: "E_CLI_INVOCATION_INVALID" });
|
|
6
|
+
const store = getOperationalStore(target);
|
|
7
|
+
if (!store) throw Object.assign(new Error("storage-backup requires an explicitly migrated SQLite project"), { code: "E_STORAGE_MIGRATION_REQUIRED" });
|
|
8
|
+
const filename = await assertSafePath(target, destination);
|
|
9
|
+
if (includeAttachments) {
|
|
10
|
+
const { backupProjectStorage } = await import("../storage/project-backup.js");
|
|
11
|
+
return backupProjectStorage(store.db, target, filename);
|
|
12
|
+
}
|
|
13
|
+
const { backupStorageDatabase } = await import("../storage/backup.js");
|
|
14
|
+
return backupStorageDatabase(store.db, filename);
|
|
15
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { resumeProjectStorageMigration } from "../storage/migration.js";
|
|
2
|
+
|
|
3
|
+
export async function runStorageMigrationResume({ target, destination, expectedOwnerId, writersQuiesced = false, acknowledgeUnboundHandoff = false, packageRoot } = {}) {
|
|
4
|
+
return resumeProjectStorageMigration(target, { destination, expectedOwnerId, writersQuiesced, acknowledgeUnboundHandoff, packageRoot });
|
|
5
|
+
}
|