@cassiomc1/forgeloop 1.12.0 → 1.14.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/.github/copilot-instructions.md +1 -1
- package/AGENTS.md +1 -1
- package/AGENT_COMPATIBILITY.md +8 -0
- package/CLAUDE.md +1 -1
- package/CONTRIBUTING.md +90 -0
- package/DOCS_INDEX.md +46 -12
- package/ENG/c-development-eng.md +112 -0
- package/ENG/cpp-development-eng.md +109 -0
- package/ENG/dotnet-aspnetcore-development-eng.md +401 -0
- package/ENG/go-development-eng.md +103 -0
- package/ENG/java-development-eng.md +125 -0
- package/ENG/nodejs-backend-development-eng.md +605 -0
- package/ENG/php-development-eng.md +104 -0
- package/ENG/rust-development-eng.md +422 -0
- package/ENG/sec-code-eng.md +7 -7
- package/ENG/sql-development-eng.md +108 -0
- package/ENG/swift-development-eng.md +111 -0
- package/ENG/typescript-development-eng.md +108 -0
- package/EXECUTION_STATE.md +12 -0
- package/GUIDE_ROUTER.md +418 -9
- package/LOOP_ENGINEERING.md +28 -2
- package/ORCHESTRATOR_INTEGRATION.md +9 -5
- package/PROTOCOL_INTEGRATION.md +55 -2
- package/QUALITY_SCORECARD.md +1 -0
- package/README.md +78 -52
- package/TERMINOLOGY.md +2 -0
- package/THIRD_PARTY_NOTICES.md +19 -7
- package/THREAT_MODEL.md +140 -1
- package/completions/_forgeloop +22 -4
- package/completions/forgeloop.bash +40 -4
- package/completions/forgeloop.fish +130 -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 +81 -3
- package/docs/AGENT_SKILL.md +66 -0
- package/docs/ARTIFACT_REFERENCE.md +123 -0
- package/docs/AUDIT_UX.md +46 -0
- package/docs/BROWSER_VERIFICATION.md +136 -0
- package/docs/CLI_REFERENCE.md +392 -10
- package/docs/CODE_ATTESTATION.md +2 -2
- package/docs/DOCUMENTATION_GUIDE.md +34 -12
- package/docs/GETTING_STARTED.md +59 -0
- 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 +60 -19
- package/docs/PROVIDERS.md +126 -0
- package/docs/PROVIDER_ARCHITECTURE.md +199 -0
- package/docs/RECIPES.md +32 -0
- package/docs/RELEASE_CHECKLIST.md +66 -5
- package/docs/SECURITY_REVIEW.md +71 -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 +298 -3
- 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 +1397 -0
- package/docs/protocol-requirements.json +101 -0
- package/package.json +46 -4
- package/schemas/config.schema.json +14 -0
- package/schemas/context-plan.schema.json +18 -0
- package/schemas/routing-input.schema.json +1 -1
- package/schemas/semantic-decision.schema.json +46 -0
- package/schemas/test-utility.schema.json +44 -0
- package/scripts/CI_VALIDATORS.md +84 -11
- package/scripts/benchmark-jev.mjs +5 -0
- package/scripts/benchmark-test-intelligence.mjs +4 -0
- package/scripts/generate-agent-protocol-summary.mjs +40 -1
- package/scripts/generate-forgeloop-skill.mjs +133 -0
- package/scripts/jev-smoke.mjs +19 -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 +313 -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 +282 -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/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 +108 -0
- package/src/commands/checkpoint-revalidate.js +176 -0
- package/src/commands/context-plan.js +38 -0
- package/src/commands/contract-create.js +264 -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 +15 -0
- package/src/commands/gate-record.js +205 -0
- package/src/commands/gate-revalidate.js +137 -0
- package/src/commands/model-route.js +32 -0
- package/src/commands/next.js +19 -7
- package/src/commands/route.js +146 -18
- package/src/commands/semantic-plan.js +17 -0
- package/src/commands/task-abandon.js +224 -0
- package/src/commands/task-create.js +84 -25
- package/src/commands/task-list.js +22 -2
- package/src/commands/task-migrate-contract-bootstrap-repair.js +288 -0
- package/src/commands/task-repair-contract-bootstrap.js +263 -0
- 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 +10 -1
- package/src/config/guides.json +44 -0
- package/src/core/artifact-registry.js +24 -0
- package/src/core/audit-ux.js +514 -0
- 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/build-script.js +151 -0
- package/src/core/c-cpp-project.js +143 -0
- package/src/core/checkpoint-revalidation.js +319 -0
- package/src/core/cli-command-definitions.js +249 -1
- package/src/core/command-executors.js +115 -3
- package/src/core/command-input.js +212 -102
- package/src/core/completion-artifacts.js +14 -5
- package/src/core/completion.js +4 -6
- package/src/core/config.js +3 -0
- 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/contract-bootstrap-recovery.js +655 -0
- package/src/core/contract-presets.js +82 -0
- package/src/core/contract-revision.js +210 -0
- package/src/core/decision/artifact.js +69 -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 +101 -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 +130 -0
- package/src/core/decision/result.js +58 -0
- package/src/core/decision/service.js +156 -0
- package/src/core/decision/state-builder.js +65 -0
- package/src/core/decision/task-bindings.js +30 -0
- package/src/core/decision/test-provider.js +32 -0
- package/src/core/decision/thresholds.js +15 -0
- package/src/core/error-codes.js +281 -3
- package/src/core/events.js +226 -57
- package/src/core/evidence-readiness.js +9 -0
- package/src/core/execution-prerequisites.js +14 -0
- package/src/core/execution-profile.js +63 -38
- package/src/core/filesystem.js +1 -10
- package/src/core/gate-provenance.js +124 -0
- package/src/core/go-project.js +206 -0
- package/src/core/integration-invocation-policy.js +27 -4
- package/src/core/integration-resources.js +86 -61
- package/src/core/java-project.js +403 -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/multi-language-project.js +117 -0
- package/src/core/next-action-model.js +58 -0
- package/src/core/next-action-phases.js +130 -42
- package/src/core/next-action-refresh.js +43 -9
- package/src/core/next-action-review-phase.js +7 -2
- package/src/core/next-action.js +35 -7
- package/src/core/next-explanation.js +63 -0
- package/src/core/phase.js +128 -10
- package/src/core/php-project.js +85 -0
- package/src/core/preflight-consistency.js +23 -9
- package/src/core/preflight-loaders.js +37 -5
- package/src/core/project-detection.js +1760 -52
- package/src/core/protocol-info.js +65 -0
- package/src/core/protocol.js +20 -0
- package/src/core/reconcile-closure.js +132 -53
- package/src/core/recovery-history.js +1 -0
- package/src/core/resumability.js +154 -44
- package/src/core/route-artifact.js +15 -1
- package/src/core/router.js +223 -4
- package/src/core/runtime-context.js +118 -61
- package/src/core/rust-project.js +400 -0
- package/src/core/schema-validation.js +3 -0
- 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/sources.js +37 -0
- package/src/core/sql-project.js +141 -0
- package/src/core/swift-project.js +200 -0
- package/src/core/task-claim-state.js +201 -1
- package/src/core/task-conflict-inspection.js +31 -5
- package/src/core/task-paths.js +13 -0
- package/src/core/task-recovery.js +1 -0
- package/src/core/templates.js +3 -0
- 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 +90 -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 +11 -7
- package/src/core/transaction.js +1 -0
- package/src/core/typescript-project.js +349 -0
- package/src/core/xml-structure.js +123 -0
- 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
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { normalizeDecisionResult } from "../../core/decision/result.js";
|
|
2
|
+
import { safeDecisionError } from "../../core/decision/errors.js";
|
|
3
|
+
|
|
4
|
+
function finiteProbability(value) {
|
|
5
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function confidenceFromAnswer(answer) {
|
|
9
|
+
if (!answer || typeof answer !== "object" || Array.isArray(answer)) return null;
|
|
10
|
+
if (finiteProbability(answer.confidence)) return answer.confidence;
|
|
11
|
+
if (answer.type === "noul" && finiteProbability(answer.noul)) {
|
|
12
|
+
return Math.max(answer.noul, 1 - answer.noul);
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// The live TypeSafe SystemOne result carries per-answer confidence inside each
|
|
18
|
+
// answer (choice.confidence, or the noul judgment probability itself) and no
|
|
19
|
+
// top-level confidence map; translate that into the canonical
|
|
20
|
+
// answer-name -> confidence shape ForgeLoop's decision layer consumes. A
|
|
21
|
+
// provider-reported top-level map remains authoritative per key when present.
|
|
22
|
+
function deriveTypesafeConfidence(raw) {
|
|
23
|
+
const answers = raw?.answers;
|
|
24
|
+
const derived = answers && typeof answers === "object" && !Array.isArray(answers)
|
|
25
|
+
? Object.fromEntries(Object.entries(answers).map(([name, answer]) => [name, confidenceFromAnswer(answer)]))
|
|
26
|
+
: {};
|
|
27
|
+
const provided = raw?.confidence;
|
|
28
|
+
if (!provided || typeof provided !== "object" || Array.isArray(provided)) return derived;
|
|
29
|
+
for (const [name, value] of Object.entries(provided)) {
|
|
30
|
+
if (finiteProbability(value)) derived[name] = value;
|
|
31
|
+
}
|
|
32
|
+
return derived;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function normalizeTypesafeResult(raw, questionSet) {
|
|
36
|
+
try {
|
|
37
|
+
return normalizeDecisionResult({ ...raw, confidence: deriveTypesafeConfidence(raw) }, { questionSet });
|
|
38
|
+
} catch (error) {
|
|
39
|
+
throw safeDecisionError(error, "E_DECISION_RESULT_INVALID");
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { formatStatusResult } from "./commands/status.js";
|
|
8
8
|
import { formatValidateStateResult } from "./commands/validate-state.js";
|
|
9
9
|
import { formatClearStateResult } from "./commands/clear-state.js";
|
|
10
|
+
import { formatCheckpointRevalidateResult } from "./commands/checkpoint-revalidate.js";
|
|
10
11
|
import { formatInspectResult } from "./commands/inspect.js";
|
|
11
12
|
import { formatRouteResult } from "./commands/route.js";
|
|
12
13
|
import { formatValidateProtocolResult } from "./commands/validate-protocol.js";
|
|
@@ -54,6 +55,9 @@ import { formatReflectResult } from "./commands/reflect.js";
|
|
|
54
55
|
import { formatProgressResult } from "./commands/progress.js";
|
|
55
56
|
import { formatRecordDecisionCriterionResult } from "./commands/record-decision-criterion.js";
|
|
56
57
|
import { formatNextActionResult, formatCompactNextActionResult } from "./commands/next.js";
|
|
58
|
+
import { formatDiscoverResult } from "./commands/discover.js";
|
|
59
|
+
import { formatContractCreateResult } from "./commands/contract-create.js";
|
|
60
|
+
import { formatContractReviseResult } from "./commands/contract-revise.js";
|
|
57
61
|
import { formatContinuityResult } from "./commands/continuity.js";
|
|
58
62
|
import { formatRecordContinuityResult } from "./commands/record-continuity.js";
|
|
59
63
|
import { formatReconcileContinuityResult } from "./commands/reconcile-continuity.js";
|
|
@@ -66,10 +70,13 @@ import { formatTaskMigrateResult } from "./commands/task-migrate.js";
|
|
|
66
70
|
import { formatMigrateProtocolResult } from "./commands/migrate-protocol.js";
|
|
67
71
|
import { formatTaskUnlockResult } from "./commands/task-unlock.js";
|
|
68
72
|
import { formatTaskRecoverResult } from "./commands/task-recover.js";
|
|
73
|
+
import { formatTaskAbandonResult } from "./commands/task-abandon.js";
|
|
69
74
|
import { formatTaskResumeResult } from "./commands/task-resume.js";
|
|
70
75
|
import {
|
|
71
76
|
formatTaskRepairLegacyRecoveryResult,
|
|
72
77
|
} from "./commands/task-repair-legacy-recovery.js";
|
|
78
|
+
import { formatTaskRepairContractBootstrapResult } from "./commands/task-repair-contract-bootstrap.js";
|
|
79
|
+
import { formatTaskMigrateContractBootstrapRepairResult } from "./commands/task-migrate-contract-bootstrap-repair.js";
|
|
73
80
|
import { formatTaskLockStatusResult } from "./commands/task-lock-status.js";
|
|
74
81
|
import { formatProtocolInfoResult } from "./commands/protocol-info.js";
|
|
75
82
|
import { formatWorkspaceBindResult } from "./commands/workspace-bind.js";
|
|
@@ -92,6 +99,17 @@ import {
|
|
|
92
99
|
} from "./commands/repository-index.js";
|
|
93
100
|
import { defaultCommandInputValues, validateForgeLoopCommandInput } from "./core/command-input.js";
|
|
94
101
|
import { COMMAND_EXECUTORS } from "./core/command-executors.js";
|
|
102
|
+
import { formatGateRecordResult } from "./commands/gate-record.js";
|
|
103
|
+
import { formatGateRevalidateResult } from "./commands/gate-revalidate.js";
|
|
104
|
+
import { formatDecisionStatusResult } from "./commands/decision-status.js";
|
|
105
|
+
import { formatDecisionShowResult } from "./commands/decision-show.js";
|
|
106
|
+
import { formatContextPlanResult } from "./commands/context-plan.js";
|
|
107
|
+
import { formatModelRouteResult } from "./commands/model-route.js";
|
|
108
|
+
import { formatSemanticPlanResult } from "./commands/semantic-plan.js";
|
|
109
|
+
import { formatTestInventoryResult } from "./commands/test-inventory.js";
|
|
110
|
+
import { formatTestUtilityResult } from "./commands/test-utility.js";
|
|
111
|
+
import { formatTestPrunePlanResult } from "./commands/test-prune-plan.js";
|
|
112
|
+
import { formatTestPruneProbeResult } from "./commands/test-prune-probe.js";
|
|
95
113
|
import { resolveTarget } from "./core/filesystem.js";
|
|
96
114
|
import { getPackageRoot } from "./core/templates.js";
|
|
97
115
|
import { CLI_COMMAND_DEFINITIONS, buildOptionLookup, getPositionalDefinitions } from "./core/cli-command-definitions.js";
|
|
@@ -349,11 +367,81 @@ function renderJsonOr(options, result, formatter) {
|
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
export const COMMAND_HANDLERS = Object.freeze({
|
|
370
|
+
discover: async ({ target, packageRoot, options }) => {
|
|
371
|
+
const { result } = await COMMAND_EXECUTORS.discover({ target, packageRoot, options });
|
|
372
|
+
renderJsonOr(options, result, formatDiscoverResult);
|
|
373
|
+
return 0;
|
|
374
|
+
},
|
|
375
|
+
"contract-create": async ({ target, packageRoot, options }) => {
|
|
376
|
+
const { result } = await COMMAND_EXECUTORS["contract-create"]({ target, packageRoot, options });
|
|
377
|
+
renderJsonOr(options, result, formatContractCreateResult);
|
|
378
|
+
return 0;
|
|
379
|
+
},
|
|
380
|
+
"contract-revise": async ({ target, packageRoot, options }) => {
|
|
381
|
+
const { result } = await COMMAND_EXECUTORS["contract-revise"]({ target, packageRoot, options });
|
|
382
|
+
renderJsonOr(options, result, formatContractReviseResult);
|
|
383
|
+
return 0;
|
|
384
|
+
},
|
|
385
|
+
"gate-record": async ({ target, packageRoot, options }) => {
|
|
386
|
+
const { result } = await COMMAND_EXECUTORS["gate-record"]({ target, packageRoot, options });
|
|
387
|
+
renderJsonOr(options, result, formatGateRecordResult);
|
|
388
|
+
return 0;
|
|
389
|
+
},
|
|
390
|
+
"gate-revalidate": async ({ target, packageRoot, options }) => {
|
|
391
|
+
const { result } = await COMMAND_EXECUTORS["gate-revalidate"]({ target, packageRoot, options });
|
|
392
|
+
renderJsonOr(options, result, formatGateRevalidateResult);
|
|
393
|
+
return 0;
|
|
394
|
+
},
|
|
352
395
|
"protocol-info": async ({ packageVersion, options }) => {
|
|
353
396
|
const { result } = await COMMAND_EXECUTORS["protocol-info"]({ packageVersion, options });
|
|
354
397
|
renderJsonOr(options, result, formatProtocolInfoResult);
|
|
355
398
|
return 0;
|
|
356
399
|
},
|
|
400
|
+
"decision-status": async ({ target, packageRoot, options }) => {
|
|
401
|
+
const { result } = await COMMAND_EXECUTORS["decision-status"]({ target, packageRoot, options });
|
|
402
|
+
renderJsonOr(options, result, formatDecisionStatusResult);
|
|
403
|
+
return 0;
|
|
404
|
+
},
|
|
405
|
+
"decision-show": async ({ target, packageRoot, options }) => {
|
|
406
|
+
const { result } = await COMMAND_EXECUTORS["decision-show"]({ target, packageRoot, options });
|
|
407
|
+
renderJsonOr(options, result, formatDecisionShowResult);
|
|
408
|
+
return 0;
|
|
409
|
+
},
|
|
410
|
+
"context-plan": async ({ options }) => {
|
|
411
|
+
const { result } = await COMMAND_EXECUTORS["context-plan"]({ options });
|
|
412
|
+
renderJsonOr(options, result, formatContextPlanResult);
|
|
413
|
+
return 0;
|
|
414
|
+
},
|
|
415
|
+
"model-route": async ({ options }) => {
|
|
416
|
+
const { result } = await COMMAND_EXECUTORS["model-route"]({ options });
|
|
417
|
+
renderJsonOr(options, result, formatModelRouteResult);
|
|
418
|
+
return 0;
|
|
419
|
+
},
|
|
420
|
+
"semantic-plan": async ({ options }) => {
|
|
421
|
+
const { result } = await COMMAND_EXECUTORS["semantic-plan"]({ options });
|
|
422
|
+
renderJsonOr(options, result, formatSemanticPlanResult);
|
|
423
|
+
return 0;
|
|
424
|
+
},
|
|
425
|
+
"test-inventory": async ({ target, options }) => {
|
|
426
|
+
const { result } = await COMMAND_EXECUTORS["test-inventory"]({ target, options });
|
|
427
|
+
renderJsonOr(options, result, formatTestInventoryResult);
|
|
428
|
+
return 0;
|
|
429
|
+
},
|
|
430
|
+
"test-utility": async ({ target, packageRoot, options }) => {
|
|
431
|
+
const { result } = await COMMAND_EXECUTORS["test-utility"]({ target, packageRoot, options });
|
|
432
|
+
renderJsonOr(options, result, formatTestUtilityResult);
|
|
433
|
+
return 0;
|
|
434
|
+
},
|
|
435
|
+
"test-prune-plan": async ({ target, packageRoot, options }) => {
|
|
436
|
+
const { result } = await COMMAND_EXECUTORS["test-prune-plan"]({ target, packageRoot, options });
|
|
437
|
+
renderJsonOr(options, result, formatTestPrunePlanResult);
|
|
438
|
+
return 0;
|
|
439
|
+
},
|
|
440
|
+
"test-prune-probe": async ({ target, packageRoot, options }) => {
|
|
441
|
+
const { result } = await COMMAND_EXECUTORS["test-prune-probe"]({ target, packageRoot, options });
|
|
442
|
+
renderJsonOr(options, result, formatTestPruneProbeResult);
|
|
443
|
+
return 0;
|
|
444
|
+
},
|
|
357
445
|
init: async ({ target, packageRoot, packageVersion, options }) => {
|
|
358
446
|
const { result } = await COMMAND_EXECUTORS.init({ target, packageRoot, packageVersion, options });
|
|
359
447
|
printActions(result.actions);
|
|
@@ -784,11 +872,31 @@ export const COMMAND_HANDLERS = Object.freeze({
|
|
|
784
872
|
renderJsonOr(options, result, formatTaskRecoverResult);
|
|
785
873
|
return 0;
|
|
786
874
|
},
|
|
875
|
+
"task-abandon": async ({ target, packageRoot, options }) => {
|
|
876
|
+
const { result } = await COMMAND_EXECUTORS["task-abandon"]({ target, packageRoot, options });
|
|
877
|
+
renderJsonOr(options, result, formatTaskAbandonResult);
|
|
878
|
+
return 0;
|
|
879
|
+
},
|
|
787
880
|
"task-resume": async ({ target, packageRoot, options }) => {
|
|
788
881
|
const { result } = await COMMAND_EXECUTORS["task-resume"]({ target, packageRoot, options });
|
|
789
882
|
renderJsonOr(options, result, formatTaskResumeResult);
|
|
790
883
|
return 0;
|
|
791
884
|
},
|
|
885
|
+
"task-repair-contract-bootstrap": async ({ target, packageRoot, options }) => {
|
|
886
|
+
const { result } = await COMMAND_EXECUTORS["task-repair-contract-bootstrap"]({ target, packageRoot, options });
|
|
887
|
+
renderJsonOr(options, result, formatTaskRepairContractBootstrapResult);
|
|
888
|
+
return 0;
|
|
889
|
+
},
|
|
890
|
+
"task-migrate-contract-bootstrap-repair": async ({ target, packageRoot, options }) => {
|
|
891
|
+
const { result } = await COMMAND_EXECUTORS["task-migrate-contract-bootstrap-repair"]({ target, packageRoot, options });
|
|
892
|
+
renderJsonOr(options, result, formatTaskMigrateContractBootstrapRepairResult);
|
|
893
|
+
return 0;
|
|
894
|
+
},
|
|
895
|
+
"checkpoint-revalidate": async ({ target, packageRoot, options }) => {
|
|
896
|
+
const { result } = await COMMAND_EXECUTORS["checkpoint-revalidate"]({ target, packageRoot, options });
|
|
897
|
+
renderJsonOr(options, result, formatCheckpointRevalidateResult);
|
|
898
|
+
return 0;
|
|
899
|
+
},
|
|
792
900
|
"task-repair-legacy-recovery": async ({ target, packageRoot, options }) => {
|
|
793
901
|
const { result } = await COMMAND_EXECUTORS["task-repair-legacy-recovery"]({ target, packageRoot, options });
|
|
794
902
|
renderJsonOr(options, result, formatTaskRepairLegacyRecoveryResult);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { canonicalFingerprint } from "../core/artifacts.js";
|
|
2
|
+
import { readContract } from "../core/contract.js";
|
|
3
|
+
import {
|
|
4
|
+
appendProtocolEvent,
|
|
5
|
+
validateEventLedger,
|
|
6
|
+
validateStateLedgerCoherence,
|
|
7
|
+
} from "../core/events.js";
|
|
8
|
+
import { readPersistedRoute } from "../core/route-artifact.js";
|
|
9
|
+
import { currentRepositoryFingerprint } from "../core/repository.js";
|
|
10
|
+
import { resolveTaskContext } from "../core/task-context.js";
|
|
11
|
+
import { taskArtifactPath } from "../core/task-paths.js";
|
|
12
|
+
import { assertTaskMutationAllowed } from "../core/task-claim-state.js";
|
|
13
|
+
import { withTaskTransaction } from "../core/transaction.js";
|
|
14
|
+
import {
|
|
15
|
+
CHECKPOINT_REVALIDATED_EVENT,
|
|
16
|
+
assertCheckpointRevalidatedDetails,
|
|
17
|
+
assertRepositoryFingerprint,
|
|
18
|
+
} from "../core/checkpoint-revalidation.js";
|
|
19
|
+
import { resolveTaskClaimState } from "../core/task-claim-state.js";
|
|
20
|
+
import { sameCanonicalGuideList, resolveEffectiveContractBootstrapRepairAnchor } from "../core/contract-bootstrap-recovery.js";
|
|
21
|
+
import {
|
|
22
|
+
classifyLoadedWorkState,
|
|
23
|
+
createWorkState,
|
|
24
|
+
mutateWorkState,
|
|
25
|
+
readWorkState,
|
|
26
|
+
} from "../core/work-state.js";
|
|
27
|
+
|
|
28
|
+
function revalidationError(message, details = {}) {
|
|
29
|
+
const error = new Error(message);
|
|
30
|
+
error.code = "E_CHECKPOINT_REVALIDATION_UNSAFE";
|
|
31
|
+
Object.assign(error, details);
|
|
32
|
+
return error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function sameRepositoryFingerprint(left, right) {
|
|
36
|
+
return left?.branch === right?.branch && left?.head === right?.head;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function assertRouteIdentity(state, contract, route) {
|
|
40
|
+
if (!route || route.value?.contractFingerprint !== contract.fingerprint
|
|
41
|
+
|| state.routeFingerprint !== route.fingerprint
|
|
42
|
+
|| !sameCanonicalGuideList(state.selectedGuides, route.value.guides)) {
|
|
43
|
+
throw revalidationError("ROUTED checkpoint route identity cannot be proven safe", {
|
|
44
|
+
artifacts: [taskArtifactPath(state.taskId, "state"), taskArtifactPath(state.taskId, "route")],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function inspectEligibility(target, packageRoot, taskId) {
|
|
50
|
+
const state = await readWorkState(target, { packageRoot, taskId });
|
|
51
|
+
if (!state) throw revalidationError("A persisted work-state checkpoint is required");
|
|
52
|
+
if (state.phase !== "ROUTED") throw revalidationError(`Checkpoint revalidation supports phase ROUTED, found ${state.phase}`);
|
|
53
|
+
|
|
54
|
+
const ledger = await validateEventLedger(target, packageRoot, { taskId });
|
|
55
|
+
if (!ledger.valid) throw revalidationError("Checkpoint revalidation requires a structurally valid event ledger", { errors: ledger.errors });
|
|
56
|
+
if (ledger.events.some((event) => event.event === "EXECUTION_STARTED")) {
|
|
57
|
+
throw revalidationError("Checkpoint revalidation is unavailable after execution has started");
|
|
58
|
+
}
|
|
59
|
+
const coherenceErrors = validateStateLedgerCoherence(state, ledger.events);
|
|
60
|
+
if (coherenceErrors.length > 0) throw revalidationError("Checkpoint revalidation requires coherent state and ledger", { errors: coherenceErrors });
|
|
61
|
+
const ownership = await resolveTaskClaimState(target, { taskId, packageRoot });
|
|
62
|
+
if (!ownership.ownershipValid || !ownership.mutationAllowed) {
|
|
63
|
+
throw revalidationError("Checkpoint revalidation cannot bypass invalid task ownership", { errors: ownership.ownershipErrors });
|
|
64
|
+
}
|
|
65
|
+
const contract = await readContract(target, packageRoot, { taskId });
|
|
66
|
+
if (state.contractFingerprint !== contract.fingerprint) {
|
|
67
|
+
throw revalidationError("Checkpoint contract identity changed; use the contract revision path");
|
|
68
|
+
}
|
|
69
|
+
const route = await readPersistedRoute(target, packageRoot, { taskId });
|
|
70
|
+
assertRouteIdentity(state, contract, route);
|
|
71
|
+
|
|
72
|
+
const freshness = await classifyLoadedWorkState({
|
|
73
|
+
target,
|
|
74
|
+
state,
|
|
75
|
+
contractFile: taskArtifactPath(taskId, "contract"),
|
|
76
|
+
});
|
|
77
|
+
const repository = freshness.repository;
|
|
78
|
+
assertRepositoryFingerprint(repository, "current repository fingerprint", { requireHead: true });
|
|
79
|
+
const reasons = [...new Set(freshness.reasons)].sort();
|
|
80
|
+
if (reasons.length === 0) {
|
|
81
|
+
return { state, contract, route, ledger, repository, freshness, alreadyFresh: true };
|
|
82
|
+
}
|
|
83
|
+
if (reasons.length !== 1 || reasons[0] !== "REPOSITORY_CHANGED") {
|
|
84
|
+
throw revalidationError(`Checkpoint freshness is not repository-only: ${reasons.join(", ")}`);
|
|
85
|
+
}
|
|
86
|
+
const repairAnchor = resolveEffectiveContractBootstrapRepairAnchor(ledger.events);
|
|
87
|
+
if (repairAnchor && (repairAnchor.details.contractFingerprint !== contract.fingerprint
|
|
88
|
+
|| repairAnchor.details.routeFingerprint !== route.fingerprint)) {
|
|
89
|
+
throw revalidationError("Repaired checkpoint identity does not match the current contract and route");
|
|
90
|
+
}
|
|
91
|
+
return { state, contract, route, ledger, repository, freshness, repairAnchor, alreadyFresh: false };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function resultFor(taskId, state, repository, event = null, transaction = null, alreadyFresh = false) {
|
|
95
|
+
return {
|
|
96
|
+
taskId,
|
|
97
|
+
revalidated: !alreadyFresh,
|
|
98
|
+
alreadyFresh,
|
|
99
|
+
phase: state.phase,
|
|
100
|
+
previousRevision: event ? event.details.previousStateRevision : state.revision,
|
|
101
|
+
revalidatedRevision: event ? event.details.revalidatedStateRevision : state.revision,
|
|
102
|
+
previousRepositoryFingerprint: event?.details.previousRepositoryFingerprint ?? repository,
|
|
103
|
+
repositoryFingerprint: event?.details.repositoryFingerprint ?? repository,
|
|
104
|
+
eventSeq: event?.seq ?? null,
|
|
105
|
+
transactionCommitSeq: transaction?.seq ?? null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function revalidateLocked(target, packageRoot, taskId, transaction) {
|
|
110
|
+
const ownership = await resolveTaskClaimState(target, { taskId, packageRoot });
|
|
111
|
+
if (!ownership.ownershipValid || !ownership.mutationAllowed) {
|
|
112
|
+
throw revalidationError("Checkpoint revalidation cannot bypass invalid task ownership", { errors: ownership.ownershipErrors });
|
|
113
|
+
}
|
|
114
|
+
await assertTaskMutationAllowed(target, { taskId, packageRoot });
|
|
115
|
+
const inspected = await inspectEligibility(target, packageRoot, taskId);
|
|
116
|
+
if (inspected.alreadyFresh) return resultFor(taskId, inspected.state, inspected.repository, null, null, true);
|
|
117
|
+
|
|
118
|
+
const before = inspected.state;
|
|
119
|
+
const previousStateFingerprint = canonicalFingerprint(before);
|
|
120
|
+
const previousRepositoryFingerprint = structuredClone(before.repositoryFingerprint);
|
|
121
|
+
const repository = await currentRepositoryFingerprint(target);
|
|
122
|
+
assertRepositoryFingerprint(repository, "current repository fingerprint", { requireHead: true });
|
|
123
|
+
if (!sameRepositoryFingerprint(repository, inspected.repository)) {
|
|
124
|
+
throw revalidationError("Repository identity changed during checkpoint revalidation");
|
|
125
|
+
}
|
|
126
|
+
const next = await mutateWorkState(target, {
|
|
127
|
+
expectedRevision: before.revision,
|
|
128
|
+
packageRoot,
|
|
129
|
+
taskId,
|
|
130
|
+
}, (current) => createWorkState({
|
|
131
|
+
...current,
|
|
132
|
+
repositoryFingerprint: repository,
|
|
133
|
+
lastUpdated: new Date().toISOString(),
|
|
134
|
+
}));
|
|
135
|
+
const details = {
|
|
136
|
+
phase: next.phase,
|
|
137
|
+
previousRepositoryFingerprint,
|
|
138
|
+
repositoryFingerprint: structuredClone(repository),
|
|
139
|
+
contractFingerprint: next.contractFingerprint,
|
|
140
|
+
routeFingerprint: next.routeFingerprint,
|
|
141
|
+
previousStateRevision: before.revision,
|
|
142
|
+
revalidatedStateRevision: next.revision,
|
|
143
|
+
previousStateFingerprint,
|
|
144
|
+
revalidatedStateFingerprint: canonicalFingerprint(next),
|
|
145
|
+
};
|
|
146
|
+
assertCheckpointRevalidatedDetails(details);
|
|
147
|
+
const event = await appendProtocolEvent(target, {
|
|
148
|
+
taskId,
|
|
149
|
+
event: CHECKPOINT_REVALIDATED_EVENT,
|
|
150
|
+
details,
|
|
151
|
+
}, packageRoot, { taskId });
|
|
152
|
+
const commitEvent = await appendProtocolEvent(target, {
|
|
153
|
+
taskId,
|
|
154
|
+
event: "TRANSACTION_COMMITTED",
|
|
155
|
+
details: { transactionId: transaction.transactionId, operation: "checkpoint-revalidate" },
|
|
156
|
+
}, packageRoot, { taskId });
|
|
157
|
+
return resultFor(taskId, next, repository, event, commitEvent, false);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export async function runCheckpointRevalidate({ target, packageRoot, taskId } = {}) {
|
|
161
|
+
const context = await resolveTaskContext(target, { taskId, packageRoot, explicitRequired: true });
|
|
162
|
+
const effectiveTaskId = context.taskId;
|
|
163
|
+
const initial = await inspectEligibility(target, packageRoot, effectiveTaskId);
|
|
164
|
+
if (initial.alreadyFresh) return resultFor(effectiveTaskId, initial.state, initial.repository, null, null, true);
|
|
165
|
+
return withTaskTransaction({
|
|
166
|
+
target,
|
|
167
|
+
taskId: effectiveTaskId,
|
|
168
|
+
operation: "checkpoint-revalidate",
|
|
169
|
+
packageRoot,
|
|
170
|
+
recordCommitEvent: false,
|
|
171
|
+
}, async (transaction) => revalidateLocked(target, packageRoot, effectiveTaskId, transaction));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function formatCheckpointRevalidateResult(result) {
|
|
175
|
+
return `${JSON.stringify(result, null, 2)}\n`;
|
|
176
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { compileContext } from "../core/context-compiler/compiler.js";
|
|
2
|
+
import { normalizeContextCandidates } from "../core/context-compiler/candidates.js";
|
|
3
|
+
import { canonicalFingerprint } from "../core/artifacts.js";
|
|
4
|
+
import { buildContextQuestionSet } from "../core/decision/question-registry.js";
|
|
5
|
+
import { ensureSemanticDecision } from "../core/decision/service.js";
|
|
6
|
+
|
|
7
|
+
export async function runContextPlan({ target, packageRoot, taskId, decisionId, profile = "balanced", candidates = [], mandatoryIds = [], provider = null, readOnly = false } = {}) {
|
|
8
|
+
if (readOnly) return compileContext({ profile, candidates, mandatoryIds });
|
|
9
|
+
if (target && taskId) {
|
|
10
|
+
const normalized = normalizeContextCandidates(candidates);
|
|
11
|
+
const candidateSetFingerprint = canonicalFingerprint(normalized.map((candidate) => ({
|
|
12
|
+
id: candidate.id, sourceRef: candidate.sourceRef, summary: candidate.summary,
|
|
13
|
+
required: candidate.required, mandatory: candidate.mandatory,
|
|
14
|
+
})));
|
|
15
|
+
const questionSet = buildContextQuestionSet(normalized);
|
|
16
|
+
const decision = await ensureSemanticDecision({
|
|
17
|
+
target, packageRoot, taskId, decisionId, provider, allowNetwork: !readOnly,
|
|
18
|
+
request: {
|
|
19
|
+
decisionKind: "CONTEXT_PLAN", questionSetId: questionSet.id, questionSet,
|
|
20
|
+
state: { candidates: normalized.map(({ id, sourceRef, kind, summary, required, mandatory, risk, trust }) => ({ id, sourceRef, kind, summary, required, mandatory, risk, trust })) },
|
|
21
|
+
candidateIds: normalized.map((candidate) => candidate.id), candidateSetFingerprint,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return compileContext({ profile, candidates, mandatoryIds, semanticRanker: () => ({ rankedIds: decision.artifact.decision?.rankedIds ?? [], excludedIds: decision.artifact.decision?.excludedIds ?? [] }) });
|
|
25
|
+
}
|
|
26
|
+
return compileContext({ profile, candidates, mandatoryIds });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function formatContextPlanResult(result) {
|
|
30
|
+
return [
|
|
31
|
+
`Context plan: ${result.selectedItems}/${result.candidateItems} items`,
|
|
32
|
+
`Profile: ${result.profile}`,
|
|
33
|
+
`Selected chars: ${result.selectedChars}/${result.budget.maxChars}`,
|
|
34
|
+
`Prompt-injection candidates: ${result.promptInjectionIds.length}`,
|
|
35
|
+
`Fingerprint: ${result.decisionFingerprint}`,
|
|
36
|
+
"",
|
|
37
|
+
].join("\n");
|
|
38
|
+
}
|