clinkx 0.3.0 → 1.0.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/CHANGELOG.md +33 -0
- package/LICENSE +10 -0
- package/README.md +82 -26
- package/clinkx-workflows/dist/allowed-roots.d.ts +1 -0
- package/clinkx-workflows/dist/allowed-roots.js +5 -0
- package/clinkx-workflows/dist/allowed-roots.js.map +1 -0
- package/clinkx-workflows/dist/artifacts.d.ts +20 -1
- package/clinkx-workflows/dist/artifacts.js +38 -9
- package/clinkx-workflows/dist/artifacts.js.map +1 -1
- package/clinkx-workflows/dist/backend.d.ts +4 -0
- package/clinkx-workflows/dist/citation-check.d.ts +40 -0
- package/clinkx-workflows/dist/citation-check.js +348 -0
- package/clinkx-workflows/dist/citation-check.js.map +1 -0
- package/clinkx-workflows/dist/clink-client.d.ts +2 -1
- package/clinkx-workflows/dist/clink-client.js +17 -4
- package/clinkx-workflows/dist/clink-client.js.map +1 -1
- package/clinkx-workflows/dist/config.d.ts +145 -16
- package/clinkx-workflows/dist/config.js +384 -26
- package/clinkx-workflows/dist/config.js.map +1 -1
- package/clinkx-workflows/dist/contained-file.d.ts +172 -0
- package/clinkx-workflows/dist/contained-file.js +483 -0
- package/clinkx-workflows/dist/contained-file.js.map +1 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-contract.d.ts +416 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-contract.js +328 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-contract.js.map +1 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-router.d.ts +24 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-router.js +39 -0
- package/clinkx-workflows/dist/context-builder-lifecycle-router.js.map +1 -0
- package/clinkx-workflows/dist/context-cache-key.d.ts +53 -0
- package/clinkx-workflows/dist/context-cache-key.js +91 -0
- package/clinkx-workflows/dist/context-cache-key.js.map +1 -0
- package/clinkx-workflows/dist/context-mode-resolver.d.ts +27 -0
- package/clinkx-workflows/dist/context-mode-resolver.js +126 -0
- package/clinkx-workflows/dist/context-mode-resolver.js.map +1 -0
- package/clinkx-workflows/dist/context-preflight.d.ts +184 -0
- package/clinkx-workflows/dist/context-preflight.js +91 -0
- package/clinkx-workflows/dist/context-preflight.js.map +1 -0
- package/clinkx-workflows/dist/council-expander.d.ts +1 -1
- package/clinkx-workflows/dist/council-expander.js +2 -1
- package/clinkx-workflows/dist/council-expander.js.map +1 -1
- package/clinkx-workflows/dist/dashboard/activity-contract.d.ts +165 -0
- package/clinkx-workflows/dist/dashboard/activity-contract.js +105 -0
- package/clinkx-workflows/dist/dashboard/activity-contract.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/activity-lease.d.ts +25 -0
- package/clinkx-workflows/dist/dashboard/activity-lease.js +34 -0
- package/clinkx-workflows/dist/dashboard/activity-lease.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/activity-reader.d.ts +86 -0
- package/clinkx-workflows/dist/dashboard/activity-reader.js +480 -0
- package/clinkx-workflows/dist/dashboard/activity-reader.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/api-routes.d.ts +36 -0
- package/clinkx-workflows/dist/dashboard/api-routes.js +1047 -0
- package/clinkx-workflows/dist/dashboard/api-routes.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/artifact-index.d.ts +37 -0
- package/clinkx-workflows/dist/dashboard/artifact-index.js +145 -0
- package/clinkx-workflows/dist/dashboard/artifact-index.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/challenge-store.d.ts +31 -0
- package/clinkx-workflows/dist/dashboard/auth/challenge-store.js +65 -0
- package/clinkx-workflows/dist/dashboard/auth/challenge-store.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/controller.d.ts +26 -0
- package/clinkx-workflows/dist/dashboard/auth/controller.js +596 -0
- package/clinkx-workflows/dist/dashboard/auth/controller.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/credential-store.d.ts +60 -0
- package/clinkx-workflows/dist/dashboard/auth/credential-store.js +776 -0
- package/clinkx-workflows/dist/dashboard/auth/credential-store.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.d.ts +9 -0
- package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js +44 -0
- package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/session-store.d.ts +17 -0
- package/clinkx-workflows/dist/dashboard/auth/session-store.js +77 -0
- package/clinkx-workflows/dist/dashboard/auth/session-store.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/auth/webauthn-service.d.ts +25 -0
- package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js +71 -0
- package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/context-run-liveness.d.ts +37 -0
- package/clinkx-workflows/dist/dashboard/context-run-liveness.js +49 -0
- package/clinkx-workflows/dist/dashboard/context-run-liveness.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/context-run-reader.d.ts +222 -0
- package/clinkx-workflows/dist/dashboard/context-run-reader.js +1178 -0
- package/clinkx-workflows/dist/dashboard/context-run-reader.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/contracts.d.ts +8936 -0
- package/clinkx-workflows/dist/dashboard/contracts.js +1157 -0
- package/clinkx-workflows/dist/dashboard/contracts.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/generation.d.ts +14 -0
- package/clinkx-workflows/dist/dashboard/generation.js +41 -0
- package/clinkx-workflows/dist/dashboard/generation.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/index.d.ts +28 -0
- package/clinkx-workflows/dist/dashboard/index.js +16 -0
- package/clinkx-workflows/dist/dashboard/index.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/lazy-content.d.ts +101 -0
- package/clinkx-workflows/dist/dashboard/lazy-content.js +748 -0
- package/clinkx-workflows/dist/dashboard/lazy-content.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/progress-report-contract.d.ts +303 -0
- package/clinkx-workflows/dist/dashboard/progress-report-contract.js +221 -0
- package/clinkx-workflows/dist/dashboard/progress-report-contract.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/progress-report-reader.d.ts +50 -0
- package/clinkx-workflows/dist/dashboard/progress-report-reader.js +581 -0
- package/clinkx-workflows/dist/dashboard/progress-report-reader.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.d.ts +89 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js +71 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-store.d.ts +28 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-store.js +110 -0
- package/clinkx-workflows/dist/dashboard/progress-report-status-store.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/read-model.d.ts +86 -0
- package/clinkx-workflows/dist/dashboard/read-model.js +440 -0
- package/clinkx-workflows/dist/dashboard/read-model.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/request-admission.d.ts +31 -0
- package/clinkx-workflows/dist/dashboard/request-admission.js +126 -0
- package/clinkx-workflows/dist/dashboard/request-admission.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/scanner.d.ts +75 -0
- package/clinkx-workflows/dist/dashboard/scanner.js +1110 -0
- package/clinkx-workflows/dist/dashboard/scanner.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/server-factory.d.ts +50 -0
- package/clinkx-workflows/dist/dashboard/server-factory.js +431 -0
- package/clinkx-workflows/dist/dashboard/server-factory.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-contract.d.ts +2611 -0
- package/clinkx-workflows/dist/dashboard/session-log-contract.js +480 -0
- package/clinkx-workflows/dist/dashboard/session-log-contract.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-identity.d.ts +21 -0
- package/clinkx-workflows/dist/dashboard/session-log-identity.js +101 -0
- package/clinkx-workflows/dist/dashboard/session-log-identity.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-journal.d.ts +43 -0
- package/clinkx-workflows/dist/dashboard/session-log-journal.js +522 -0
- package/clinkx-workflows/dist/dashboard/session-log-journal.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-reader.d.ts +61 -0
- package/clinkx-workflows/dist/dashboard/session-log-reader.js +378 -0
- package/clinkx-workflows/dist/dashboard/session-log-reader.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-redaction.d.ts +6 -0
- package/clinkx-workflows/dist/dashboard/session-log-redaction.js +367 -0
- package/clinkx-workflows/dist/dashboard/session-log-redaction.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/session-log-retention.d.ts +23 -0
- package/clinkx-workflows/dist/dashboard/session-log-retention.js +212 -0
- package/clinkx-workflows/dist/dashboard/session-log-retention.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/static-responses.d.ts +10 -0
- package/clinkx-workflows/dist/dashboard/static-responses.js +94 -0
- package/clinkx-workflows/dist/dashboard/static-responses.js.map +1 -0
- package/clinkx-workflows/dist/dashboard/worker-lock-observer.d.ts +28 -0
- package/clinkx-workflows/dist/dashboard/worker-lock-observer.js +241 -0
- package/clinkx-workflows/dist/dashboard/worker-lock-observer.js.map +1 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/index-DOkMXTfB.js +25 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/clinkx-workflows/dist/dashboard-ui/assets/style-ChJsn0KD.css +1 -0
- package/clinkx-workflows/dist/dashboard-ui/contracts/council-plan-review-input-v1.json +158 -0
- package/clinkx-workflows/dist/dashboard-ui/index.html +15 -0
- package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Mono-OFL.txt +93 -0
- package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Sans-OFL.txt +93 -0
- package/clinkx-workflows/dist/dashboard-ui/licenses/JetBrains-Mono-OFL.txt +93 -0
- package/clinkx-workflows/dist/dashboard-ui/licenses/NOTICE.md +32 -0
- package/clinkx-workflows/dist/dashboard-ui/theme-init.js +8 -0
- package/clinkx-workflows/dist/definition-normalizer.d.ts +19 -0
- package/clinkx-workflows/dist/definition-normalizer.js.map +1 -1
- package/clinkx-workflows/dist/delegate-validate.d.ts +78 -0
- package/clinkx-workflows/dist/delegate-validate.js +97 -0
- package/clinkx-workflows/dist/delegate-validate.js.map +1 -0
- package/clinkx-workflows/dist/engine.d.ts +141 -0
- package/clinkx-workflows/dist/engine.js +882 -28
- package/clinkx-workflows/dist/engine.js.map +1 -1
- package/clinkx-workflows/dist/errors.d.ts +2 -0
- package/clinkx-workflows/dist/errors.js.map +1 -1
- package/clinkx-workflows/dist/fingerprint.d.ts +1 -1
- package/clinkx-workflows/dist/fingerprint.js +1 -1
- package/clinkx-workflows/dist/index.d.ts +19 -0
- package/clinkx-workflows/dist/index.js +15 -0
- package/clinkx-workflows/dist/index.js.map +1 -1
- package/clinkx-workflows/dist/loader.d.ts +9 -3
- package/clinkx-workflows/dist/loader.js +92 -21
- package/clinkx-workflows/dist/loader.js.map +1 -1
- package/clinkx-workflows/dist/plan-review/admission.d.ts +160 -0
- package/clinkx-workflows/dist/plan-review/admission.js +290 -0
- package/clinkx-workflows/dist/plan-review/admission.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/context-policy.d.ts +55 -0
- package/clinkx-workflows/dist/plan-review/context-policy.js +146 -0
- package/clinkx-workflows/dist/plan-review/context-policy.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/contract.d.ts +763 -0
- package/clinkx-workflows/dist/plan-review/contract.js +289 -0
- package/clinkx-workflows/dist/plan-review/contract.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/digest.d.ts +68 -0
- package/clinkx-workflows/dist/plan-review/digest.js +241 -0
- package/clinkx-workflows/dist/plan-review/digest.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/discovery.d.ts +45 -0
- package/clinkx-workflows/dist/plan-review/discovery.js +36 -0
- package/clinkx-workflows/dist/plan-review/discovery.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/execution-contract.d.ts +298 -0
- package/clinkx-workflows/dist/plan-review/execution-contract.js +194 -0
- package/clinkx-workflows/dist/plan-review/execution-contract.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/expander.d.ts +48 -0
- package/clinkx-workflows/dist/plan-review/expander.js +243 -0
- package/clinkx-workflows/dist/plan-review/expander.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/projector.d.ts +126 -0
- package/clinkx-workflows/dist/plan-review/projector.js +437 -0
- package/clinkx-workflows/dist/plan-review/projector.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/publication.d.ts +95 -0
- package/clinkx-workflows/dist/plan-review/publication.js +182 -0
- package/clinkx-workflows/dist/plan-review/publication.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/ranking-reducer.d.ts +34 -0
- package/clinkx-workflows/dist/plan-review/ranking-reducer.js +139 -0
- package/clinkx-workflows/dist/plan-review/ranking-reducer.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/resume.d.ts +38 -0
- package/clinkx-workflows/dist/plan-review/resume.js +122 -0
- package/clinkx-workflows/dist/plan-review/resume.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/rubric.d.ts +7 -0
- package/clinkx-workflows/dist/plan-review/rubric.js +24 -0
- package/clinkx-workflows/dist/plan-review/rubric.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/run-state.d.ts +398 -0
- package/clinkx-workflows/dist/plan-review/run-state.js +183 -0
- package/clinkx-workflows/dist/plan-review/run-state.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/runtime-policy.d.ts +74 -0
- package/clinkx-workflows/dist/plan-review/runtime-policy.js +186 -0
- package/clinkx-workflows/dist/plan-review/runtime-policy.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/snapshot.d.ts +81 -0
- package/clinkx-workflows/dist/plan-review/snapshot.js +170 -0
- package/clinkx-workflows/dist/plan-review/snapshot.js.map +1 -0
- package/clinkx-workflows/dist/plan-review/stage-error.d.ts +19 -0
- package/clinkx-workflows/dist/plan-review/stage-error.js +20 -0
- package/clinkx-workflows/dist/plan-review/stage-error.js.map +1 -0
- package/clinkx-workflows/dist/post-processors/index.d.ts +20 -0
- package/clinkx-workflows/dist/post-processors/index.js +21 -0
- package/clinkx-workflows/dist/post-processors/index.js.map +1 -0
- package/clinkx-workflows/dist/prompt-budget.d.ts +7 -0
- package/clinkx-workflows/dist/prompt-budget.js +7 -1
- package/clinkx-workflows/dist/prompt-budget.js.map +1 -1
- package/clinkx-workflows/dist/reducers/index.js +2 -0
- package/clinkx-workflows/dist/reducers/index.js.map +1 -1
- package/clinkx-workflows/dist/run-lock-heartbeat.d.ts +2 -0
- package/clinkx-workflows/dist/run-lock-heartbeat.js +3 -0
- package/clinkx-workflows/dist/run-lock-heartbeat.js.map +1 -0
- package/clinkx-workflows/dist/run-summary/cards/council-plan-review.d.ts +34 -0
- package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js +74 -0
- package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js.map +1 -0
- package/clinkx-workflows/dist/run-summary/cards/index.js +5 -0
- package/clinkx-workflows/dist/run-summary/cards/index.js.map +1 -1
- package/clinkx-workflows/dist/run-summary.d.ts +13 -0
- package/clinkx-workflows/dist/run-summary.js +29 -1
- package/clinkx-workflows/dist/run-summary.js.map +1 -1
- package/clinkx-workflows/dist/schema.d.ts +76 -21
- package/clinkx-workflows/dist/schema.js +10 -1
- package/clinkx-workflows/dist/schema.js.map +1 -1
- package/clinkx-workflows/dist/seed-terms.d.ts +30 -0
- package/clinkx-workflows/dist/seed-terms.js +176 -0
- package/clinkx-workflows/dist/seed-terms.js.map +1 -0
- package/clinkx-workflows/dist/server.d.ts +5 -2
- package/clinkx-workflows/dist/server.js +82 -52
- package/clinkx-workflows/dist/server.js.map +1 -1
- package/clinkx-workflows/dist/shutdown.d.ts +18 -20
- package/clinkx-workflows/dist/shutdown.js +43 -61
- package/clinkx-workflows/dist/shutdown.js.map +1 -1
- package/clinkx-workflows/dist/state-schema.d.ts +38 -0
- package/clinkx-workflows/dist/state.d.ts +170 -3
- package/clinkx-workflows/dist/state.js +1275 -28
- package/clinkx-workflows/dist/state.js.map +1 -1
- package/clinkx-workflows/dist/transport.d.ts +15 -0
- package/clinkx-workflows/dist/transport.js +19 -10
- package/clinkx-workflows/dist/transport.js.map +1 -1
- package/clinkx-workflows/dist/types.d.ts +14 -2
- package/clinkx-workflows/dist/validators/council.d.ts +318 -85
- package/clinkx-workflows/dist/validators/council.js +52 -13
- package/clinkx-workflows/dist/validators/council.js.map +1 -1
- package/clinkx-workflows/dist/validators/index.d.ts +1 -0
- package/clinkx-workflows/dist/validators/index.js +3 -0
- package/clinkx-workflows/dist/validators/index.js.map +1 -1
- package/clinkx-workflows/dist/validators/plan-review.d.ts +398 -0
- package/clinkx-workflows/dist/validators/plan-review.js +316 -0
- package/clinkx-workflows/dist/validators/plan-review.js.map +1 -0
- package/clinkx-workflows/dist/workflow-receipt.js +188 -4
- package/clinkx-workflows/dist/workflow-receipt.js.map +1 -1
- package/clinkx-workflows/dist/workflow-tools.d.ts +48 -3
- package/clinkx-workflows/dist/workflow-tools.js +1402 -59
- package/clinkx-workflows/dist/workflow-tools.js.map +1 -1
- package/clinkx-workflows/dist/workspace-signature.d.ts +16 -0
- package/clinkx-workflows/dist/workspace-signature.js +388 -0
- package/clinkx-workflows/dist/workspace-signature.js.map +1 -0
- package/clinkx-workflows/templates/council/answer-specialist.txt +2 -1
- package/clinkx-workflows/templates/council/code-review-chairman.txt +13 -0
- package/clinkx-workflows/templates/council/code-review-cross-reviewer.txt +4 -1
- package/clinkx-workflows/templates/council/code-review-reviewer.txt +19 -3
- package/clinkx-workflows/templates/council/debug-debugger.txt +2 -1
- package/clinkx-workflows/templates/council/discover-analyst.txt +2 -1
- package/clinkx-workflows/templates/council/member.txt +2 -1
- package/clinkx-workflows/templates/council/plan-review-chairman.txt +68 -0
- package/clinkx-workflows/templates/council/plan-review-cross-reviewer.txt +51 -0
- package/clinkx-workflows/templates/council/plan-review-reviewer.txt +60 -0
- package/clinkx-workflows/templates/plan-review/chairman.txt +48 -0
- package/clinkx-workflows/templates/plan-review/cross-review.txt +52 -0
- package/clinkx-workflows/templates/plan-review/ranking.txt +16 -0
- package/clinkx-workflows/templates/plan-review/reviewer.txt +57 -0
- package/clinkx-workflows/workflows/council-answer.yaml +97 -8
- package/clinkx-workflows/workflows/council-code-review.yaml +103 -8
- package/clinkx-workflows/workflows/council-debug.yaml +97 -8
- package/clinkx-workflows/workflows/council-default.yaml +97 -8
- package/clinkx-workflows/workflows/council-discover.yaml +97 -8
- package/clinkx-workflows/workflows/council-plan-review.yaml +250 -0
- package/clinkx-workflows/workflows/plan-review-receipts.yaml +230 -0
- package/conf/adapters/agy.json +49 -0
- package/conf/adapters/claude.json +5 -0
- package/conf/adapters/codex-app-server.json +44 -0
- package/conf/adapters/codex.json +7 -2
- package/conf/adapters/glm.json +5 -0
- package/conf/adapters/grok.json +60 -0
- package/conf/adapters/hapi/agy.json +52 -0
- package/conf/adapters/hapi/claude.json +5 -0
- package/conf/adapters/hapi/codex.json +7 -2
- package/conf/adapters/hapi/glm.json +5 -0
- package/dist/activity-journal.d.ts +42 -0
- package/dist/activity-journal.js +381 -0
- package/dist/activity-journal.js.map +1 -0
- package/dist/allowed-roots.d.ts +41 -0
- package/dist/allowed-roots.js +125 -3
- package/dist/allowed-roots.js.map +1 -1
- package/dist/codex/activity-session-log.d.ts +14 -0
- package/dist/codex/activity-session-log.js +206 -0
- package/dist/codex/activity-session-log.js.map +1 -0
- package/dist/codex/agent-tools.d.ts +23 -0
- package/dist/codex/agent-tools.js +1270 -0
- package/dist/codex/agent-tools.js.map +1 -0
- package/dist/codex/app-server-client.d.ts +76 -0
- package/dist/codex/app-server-client.js +582 -0
- package/dist/codex/app-server-client.js.map +1 -0
- package/dist/codex/app-server-registry.d.ts +389 -0
- package/dist/codex/app-server-registry.js +1407 -0
- package/dist/codex/app-server-registry.js.map +1 -0
- package/dist/codex/client-types.d.ts +109 -0
- package/dist/codex/client-types.js +2 -0
- package/dist/codex/client-types.js.map +1 -0
- package/dist/codex/protocol.d.ts +5375 -0
- package/dist/codex/protocol.js +614 -0
- package/dist/codex/protocol.js.map +1 -0
- package/dist/codex/session.d.ts +263 -0
- package/dist/codex/session.js +466 -0
- package/dist/codex/session.js.map +1 -0
- package/dist/config.d.ts +185 -19
- package/dist/config.js +82 -16
- package/dist/config.js.map +1 -1
- package/dist/context-builder/anchors.d.ts +1 -0
- package/dist/context-builder/anchors.js +3 -0
- package/dist/context-builder/anchors.js.map +1 -1
- package/dist/context-builder/bundle.d.ts +35 -2
- package/dist/context-builder/bundle.js +342 -2417
- package/dist/context-builder/bundle.js.map +1 -1
- package/dist/context-builder/codemap.d.ts +5 -0
- package/dist/context-builder/codemap.js +387 -13
- package/dist/context-builder/codemap.js.map +1 -1
- package/dist/context-builder/config.d.ts +1 -0
- package/dist/context-builder/config.js +12 -0
- package/dist/context-builder/config.js.map +1 -1
- package/dist/context-builder/context-run-catalog.d.ts +17 -0
- package/dist/context-builder/context-run-catalog.js +99 -0
- package/dist/context-builder/context-run-catalog.js.map +1 -0
- package/dist/context-builder/delegate-packet.d.ts +37 -0
- package/dist/context-builder/delegate-packet.js +359 -67
- package/dist/context-builder/delegate-packet.js.map +1 -1
- package/dist/context-builder/delegate-validation.d.ts +10 -1
- package/dist/context-builder/delegate-validation.js +153 -41
- package/dist/context-builder/delegate-validation.js.map +1 -1
- package/dist/context-builder/delegate.d.ts +2 -0
- package/dist/context-builder/delegate.js +1 -0
- package/dist/context-builder/delegate.js.map +1 -1
- package/dist/context-builder/diagnostics.d.ts +11 -2
- package/dist/context-builder/diagnostics.js +39 -6
- package/dist/context-builder/diagnostics.js.map +1 -1
- package/dist/context-builder/discovery.d.ts +29 -1
- package/dist/context-builder/discovery.js +475 -175
- package/dist/context-builder/discovery.js.map +1 -1
- package/dist/context-builder/globs.js +10 -10
- package/dist/context-builder/globs.js.map +1 -1
- package/dist/context-builder/handler.d.ts +26 -2
- package/dist/context-builder/handler.js +1158 -2416
- package/dist/context-builder/handler.js.map +1 -1
- package/dist/context-builder/lifecycle-contract.d.ts +424 -0
- package/dist/context-builder/lifecycle-contract.js +523 -0
- package/dist/context-builder/lifecycle-contract.js.map +1 -0
- package/dist/context-builder/lifecycle-journal.d.ts +62 -0
- package/dist/context-builder/lifecycle-journal.js +88 -0
- package/dist/context-builder/lifecycle-journal.js.map +1 -0
- package/dist/context-builder/lifecycle-observer.d.ts +102 -0
- package/dist/context-builder/lifecycle-observer.js +258 -0
- package/dist/context-builder/lifecycle-observer.js.map +1 -0
- package/dist/context-builder/lifecycle-reconcile.d.ts +32 -0
- package/dist/context-builder/lifecycle-reconcile.js +191 -0
- package/dist/context-builder/lifecycle-reconcile.js.map +1 -0
- package/dist/context-builder/lifecycle-recovery.d.ts +2 -0
- package/dist/context-builder/lifecycle-recovery.js +14 -0
- package/dist/context-builder/lifecycle-recovery.js.map +1 -0
- package/dist/context-builder/path-signals.js +9 -5
- package/dist/context-builder/path-signals.js.map +1 -1
- package/dist/context-builder/progress.d.ts +3 -1
- package/dist/context-builder/progress.js +23 -0
- package/dist/context-builder/progress.js.map +1 -1
- package/dist/context-builder/receipt.d.ts +6 -4
- package/dist/context-builder/receipt.js +12 -1
- package/dist/context-builder/receipt.js.map +1 -1
- package/dist/context-builder/refine-handler.d.ts +14 -0
- package/dist/context-builder/refine-handler.js +790 -0
- package/dist/context-builder/refine-handler.js.map +1 -0
- package/dist/context-builder/review-coverage.d.ts +84 -0
- package/dist/context-builder/review-coverage.js +437 -0
- package/dist/context-builder/review-coverage.js.map +1 -0
- package/dist/context-builder/schema.d.ts +239 -1
- package/dist/context-builder/schema.js +112 -6
- package/dist/context-builder/schema.js.map +1 -1
- package/dist/context-builder/secrets.d.ts +28 -0
- package/dist/context-builder/secrets.js +1473 -44
- package/dist/context-builder/secrets.js.map +1 -1
- package/dist/context-builder/selection.d.ts +7 -3
- package/dist/context-builder/selection.js +200 -738
- package/dist/context-builder/selection.js.map +1 -1
- package/dist/context-builder/session-log-identity.d.ts +1 -0
- package/dist/context-builder/session-log-identity.js +66 -0
- package/dist/context-builder/session-log-identity.js.map +1 -0
- package/dist/context-builder/slice-range-math.d.ts +16 -0
- package/dist/context-builder/slice-range-math.js +137 -0
- package/dist/context-builder/slice-range-math.js.map +1 -0
- package/dist/context-builder/status.d.ts +22 -1
- package/dist/context-builder/status.js +59 -4
- package/dist/context-builder/status.js.map +1 -1
- package/dist/context-builder/storage.d.ts +35 -2
- package/dist/context-builder/storage.js +271 -14
- package/dist/context-builder/storage.js.map +1 -1
- package/dist/context-builder/token-estimate.d.ts +13 -2
- package/dist/context-builder/token-estimate.js +77 -4
- package/dist/context-builder/token-estimate.js.map +1 -1
- package/dist/context-builder/versions.d.ts +29 -0
- package/dist/context-builder/versions.js +30 -0
- package/dist/context-builder/versions.js.map +1 -0
- package/dist/context-builder/workflow-runner.d.ts +69 -0
- package/dist/context-builder/workflow-runner.js +1051 -0
- package/dist/context-builder/workflow-runner.js.map +1 -0
- package/dist/context-builder/write-watchdog.d.ts +14 -0
- package/dist/context-builder/write-watchdog.js +38 -0
- package/dist/context-builder/write-watchdog.js.map +1 -0
- package/dist/dashboard-adapter-catalog.d.ts +9 -0
- package/dist/dashboard-adapter-catalog.js +46 -0
- package/dist/dashboard-adapter-catalog.js.map +1 -0
- package/dist/dashboard-cli.d.ts +79 -0
- package/dist/dashboard-cli.js +585 -0
- package/dist/dashboard-cli.js.map +1 -0
- package/dist/dashboard-companion/client.d.ts +36 -0
- package/dist/dashboard-companion/client.js +210 -0
- package/dist/dashboard-companion/client.js.map +1 -0
- package/dist/dashboard-companion/config.d.ts +8 -0
- package/dist/dashboard-companion/config.js +52 -0
- package/dist/dashboard-companion/config.js.map +1 -0
- package/dist/dashboard-companion/http-proxy.d.ts +10 -0
- package/dist/dashboard-companion/http-proxy.js +234 -0
- package/dist/dashboard-companion/http-proxy.js.map +1 -0
- package/dist/dashboard-companion/protocol.d.ts +80 -0
- package/dist/dashboard-companion/protocol.js +455 -0
- package/dist/dashboard-companion/protocol.js.map +1 -0
- package/dist/dashboard-companion/standalone-assets.d.ts +12 -0
- package/dist/dashboard-companion/standalone-assets.js +72 -0
- package/dist/dashboard-companion/standalone-assets.js.map +1 -0
- package/dist/dashboard-companion/standalone-entry.d.ts +1 -0
- package/dist/dashboard-companion/standalone-entry.js +17 -0
- package/dist/dashboard-companion/standalone-entry.js.map +1 -0
- package/dist/dashboard-gateway/config.d.ts +9 -0
- package/dist/dashboard-gateway/config.js +44 -0
- package/dist/dashboard-gateway/config.js.map +1 -0
- package/dist/dashboard-gateway/index.d.ts +11 -0
- package/dist/dashboard-gateway/index.js +755 -0
- package/dist/dashboard-gateway/index.js.map +1 -0
- package/dist/dashboard-gateway/main.d.ts +1 -0
- package/dist/dashboard-gateway/main.js +25 -0
- package/dist/dashboard-gateway/main.js.map +1 -0
- package/dist/dashboard-pairing-token.d.ts +1 -0
- package/dist/dashboard-pairing-token.js +5 -0
- package/dist/dashboard-pairing-token.js.map +1 -0
- package/dist/elaris/client.d.ts +73 -0
- package/dist/elaris/client.js +825 -0
- package/dist/elaris/client.js.map +1 -0
- package/dist/elaris/config.d.ts +18 -0
- package/dist/elaris/config.js +75 -0
- package/dist/elaris/config.js.map +1 -0
- package/dist/elaris/errors.d.ts +41 -0
- package/dist/elaris/errors.js +205 -0
- package/dist/elaris/errors.js.map +1 -0
- package/dist/elaris/github-repo.d.ts +18 -0
- package/dist/elaris/github-repo.js +89 -0
- package/dist/elaris/github-repo.js.map +1 -0
- package/dist/elaris/index.d.ts +10 -0
- package/dist/elaris/index.js +11 -0
- package/dist/elaris/index.js.map +1 -0
- package/dist/elaris/redact.d.ts +89 -0
- package/dist/elaris/redact.js +423 -0
- package/dist/elaris/redact.js.map +1 -0
- package/dist/elaris/run-id.d.ts +5 -0
- package/dist/elaris/run-id.js +20 -0
- package/dist/elaris/run-id.js.map +1 -0
- package/dist/elaris/status.d.ts +45 -0
- package/dist/elaris/status.js +122 -0
- package/dist/elaris/status.js.map +1 -0
- package/dist/elaris/tool-schemas.d.ts +314 -0
- package/dist/elaris/tool-schemas.js +208 -0
- package/dist/elaris/tool-schemas.js.map +1 -0
- package/dist/elaris/tools.d.ts +73 -0
- package/dist/elaris/tools.js +1065 -0
- package/dist/elaris/tools.js.map +1 -0
- package/dist/elaris/types.d.ts +1541 -0
- package/dist/elaris/types.js +252 -0
- package/dist/elaris/types.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -1
- package/dist/handler.d.ts +4 -0
- package/dist/handler.js +10 -1
- package/dist/handler.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/local-clink-backend.d.ts +3 -0
- package/dist/local-clink-backend.js +4 -0
- package/dist/local-clink-backend.js.map +1 -1
- package/dist/package-info.d.ts +2 -0
- package/dist/package-info.js +18 -0
- package/dist/package-info.js.map +1 -0
- package/dist/parsers/codex-jsonl.js +48 -3
- package/dist/parsers/codex-jsonl.js.map +1 -1
- package/dist/parsers/extract.d.ts +10 -1
- package/dist/parsers/extract.js +11 -3
- package/dist/parsers/extract.js.map +1 -1
- package/dist/pipeline.d.ts +4 -0
- package/dist/pipeline.js +129 -8
- package/dist/pipeline.js.map +1 -1
- package/dist/run-dir.d.ts +24 -0
- package/dist/run-dir.js +201 -2
- package/dist/run-dir.js.map +1 -1
- package/dist/runner.d.ts +13 -0
- package/dist/runner.js +184 -15
- package/dist/runner.js.map +1 -1
- package/dist/safety.d.ts +4 -4
- package/dist/safety.js +4 -4
- package/dist/schema.d.ts +7 -7
- package/dist/server.d.ts +1 -0
- package/dist/server.js +359 -17
- package/dist/server.js.map +1 -1
- package/dist/session-log-stream.d.ts +18 -0
- package/dist/session-log-stream.js +319 -0
- package/dist/session-log-stream.js.map +1 -0
- package/package.json +46 -5
- package/conf/adapters/gemini.json +0 -44
- package/conf/adapters/hapi/gemini.json +0 -47
- package/dist/parsers/gemini-json.d.ts +0 -2
- package/dist/parsers/gemini-json.js +0 -72
- package/dist/parsers/gemini-json.js.map +0 -1
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { realpathSync, statSync } from "node:fs";
|
|
3
|
+
import { copyFile, mkdir, readFile, realpath, rename, rm, utimes, } from "node:fs/promises";
|
|
4
|
+
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Deep `clinkx-workflows/dist` imports (one-way dependency, build-order coupled)
|
|
7
|
+
//
|
|
8
|
+
// The next four imports pull cache-key, preflight-contract, config, and
|
|
9
|
+
// workspace-signature helpers from the COMPILED output of the sibling
|
|
10
|
+
// `clinkx-workflows` package rather than from a published entry point. This is
|
|
11
|
+
// deliberate and safe:
|
|
12
|
+
//
|
|
13
|
+
// - The dependency arrow points one way: root -> clinkx-workflows. The
|
|
14
|
+
// workflows package defines only the `ContextBuilderRunner` callback
|
|
15
|
+
// interface and never statically imports the root `context-builder/`
|
|
16
|
+
// modules, so there is no import cycle. See docs/architecture.md, "Module
|
|
17
|
+
// boundary (no dependency cycle)".
|
|
18
|
+
// - `clinkx-workflows` is a separate tsc project with no package `exports`
|
|
19
|
+
// map; its public runtime surface is its `dist/*.js` files. Importing its
|
|
20
|
+
// source `.ts` would violate the NodeNext + `.js`-extension ESM contract.
|
|
21
|
+
//
|
|
22
|
+
// BUILD ORDER: `clinkx-workflows/dist` MUST be built before the root package is
|
|
23
|
+
// built or run. `npm run build:all` enforces this (clinkx-workflows first, then
|
|
24
|
+
// root). A bare `npm run build` assumes dist already exists; a missing dist
|
|
25
|
+
// surfaces as ERR_MODULE_NOT_FOUND at import time, not a compile error.
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
import { computeCacheKey, computeInputsHash, deriveWfctxId, } from "../../clinkx-workflows/dist/context-cache-key.js";
|
|
28
|
+
import { resolveWorkspaceRoot as resolveWorkflowWorkspaceRoot } from "../../clinkx-workflows/dist/config.js";
|
|
29
|
+
import { createSessionLogGeneration, readSessionLogGeneration, } from "../../clinkx-workflows/dist/dashboard/session-log-identity.js";
|
|
30
|
+
import { getSignatureCoveredPaths, workspaceSignature as computeWorkspaceSignature, } from "../../clinkx-workflows/dist/workspace-signature.js";
|
|
31
|
+
import { isArtifactOnlyAllowedRootEntry, isPathWithinAllowedRoots, } from "../allowed-roots.js";
|
|
32
|
+
import { CancellationError, ExecutionError, InvalidParamsError } from "../errors.js";
|
|
33
|
+
import { logger } from "../logger.js";
|
|
34
|
+
import { getCurrentAllowedRoots } from "../paths.js";
|
|
35
|
+
import { CONTEXT_BUILDER_RENDERER_VERSION } from "./bundle.js";
|
|
36
|
+
import { CONTEXT_DELEGATE_PROMPT_VERSION, CONTEXT_DISCOVERY_ALGORITHM_VERSION, } from "./versions.js";
|
|
37
|
+
import { getSharedContextBuilderSemaphore, resolveContextBuilderRunsDir, } from "./config.js";
|
|
38
|
+
import { handleContextBuilder } from "./handler.js";
|
|
39
|
+
import { CONTEXT_BUILDER_INTENT_PROFILE_DEFAULTS, CONTEXT_BUILDER_INTENT_PROFILES, resolveContextBuilderAdapterBudgetInput, } from "./schema.js";
|
|
40
|
+
import { assertNoHighConfidenceSecretsInTask, resolveAllowSecrets, } from "./secrets.js";
|
|
41
|
+
import { CONTEXT_BUILDER_DELEGATE_SCHEMA_VERSION, CONTEXT_BUILDER_NO_DELEGATE_SCHEMA_VERSION, createContextBuilderReceipt, } from "./receipt.js";
|
|
42
|
+
import { notEvaluatedCoverageReport, } from "./review-coverage.js";
|
|
43
|
+
import { isContextBuilderRunCommitted, evictWorkflowContextRuns, promoteContextBuilderRun, resolveContextBuilderRunPaths, withContextBuilderRunMutationLease, } from "./storage.js";
|
|
44
|
+
import { ContextBuilderLifecycleController, ContextBuilderLifecycleObserverError, } from "./lifecycle-observer.js";
|
|
45
|
+
export function createWorkflowContextBuilderRunner(options = {}) {
|
|
46
|
+
const cb = options.handleContextBuilder ?? handleContextBuilder;
|
|
47
|
+
// Default to the SHARED process-wide context_builder gate so workflow
|
|
48
|
+
// preflight, standalone context_builder, and refine_context_run all contend
|
|
49
|
+
// for one CLINKX_CONTEXT_BUILDER_MAX_CONCURRENT permit pool. Tests may inject
|
|
50
|
+
// their own semaphore for isolation.
|
|
51
|
+
const semaphore = options.semaphore ?? getSharedContextBuilderSemaphore();
|
|
52
|
+
const runIdFactory = options.runIdFactory ?? generateWorkflowPreflightRunId;
|
|
53
|
+
const workspaceRootResolver = options.resolveWorkspaceRoot ?? resolveWorkflowWorkspaceRoot;
|
|
54
|
+
const workspaceSignature = options.workspaceSignature ?? computeWorkspaceSignature;
|
|
55
|
+
const signatureCoveredPaths = options.getSignatureCoveredPaths ?? getSignatureCoveredPaths;
|
|
56
|
+
const rendererVersion = options.rendererVersion ?? CONTEXT_BUILDER_RENDERER_VERSION;
|
|
57
|
+
const discoveryAlgorithmVersion = options.discoveryAlgorithmVersion ?? CONTEXT_DISCOVERY_ALGORITHM_VERSION;
|
|
58
|
+
const delegatePromptVersion = options.delegatePromptVersion ?? CONTEXT_DELEGATE_PROMPT_VERSION;
|
|
59
|
+
const registry = options.registry;
|
|
60
|
+
return {
|
|
61
|
+
assertRootsAllowed(roots) {
|
|
62
|
+
assertExplicitRootsWithinAllowed(roots);
|
|
63
|
+
},
|
|
64
|
+
assertTaskSecretsAllowed(variables) {
|
|
65
|
+
const rawFlag = variables["cb_allow_secrets"];
|
|
66
|
+
const explicit = typeof rawFlag === "boolean" ? rawFlag : undefined;
|
|
67
|
+
if (resolveAllowSecrets(explicit)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
for (const key of ["cb_task", "user_request"]) {
|
|
71
|
+
const value = variables[key];
|
|
72
|
+
if (typeof value === "string" && value.length > 0) {
|
|
73
|
+
assertNoHighConfidenceSecretsInTask(value);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async runOrReuse(input, opts) {
|
|
78
|
+
let lifecycle;
|
|
79
|
+
try {
|
|
80
|
+
throwIfAborted(opts.signal);
|
|
81
|
+
const mappedInput = await mapPreflightContextInput(input, {
|
|
82
|
+
resolveWorkspaceRoot: workspaceRootResolver,
|
|
83
|
+
});
|
|
84
|
+
const mapped = input.context_budget_adapter == null ||
|
|
85
|
+
input.context_budget_adapter.trim() === ""
|
|
86
|
+
? mappedInput
|
|
87
|
+
: {
|
|
88
|
+
...mappedInput,
|
|
89
|
+
budget: resolveContextBuilderAdapterBudgetInput({
|
|
90
|
+
adapterDefaults: resolveAdapterBudgetDefaults(registry, input.context_budget_adapter),
|
|
91
|
+
profile: mappedInput.profile,
|
|
92
|
+
explicit: mappedInput.budget,
|
|
93
|
+
}),
|
|
94
|
+
};
|
|
95
|
+
const lifecycleInjection = options.lifecycleFactory?.(input);
|
|
96
|
+
lifecycle = lifecycleInjection == null
|
|
97
|
+
? undefined
|
|
98
|
+
: new ContextBuilderLifecycleController({
|
|
99
|
+
operationKind: "workflow_preflight",
|
|
100
|
+
execution: workflowLifecycleExecutionConfig(mapped),
|
|
101
|
+
observer: lifecycleInjection.observer,
|
|
102
|
+
...(lifecycleInjection.origin == null
|
|
103
|
+
? {}
|
|
104
|
+
: { origin: lifecycleInjection.origin }),
|
|
105
|
+
...(options.lifecycleNow == null
|
|
106
|
+
? {}
|
|
107
|
+
: { now: options.lifecycleNow }),
|
|
108
|
+
});
|
|
109
|
+
await lifecycle?.transition("resolving");
|
|
110
|
+
// The controller has now minted the preflight operation id
|
|
111
|
+
// (lifecycle.contextRunId). Pair it with a generation sidecar created under
|
|
112
|
+
// the workflow run dir so the dashboard can later locate the preflight's
|
|
113
|
+
// session-log subtree. Only the injected-lifecycle (workflow) path builds
|
|
114
|
+
// this; the standalone path derives its own identity from its journal.
|
|
115
|
+
const preflightSessionLogContext = lifecycle == null
|
|
116
|
+
? undefined
|
|
117
|
+
: await resolvePreflightSessionLogContext(input.runDir, lifecycle.contextRunId);
|
|
118
|
+
const cacheInput = {
|
|
119
|
+
...mapped,
|
|
120
|
+
roots: await normalizeCacheRoots(mapped.roots),
|
|
121
|
+
};
|
|
122
|
+
const includeSelectedContext = input.includeSelectedContext === true;
|
|
123
|
+
const effectiveSchemaVersion = mapped.delegate.enabled === true
|
|
124
|
+
? CONTEXT_BUILDER_DELEGATE_SCHEMA_VERSION
|
|
125
|
+
: CONTEXT_BUILDER_NO_DELEGATE_SCHEMA_VERSION;
|
|
126
|
+
const cacheSchemaVersion = options.cbSchemaVersion ?? effectiveSchemaVersion;
|
|
127
|
+
const runsDir = await resolveContextBuilderRunsDir(options.runsDir);
|
|
128
|
+
let preSig = await workspaceSignature(mapped.roots);
|
|
129
|
+
throwIfAborted(opts.signal);
|
|
130
|
+
let cache = deriveCacheCoordinates(cacheInput, preSig, runsDir, {
|
|
131
|
+
rendererVersion,
|
|
132
|
+
cbSchemaVersion: cacheSchemaVersion,
|
|
133
|
+
discoveryAlgorithmVersion,
|
|
134
|
+
delegatePromptVersion,
|
|
135
|
+
});
|
|
136
|
+
let cacheReason = "cache_miss";
|
|
137
|
+
if (await isContextBuilderRunCommitted(cache.targetStorage.runDir)) {
|
|
138
|
+
const postSig = await workspaceSignature(mapped.roots);
|
|
139
|
+
throwIfAborted(opts.signal);
|
|
140
|
+
if (postSig === preSig) {
|
|
141
|
+
const hit = await withContextBuilderRunMutationLease(cache.targetStorage, async () => {
|
|
142
|
+
// The unleased probe above is only an optimization. Pruning may
|
|
143
|
+
// win before this lease is acquired, so re-check under the lock
|
|
144
|
+
// before reading the manifest or materializing any artifact.
|
|
145
|
+
if (!await isContextBuilderRunCommitted(cache.targetStorage.runDir)) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
// Refresh directory mtime so LRU eviction treats this as recently used.
|
|
149
|
+
try {
|
|
150
|
+
const now = new Date();
|
|
151
|
+
await utimes(cache.targetStorage.runDir, now, now);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// best-effort — a hit must not fail because utimes failed
|
|
155
|
+
}
|
|
156
|
+
return await synthesizePreflightResultFromCommittedRun({
|
|
157
|
+
storage: cache.targetStorage,
|
|
158
|
+
runDir: input.runDir,
|
|
159
|
+
keyPrefix: cache.keyPrefix,
|
|
160
|
+
schemaVersion: effectiveSchemaVersion,
|
|
161
|
+
budgetCaps: mapped.budget,
|
|
162
|
+
includeSelectedContext,
|
|
163
|
+
...(lifecycle == null ? {} : { lifecycle }),
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
if (hit !== undefined) {
|
|
167
|
+
await lifecycle?.complete(workflowLifecycleTerminalStatus(hit), {
|
|
168
|
+
artifactRunId: hit.source_run_id,
|
|
169
|
+
...workflowResultLifecyclePatch(hit, lifecycle, true),
|
|
170
|
+
});
|
|
171
|
+
return hit;
|
|
172
|
+
}
|
|
173
|
+
cacheReason = "cache_stale";
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
cacheReason = "cache_stale";
|
|
177
|
+
preSig = postSig;
|
|
178
|
+
cache = deriveCacheCoordinates(cacheInput, preSig, runsDir, {
|
|
179
|
+
rendererVersion,
|
|
180
|
+
cbSchemaVersion: cacheSchemaVersion,
|
|
181
|
+
discoveryAlgorithmVersion,
|
|
182
|
+
delegatePromptVersion,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
await lifecycle?.transition("cache_lookup", {
|
|
187
|
+
cache: {
|
|
188
|
+
lookup: "miss",
|
|
189
|
+
write: "not_attempted",
|
|
190
|
+
reason_code: cacheReason,
|
|
191
|
+
},
|
|
192
|
+
reasonCodes: [cacheReason],
|
|
193
|
+
});
|
|
194
|
+
const tempId = runIdFactory();
|
|
195
|
+
const tempInput = { ...mapped, run_id: tempId };
|
|
196
|
+
const response = await cb(tempInput, {
|
|
197
|
+
runsDir,
|
|
198
|
+
semaphore,
|
|
199
|
+
...(registry == null ? {} : { registry }),
|
|
200
|
+
...(input.allowRootWideDiscovery == null
|
|
201
|
+
? {}
|
|
202
|
+
: { allowRootWideDiscovery: input.allowRootWideDiscovery }),
|
|
203
|
+
...(opts.signal == null ? {} : { signal: opts.signal }),
|
|
204
|
+
...(lifecycle == null ? {} : { lifecycleController: lifecycle }),
|
|
205
|
+
...(preflightSessionLogContext == null
|
|
206
|
+
? {}
|
|
207
|
+
: { sessionLogContext: preflightSessionLogContext }),
|
|
208
|
+
});
|
|
209
|
+
throwIfAborted(opts.signal);
|
|
210
|
+
const receipt = parseReceiptResponse(response);
|
|
211
|
+
const tempStorage = resolveContextBuilderRunPaths(runsDir, tempId);
|
|
212
|
+
// The id of the run this call will return as its live source. Eviction in
|
|
213
|
+
// the finally must protect it so small/zero retention bounds cannot delete
|
|
214
|
+
// the run whose source_artifact_dir we are about to hand back.
|
|
215
|
+
let liveSourceRunId = tempId;
|
|
216
|
+
try {
|
|
217
|
+
const tempManifest = await readManifest(tempStorage.manifestJson);
|
|
218
|
+
// Degraded fallback selections (delegate failure_policy:"fallback") must
|
|
219
|
+
// NEVER enter the shared wfctx cache: a cached fallback would be replayed
|
|
220
|
+
// for a later fail-closed failure_policy:"fail" request (silently
|
|
221
|
+
// succeeding instead of failing) and would mask genuine delegated
|
|
222
|
+
// successes. Not caching also lets a later identical request retry
|
|
223
|
+
// delegation rather than reusing a stale degraded bundle. The manifest
|
|
224
|
+
// is the authoritative persisted source; fall back to the receipt.
|
|
225
|
+
const fallbackUsed = tempManifest.delegate?.fallback_used === true ||
|
|
226
|
+
receipt.delegate?.fallback_used === true;
|
|
227
|
+
const selectedPaths = await resolveSelectedContextPaths(tempManifest, mapped.roots);
|
|
228
|
+
const gate = await evaluatePostCbPromotionGate({
|
|
229
|
+
roots: mapped.roots,
|
|
230
|
+
selectedPaths,
|
|
231
|
+
workspaceSignature,
|
|
232
|
+
signatureCoveredPaths,
|
|
233
|
+
});
|
|
234
|
+
throwIfAborted(opts.signal);
|
|
235
|
+
if (!fallbackUsed && gate?.selectedFilesCovered === true && gate.postSig === preSig) {
|
|
236
|
+
try {
|
|
237
|
+
await lifecycle?.transition("materializing");
|
|
238
|
+
const promoted = await promoteContextBuilderRun(tempStorage.runDir, cache.wfctxId);
|
|
239
|
+
// Promote succeeded and renamed temp → wfctx: protect the wfctx run
|
|
240
|
+
// immediately so a later throw (e.g. copyBundleArtifactsIntoRun) can
|
|
241
|
+
// never leave the freshly-promoted run unprotected against zero/small
|
|
242
|
+
// retention eviction in the finally.
|
|
243
|
+
liveSourceRunId = cache.wfctxId;
|
|
244
|
+
// Copy from the PROMOTED wfctx run (the temp dir is now deleted) so
|
|
245
|
+
// the fanned manifest's run_id matches the returned source_run_id and
|
|
246
|
+
// its artifact paths point at live files.
|
|
247
|
+
const promotedManifest = await readManifest(promoted.manifestJson);
|
|
248
|
+
const resultBeforeMaterialization = buildPreflightResult({
|
|
249
|
+
receipt: createReceiptFromManifest(promotedManifest, promoted),
|
|
250
|
+
sourceRunId: cache.wfctxId,
|
|
251
|
+
sourceArtifactDir: promoted.runDir,
|
|
252
|
+
cache: {
|
|
253
|
+
hit: false,
|
|
254
|
+
write: true,
|
|
255
|
+
target_id: cache.wfctxId,
|
|
256
|
+
key_prefix: cache.keyPrefix,
|
|
257
|
+
},
|
|
258
|
+
copiedPaths: [],
|
|
259
|
+
schemaVersion: effectiveSchemaVersion,
|
|
260
|
+
observability: preflightObservabilityFromManifest(tempManifest, mapped.budget),
|
|
261
|
+
coverage: coverageFromManifest(tempManifest),
|
|
262
|
+
});
|
|
263
|
+
const copiedPaths = await copyBundleArtifactsIntoRun(promotedManifest.artifacts, input.runDir, {
|
|
264
|
+
includeSelectedContext,
|
|
265
|
+
...(lifecycle == null
|
|
266
|
+
? {}
|
|
267
|
+
: {
|
|
268
|
+
beforeManifestCommit: async () => {
|
|
269
|
+
await lifecycle?.transition("committing", {
|
|
270
|
+
artifactRunId: resultBeforeMaterialization.source_run_id,
|
|
271
|
+
cache: {
|
|
272
|
+
lookup: "miss",
|
|
273
|
+
write: "written",
|
|
274
|
+
reason_code: cacheReason,
|
|
275
|
+
},
|
|
276
|
+
...workflowResultLifecyclePatch(resultBeforeMaterialization, lifecycle),
|
|
277
|
+
});
|
|
278
|
+
},
|
|
279
|
+
}),
|
|
280
|
+
});
|
|
281
|
+
const result = {
|
|
282
|
+
...resultBeforeMaterialization,
|
|
283
|
+
copied_paths: copiedPaths,
|
|
284
|
+
};
|
|
285
|
+
await lifecycle?.complete(workflowLifecycleTerminalStatus(result), {
|
|
286
|
+
artifactRunId: result.source_run_id,
|
|
287
|
+
...workflowResultLifecyclePatch(result, lifecycle),
|
|
288
|
+
});
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
if (!isPromoteClaimConflict(error)) {
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Non-promote (or promote-claim-conflict) path: copy from the surviving
|
|
298
|
+
// temp run, which is the authoritative source for the returned id.
|
|
299
|
+
await lifecycle?.transition("materializing");
|
|
300
|
+
const resultBeforeMaterialization = buildPreflightResult({
|
|
301
|
+
receipt: createReceiptFromManifest(tempManifest, tempStorage),
|
|
302
|
+
sourceRunId: tempId,
|
|
303
|
+
sourceArtifactDir: tempStorage.runDir,
|
|
304
|
+
cache: {
|
|
305
|
+
hit: false,
|
|
306
|
+
write: false,
|
|
307
|
+
target_id: null,
|
|
308
|
+
key_prefix: cache.keyPrefix,
|
|
309
|
+
},
|
|
310
|
+
copiedPaths: [],
|
|
311
|
+
schemaVersion: effectiveSchemaVersion,
|
|
312
|
+
observability: preflightObservabilityFromManifest(tempManifest, mapped.budget),
|
|
313
|
+
coverage: coverageFromManifest(tempManifest),
|
|
314
|
+
});
|
|
315
|
+
const copiedPaths = await copyBundleArtifactsIntoRun(tempManifest.artifacts, input.runDir, {
|
|
316
|
+
includeSelectedContext,
|
|
317
|
+
...(lifecycle == null
|
|
318
|
+
? {}
|
|
319
|
+
: {
|
|
320
|
+
beforeManifestCommit: async () => {
|
|
321
|
+
await lifecycle?.transition("committing", {
|
|
322
|
+
artifactRunId: resultBeforeMaterialization.source_run_id,
|
|
323
|
+
cache: {
|
|
324
|
+
lookup: "miss",
|
|
325
|
+
write: "skipped",
|
|
326
|
+
reason_code: cacheReason,
|
|
327
|
+
},
|
|
328
|
+
...workflowResultLifecyclePatch(resultBeforeMaterialization, lifecycle),
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
}),
|
|
332
|
+
});
|
|
333
|
+
const result = {
|
|
334
|
+
...resultBeforeMaterialization,
|
|
335
|
+
copied_paths: copiedPaths,
|
|
336
|
+
};
|
|
337
|
+
await lifecycle?.complete(workflowLifecycleTerminalStatus(result), {
|
|
338
|
+
artifactRunId: result.source_run_id,
|
|
339
|
+
...workflowResultLifecyclePatch(result, lifecycle),
|
|
340
|
+
});
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
finally {
|
|
344
|
+
// Best-effort, prefix-scoped/TTL-guarded eviction on every completed
|
|
345
|
+
// MISS path (promote and non-promote). The active source run of this
|
|
346
|
+
// call is protected so zero/small retention bounds cannot self-delete
|
|
347
|
+
// the run whose source_artifact_dir we just returned.
|
|
348
|
+
await evictWorkflowContextRuns(runsDir, {
|
|
349
|
+
protectedRunIds: [liveSourceRunId],
|
|
350
|
+
})
|
|
351
|
+
.then((eviction) => {
|
|
352
|
+
if (eviction.failed > 0) {
|
|
353
|
+
logger.warn({ runsDir, eviction }, "workflow context_builder cache eviction had delete failures");
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
.catch((err) => {
|
|
357
|
+
logger.warn({ err, runsDir }, "workflow context_builder cache eviction failed");
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
if (lifecycle != null && !(error instanceof ContextBuilderLifecycleObserverError)) {
|
|
363
|
+
const cancelled = error instanceof CancellationError || opts.signal?.aborted === true;
|
|
364
|
+
const delegateFailed = workflowDelegateExecutionActive(lifecycle);
|
|
365
|
+
await lifecycle.fail(cancelled ? "cancelled" : "failed", {
|
|
366
|
+
...workflowTerminalExecutionPatch(lifecycle, cancelled),
|
|
367
|
+
reasonCodes: [
|
|
368
|
+
cancelled
|
|
369
|
+
? "operation_cancelled"
|
|
370
|
+
: delegateFailed
|
|
371
|
+
? "delegate_failed"
|
|
372
|
+
: "internal_failure",
|
|
373
|
+
],
|
|
374
|
+
...(!cancelled && delegateFailed
|
|
375
|
+
? {
|
|
376
|
+
fallback: {
|
|
377
|
+
status: "failed",
|
|
378
|
+
reason_code: "delegate_failed",
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
: {}),
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
// Rethrow the ORIGINAL error object, never a wrapper: markers set by
|
|
385
|
+
// the handler (e.g. ExecutionError.failureClass:"transient" on a
|
|
386
|
+
// delegate timeout) must reach the workflow engine's failure
|
|
387
|
+
// classifier intact.
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Subdirectory of the workflow run dir holding the preflight session-log
|
|
395
|
+
* generation sidecar. The dashboard reads this back to locate the preflight's
|
|
396
|
+
* session-log subtree and to pair it with the persisted lifecycle context_run_id.
|
|
397
|
+
*/
|
|
398
|
+
const PREFLIGHT_SESSION_LOG_DIR = ".context-preflight";
|
|
399
|
+
/**
|
|
400
|
+
* Create-or-read the preflight session-log generation sidecar under the workflow
|
|
401
|
+
* run dir, then pair it with the controller-minted operation id. Create-or-read
|
|
402
|
+
* (rather than exclusive-create) keeps the generation stable across retries of
|
|
403
|
+
* the same run. Best-effort: any failure resolves to undefined, and the preflight
|
|
404
|
+
* renders without a `[ log ]` affordance (the prior telemetry-only contract).
|
|
405
|
+
*/
|
|
406
|
+
async function resolvePreflightSessionLogContext(runDir, contextRunId) {
|
|
407
|
+
try {
|
|
408
|
+
const sidecarDir = join(runDir, PREFLIGHT_SESSION_LOG_DIR);
|
|
409
|
+
await mkdir(sidecarDir, { recursive: true, mode: 0o700 });
|
|
410
|
+
const existing = await readSessionLogGeneration(sidecarDir);
|
|
411
|
+
const contextGeneration = existing.kind === "available"
|
|
412
|
+
? existing.sessionLogGeneration
|
|
413
|
+
: await createSessionLogGeneration(sidecarDir);
|
|
414
|
+
return { contextRunId, contextGeneration };
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
return undefined;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function workflowLifecycleExecutionConfig(input) {
|
|
421
|
+
if (input.delegate.enabled !== true) {
|
|
422
|
+
return {
|
|
423
|
+
curator: { configured: false, enabled: false },
|
|
424
|
+
finalizer: { configured: false, enabled: false },
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
const finalizerEnabled = input.delegate.finalizer.enabled ??
|
|
428
|
+
(input.profile == null
|
|
429
|
+
? true
|
|
430
|
+
: CONTEXT_BUILDER_INTENT_PROFILE_DEFAULTS[input.profile].finalizer_enabled);
|
|
431
|
+
return {
|
|
432
|
+
curator: { configured: true, enabled: true },
|
|
433
|
+
finalizer: { configured: true, enabled: finalizerEnabled },
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function workflowLifecycleTerminalStatus(result) {
|
|
437
|
+
return result.delegate?.fallback_used === true || result.status === "partial"
|
|
438
|
+
? "partial"
|
|
439
|
+
: "succeeded";
|
|
440
|
+
}
|
|
441
|
+
function workflowResultLifecyclePatch(result, lifecycle, cacheHit = false) {
|
|
442
|
+
const coverage = result.coverage ?? notEvaluatedCoverageReport();
|
|
443
|
+
const required = coverage.required_when_available.length;
|
|
444
|
+
const missing = coverage.missing_required.length;
|
|
445
|
+
const snapshot = lifecycle?.snapshot;
|
|
446
|
+
const executionPatch = cacheHit
|
|
447
|
+
? {
|
|
448
|
+
...(snapshot?.curator.effective_enabled === true
|
|
449
|
+
? { curatorStatus: "skipped" }
|
|
450
|
+
: {}),
|
|
451
|
+
...(snapshot?.finalizer.effective_enabled === true
|
|
452
|
+
? { finalizerStatus: "skipped" }
|
|
453
|
+
: {}),
|
|
454
|
+
}
|
|
455
|
+
: result.delegate?.fallback_used === true
|
|
456
|
+
? {
|
|
457
|
+
...(snapshot?.curator.effective_enabled === true
|
|
458
|
+
? { curatorStatus: "failed" }
|
|
459
|
+
: {}),
|
|
460
|
+
...(snapshot?.finalizer.effective_enabled === true
|
|
461
|
+
? { finalizerStatus: "skipped" }
|
|
462
|
+
: {}),
|
|
463
|
+
fallback: {
|
|
464
|
+
status: "used",
|
|
465
|
+
reason_code: "delegate_fallback",
|
|
466
|
+
},
|
|
467
|
+
reasonCodes: ["delegate_fallback"],
|
|
468
|
+
}
|
|
469
|
+
: {
|
|
470
|
+
...(snapshot?.curator.effective_enabled === true &&
|
|
471
|
+
snapshot.curator.execution_status === "pending"
|
|
472
|
+
? { curatorStatus: "succeeded" }
|
|
473
|
+
: {}),
|
|
474
|
+
...(snapshot?.finalizer.effective_enabled === true &&
|
|
475
|
+
snapshot.finalizer.execution_status === "pending"
|
|
476
|
+
? { finalizerStatus: "succeeded" }
|
|
477
|
+
: {}),
|
|
478
|
+
};
|
|
479
|
+
return {
|
|
480
|
+
...executionPatch,
|
|
481
|
+
counts: {
|
|
482
|
+
files_seen: cacheHit ? 0 : result.metrics.files_seen,
|
|
483
|
+
files_considered: cacheHit ? 0 : result.metrics.files_considered,
|
|
484
|
+
files_selected: result.metrics.files_selected,
|
|
485
|
+
files_omitted: cacheHit ? 0 : result.metrics.files_omitted,
|
|
486
|
+
search_results: cacheHit ? 0 : snapshot?.counts.search_results ?? 0,
|
|
487
|
+
bytes_read: cacheHit ? 0 : result.metrics.bytes_read,
|
|
488
|
+
bytes_written: result.metrics.bytes_written,
|
|
489
|
+
},
|
|
490
|
+
coverage: {
|
|
491
|
+
policy: coverage.policy_id,
|
|
492
|
+
status: coverage.status,
|
|
493
|
+
required,
|
|
494
|
+
selected: Math.max(0, required - missing),
|
|
495
|
+
missing,
|
|
496
|
+
},
|
|
497
|
+
...(coverage.status === "degraded"
|
|
498
|
+
? { reasonCodes: [...(executionPatch.reasonCodes ?? []), "coverage_degraded"] }
|
|
499
|
+
: {}),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
function workflowTerminalExecutionPatch(lifecycle, cancelled) {
|
|
503
|
+
const snapshot = lifecycle.snapshot;
|
|
504
|
+
if (snapshot == null)
|
|
505
|
+
return {};
|
|
506
|
+
const terminalStatus = cancelled ? "cancelled" : "failed";
|
|
507
|
+
return {
|
|
508
|
+
...(snapshot.curator.execution_status === "running"
|
|
509
|
+
? { curatorStatus: terminalStatus }
|
|
510
|
+
: snapshot.curator.execution_status === "pending"
|
|
511
|
+
? { curatorStatus: "skipped" }
|
|
512
|
+
: {}),
|
|
513
|
+
...(snapshot.finalizer.execution_status === "running"
|
|
514
|
+
? { finalizerStatus: terminalStatus }
|
|
515
|
+
: snapshot.finalizer.execution_status === "pending"
|
|
516
|
+
? { finalizerStatus: "skipped" }
|
|
517
|
+
: {}),
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function workflowDelegateExecutionActive(lifecycle) {
|
|
521
|
+
const snapshot = lifecycle.snapshot;
|
|
522
|
+
return snapshot?.curator.execution_status === "running" ||
|
|
523
|
+
snapshot?.finalizer.execution_status === "running";
|
|
524
|
+
}
|
|
525
|
+
export async function copyBundleIntoRun(receipt, runDir, options = {}) {
|
|
526
|
+
return copyBundleArtifactsIntoRun(receipt.artifacts, runDir, options);
|
|
527
|
+
}
|
|
528
|
+
export async function copyBundleArtifactsIntoRun(artifacts, runDir, options = {}) {
|
|
529
|
+
const runRoot = await realpath(runDir);
|
|
530
|
+
const contextDir = join(runRoot, "artifacts", "context");
|
|
531
|
+
await mkdir(contextDir, { recursive: true });
|
|
532
|
+
const realContextDir = await realpath(contextDir);
|
|
533
|
+
const bundleDest = await copyArtifactIntoContextDir(await resolveArtifactPath(artifacts, "bundle_md", "bundle.md"), realContextDir, "bundle.md");
|
|
534
|
+
const selectedContextDest = options.includeSelectedContext === true
|
|
535
|
+
? await copyArtifactIntoContextDir(await resolveArtifactPath(artifacts, "selected_context_jsonl", "selected-context.jsonl"), realContextDir, "selected-context.jsonl")
|
|
536
|
+
: undefined;
|
|
537
|
+
const manifestSource = await resolveArtifactPath(artifacts, "manifest_json", "manifest.json");
|
|
538
|
+
await options.beforeManifestCommit?.();
|
|
539
|
+
const manifestDest = await copyArtifactIntoContextDir(manifestSource, realContextDir, "manifest.json");
|
|
540
|
+
return selectedContextDest == null
|
|
541
|
+
? [bundleDest, manifestDest]
|
|
542
|
+
: [bundleDest, selectedContextDest, manifestDest];
|
|
543
|
+
}
|
|
544
|
+
export async function mapPreflightContextInput(input, options) {
|
|
545
|
+
assertExplicitRootsWithinAllowed(input.roots);
|
|
546
|
+
const task = input.cb_task.trim() === "" ? input.user_request : input.cb_task;
|
|
547
|
+
const roots = input.roots.length > 0
|
|
548
|
+
? [...input.roots]
|
|
549
|
+
: [await resolveFallbackRoot(options.resolveWorkspaceRoot)];
|
|
550
|
+
const profile = validateProfile(input.profile);
|
|
551
|
+
return {
|
|
552
|
+
task,
|
|
553
|
+
roots,
|
|
554
|
+
focus_paths: [...input.focus_paths],
|
|
555
|
+
include_globs: [...input.include_globs],
|
|
556
|
+
exclude_globs: [...input.exclude_globs],
|
|
557
|
+
search_terms: [...input.search_terms],
|
|
558
|
+
allow_secrets: resolveAllowSecrets(input.allow_secrets),
|
|
559
|
+
budget: input.budget ?? {},
|
|
560
|
+
delegate: input.delegate ?? { enabled: false },
|
|
561
|
+
...(options.run_id == null ? {} : { run_id: options.run_id }),
|
|
562
|
+
...(profile == null ? {} : { profile }),
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
// cb_budget_adapter is intentionally backend-agnostic: this only reads numeric
|
|
566
|
+
// context_builder.budget_defaults and NEVER executes the adapter, so app_server
|
|
567
|
+
// adapters are permitted here even though they are rejected for execution.
|
|
568
|
+
function resolveAdapterBudgetDefaults(registry, name) {
|
|
569
|
+
const trimmed = name?.trim();
|
|
570
|
+
if (trimmed == null || trimmed === "") {
|
|
571
|
+
return {};
|
|
572
|
+
}
|
|
573
|
+
if (registry == null) {
|
|
574
|
+
throw new InvalidParamsError(`cb_budget_adapter "${trimmed}" set but no adapter registry is available`);
|
|
575
|
+
}
|
|
576
|
+
const budgetDefaults = registry.resolveAdapter(trimmed).context_builder?.budget_defaults ?? {};
|
|
577
|
+
return {
|
|
578
|
+
...(budgetDefaults.max_estimated_tokens == null
|
|
579
|
+
? {}
|
|
580
|
+
: { max_estimated_tokens: budgetDefaults.max_estimated_tokens }),
|
|
581
|
+
...(budgetDefaults.max_files == null
|
|
582
|
+
? {}
|
|
583
|
+
: { max_files: budgetDefaults.max_files }),
|
|
584
|
+
...(budgetDefaults.max_scan_files == null
|
|
585
|
+
? {}
|
|
586
|
+
: { max_scan_files: budgetDefaults.max_scan_files }),
|
|
587
|
+
...(budgetDefaults.max_bytes_per_file == null
|
|
588
|
+
? {}
|
|
589
|
+
: { max_bytes_per_file: budgetDefaults.max_bytes_per_file }),
|
|
590
|
+
...(budgetDefaults.max_total_bytes == null
|
|
591
|
+
? {}
|
|
592
|
+
: { max_total_bytes: budgetDefaults.max_total_bytes }),
|
|
593
|
+
...(budgetDefaults.max_search_results == null
|
|
594
|
+
? {}
|
|
595
|
+
: { max_search_results: budgetDefaults.max_search_results }),
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function deriveCacheCoordinates(mappedInput, workspaceSig, runsDir, versions) {
|
|
599
|
+
const inputsHash = computeInputsHash(mappedInput);
|
|
600
|
+
const cacheKey = computeCacheKey({
|
|
601
|
+
inputsHash,
|
|
602
|
+
workspaceSig,
|
|
603
|
+
rendererVersion: versions.rendererVersion,
|
|
604
|
+
cbSchemaVersion: versions.cbSchemaVersion,
|
|
605
|
+
discoveryAlgorithmVersion: versions.discoveryAlgorithmVersion,
|
|
606
|
+
delegatePromptVersion: versions.delegatePromptVersion,
|
|
607
|
+
});
|
|
608
|
+
const wfctxId = deriveWfctxId(cacheKey);
|
|
609
|
+
return {
|
|
610
|
+
workspaceSig,
|
|
611
|
+
cacheKey,
|
|
612
|
+
wfctxId,
|
|
613
|
+
keyPrefix: cacheKey.slice(0, 16),
|
|
614
|
+
targetStorage: resolveContextBuilderRunPaths(runsDir, wfctxId),
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
async function synthesizePreflightResultFromCommittedRun(input) {
|
|
618
|
+
try {
|
|
619
|
+
const manifest = await readManifest(input.storage.manifestJson);
|
|
620
|
+
// A committed fallback bundle is degraded (delegate failure_policy:"fallback")
|
|
621
|
+
// and must NEVER be served, especially to a fail-closed failure_policy:"fail"
|
|
622
|
+
// request (failure_policy is intentionally not in the cache key). A poisoned
|
|
623
|
+
// wfctx entry can exist from a mixed-version/older writer, an external/manual
|
|
624
|
+
// artifact, or a future code path. Treat it as a cache MISS (return undefined,
|
|
625
|
+
// the same value the ENOENT/not-usable case returns) so runOrReuse falls
|
|
626
|
+
// through and re-runs the builder; a real "fail" policy then fails closed.
|
|
627
|
+
if (manifest.delegate?.fallback_used === true) {
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
const receipt = createReceiptFromManifest(manifest, input.storage);
|
|
631
|
+
const resultBeforeMaterialization = buildPreflightResult({
|
|
632
|
+
receipt,
|
|
633
|
+
sourceRunId: input.storage.runId,
|
|
634
|
+
sourceArtifactDir: input.storage.runDir,
|
|
635
|
+
cache: {
|
|
636
|
+
hit: true,
|
|
637
|
+
write: false,
|
|
638
|
+
target_id: input.storage.runId,
|
|
639
|
+
key_prefix: input.keyPrefix,
|
|
640
|
+
},
|
|
641
|
+
copiedPaths: [],
|
|
642
|
+
schemaVersion: input.schemaVersion,
|
|
643
|
+
observability: preflightObservabilityFromManifest(manifest, input.budgetCaps),
|
|
644
|
+
coverage: coverageFromManifest(manifest),
|
|
645
|
+
});
|
|
646
|
+
await input.lifecycle?.transition("cache_lookup", {
|
|
647
|
+
artifactRunId: resultBeforeMaterialization.source_run_id,
|
|
648
|
+
cache: { lookup: "hit", write: "skipped" },
|
|
649
|
+
...workflowResultLifecyclePatch(resultBeforeMaterialization, input.lifecycle, true),
|
|
650
|
+
});
|
|
651
|
+
await input.lifecycle?.transition("materializing");
|
|
652
|
+
const copiedPaths = await copyBundleArtifactsIntoRun(manifest.artifacts, input.runDir, {
|
|
653
|
+
includeSelectedContext: input.includeSelectedContext,
|
|
654
|
+
...(input.lifecycle == null
|
|
655
|
+
? {}
|
|
656
|
+
: {
|
|
657
|
+
beforeManifestCommit: async () => {
|
|
658
|
+
await input.lifecycle?.transition("committing");
|
|
659
|
+
},
|
|
660
|
+
}),
|
|
661
|
+
});
|
|
662
|
+
return buildPreflightResult({
|
|
663
|
+
receipt,
|
|
664
|
+
sourceRunId: input.storage.runId,
|
|
665
|
+
sourceArtifactDir: input.storage.runDir,
|
|
666
|
+
cache: {
|
|
667
|
+
hit: true,
|
|
668
|
+
write: false,
|
|
669
|
+
target_id: input.storage.runId,
|
|
670
|
+
key_prefix: input.keyPrefix,
|
|
671
|
+
},
|
|
672
|
+
copiedPaths,
|
|
673
|
+
schemaVersion: input.schemaVersion,
|
|
674
|
+
observability: preflightObservabilityFromManifest(manifest, input.budgetCaps),
|
|
675
|
+
coverage: coverageFromManifest(manifest),
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
if (isNodeError(error)
|
|
680
|
+
&& error.code === "ENOENT"
|
|
681
|
+
&& input.lifecycle?.snapshot?.cache.lookup !== "hit") {
|
|
682
|
+
return undefined;
|
|
683
|
+
}
|
|
684
|
+
throw error;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function createReceiptFromManifest(manifest, storage) {
|
|
688
|
+
return createContextBuilderReceipt({
|
|
689
|
+
run_id: storage.runId,
|
|
690
|
+
status: manifest.status,
|
|
691
|
+
artifact_dir: storage.artifactDir,
|
|
692
|
+
artifacts: { ...manifest.artifacts },
|
|
693
|
+
metrics: manifest.metrics,
|
|
694
|
+
warnings: [...manifest.warnings],
|
|
695
|
+
omissions: [...manifest.omissions],
|
|
696
|
+
...(manifest.delegate == null ? {} : { delegate: manifest.delegate }),
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
function buildPreflightResult(input) {
|
|
700
|
+
// The request-derived effective schema (input.schemaVersion) must match the
|
|
701
|
+
// receipt's own schema. A divergence means a handler-contract violation (e.g.
|
|
702
|
+
// a delegate-enabled request whose handler returned a no-delegate v1 receipt),
|
|
703
|
+
// which would otherwise emit schema_version:2 with no delegate metadata. Fail
|
|
704
|
+
// loudly rather than emit a contradictory result.
|
|
705
|
+
if (input.schemaVersion !== input.receipt.schema_version) {
|
|
706
|
+
throw new ExecutionError("context_builder schema mismatch: request-derived schema_version " +
|
|
707
|
+
`${input.schemaVersion} does not match receipt schema_version ` +
|
|
708
|
+
`${input.receipt.schema_version}`);
|
|
709
|
+
}
|
|
710
|
+
// A delegate schema_version that carries no delegate metadata is contradictory
|
|
711
|
+
// (a delegated build that lost its delegate provenance). Fail loudly rather
|
|
712
|
+
// than silently emitting delegate: undefined, which would erase fallback_used.
|
|
713
|
+
if (input.receipt.schema_version === CONTEXT_BUILDER_DELEGATE_SCHEMA_VERSION
|
|
714
|
+
&& input.receipt.delegate == null) {
|
|
715
|
+
throw new ExecutionError("context_builder receipt has delegate schema_version but no delegate metadata");
|
|
716
|
+
}
|
|
717
|
+
const delegate = input.receipt.schema_version === CONTEXT_BUILDER_DELEGATE_SCHEMA_VERSION
|
|
718
|
+
&& input.receipt.delegate != null
|
|
719
|
+
? {
|
|
720
|
+
enabled: true,
|
|
721
|
+
status: input.receipt.delegate.status,
|
|
722
|
+
fallback_used: input.receipt.delegate.fallback_used,
|
|
723
|
+
}
|
|
724
|
+
: undefined;
|
|
725
|
+
return {
|
|
726
|
+
receipt: input.receipt,
|
|
727
|
+
source_run_id: input.sourceRunId,
|
|
728
|
+
source_artifact_dir: input.sourceArtifactDir,
|
|
729
|
+
cache: input.cache,
|
|
730
|
+
schema_version: input.schemaVersion,
|
|
731
|
+
status: input.receipt.status,
|
|
732
|
+
copied_paths: input.copiedPaths,
|
|
733
|
+
coverage: input.coverage,
|
|
734
|
+
metrics: input.receipt.metrics,
|
|
735
|
+
warning_count: input.receipt.warnings.length,
|
|
736
|
+
omission_count: input.receipt.omissions.length,
|
|
737
|
+
...(delegate == null ? {} : { delegate }),
|
|
738
|
+
...(input.observability == null
|
|
739
|
+
? {}
|
|
740
|
+
: { observability: input.observability }),
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
function preflightObservabilityFromManifest(manifest, budgetCaps) {
|
|
744
|
+
const raw = manifest["observability"];
|
|
745
|
+
const record = raw !== null && typeof raw === "object"
|
|
746
|
+
? raw
|
|
747
|
+
: {};
|
|
748
|
+
return {
|
|
749
|
+
curator_ms: nullableNonNegativeNumber(record["curator_ms"]),
|
|
750
|
+
finalizer_ms: nullableNonNegativeNumber(record["finalizer_ms"]),
|
|
751
|
+
candidate_pool_size: nonNegativeInteger(record["candidate_pool_size"]),
|
|
752
|
+
delegate_packet_size: nonNegativeInteger(record["delegate_packet_size"]),
|
|
753
|
+
budget_caps: budgetCapsFromManifest(manifest["budget"], budgetCaps),
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
function coverageFromManifest(manifest) {
|
|
757
|
+
const value = manifest["coverage"];
|
|
758
|
+
if (value === null || typeof value !== "object") {
|
|
759
|
+
return notEvaluatedCoverageReport();
|
|
760
|
+
}
|
|
761
|
+
const coverage = value;
|
|
762
|
+
if (!isCoveragePolicyId(coverage["policy_id"])
|
|
763
|
+
|| !isCoverageStatus(coverage["status"])
|
|
764
|
+
|| !isEvidenceClassArray(coverage["required_when_available"])
|
|
765
|
+
|| !isEvidenceClassArray(coverage["available"])
|
|
766
|
+
|| !isEvidenceClassArray(coverage["selected"])
|
|
767
|
+
|| !isEvidenceClassArray(coverage["missing_required"])
|
|
768
|
+
|| !isEvidenceClassArray(coverage["advisory_missing"])
|
|
769
|
+
|| !isEvidenceClassArray(coverage["unclassifiable"])) {
|
|
770
|
+
return notEvaluatedCoverageReport();
|
|
771
|
+
}
|
|
772
|
+
if (!isSemanticallyConsistentCoverage(coverage)) {
|
|
773
|
+
return notEvaluatedCoverageReport();
|
|
774
|
+
}
|
|
775
|
+
return {
|
|
776
|
+
policy_id: coverage["policy_id"],
|
|
777
|
+
status: coverage["status"],
|
|
778
|
+
required_when_available: [...coverage["required_when_available"]],
|
|
779
|
+
available: [...coverage["available"]],
|
|
780
|
+
selected: [...coverage["selected"]],
|
|
781
|
+
missing_required: [...coverage["missing_required"]],
|
|
782
|
+
advisory_missing: [...coverage["advisory_missing"]],
|
|
783
|
+
unclassifiable: [...coverage["unclassifiable"]],
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
function isSemanticallyConsistentCoverage(coverage) {
|
|
787
|
+
const policyId = coverage["policy_id"];
|
|
788
|
+
const status = coverage["status"];
|
|
789
|
+
const available = new Set(coverage["available"]);
|
|
790
|
+
const selected = coverage["selected"];
|
|
791
|
+
const missing = coverage["missing_required"];
|
|
792
|
+
if (policyId === null) {
|
|
793
|
+
return (status === "not_evaluated" &&
|
|
794
|
+
available.size === 0 &&
|
|
795
|
+
selected.length === 0 &&
|
|
796
|
+
missing.length === 0);
|
|
797
|
+
}
|
|
798
|
+
if (status === "not_evaluated") {
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
if (selected.some((evidenceClass) => !available.has(evidenceClass))) {
|
|
802
|
+
return false;
|
|
803
|
+
}
|
|
804
|
+
if (status === "satisfied") {
|
|
805
|
+
return missing.length === 0 && available.has("review_target");
|
|
806
|
+
}
|
|
807
|
+
return missing.length > 0;
|
|
808
|
+
}
|
|
809
|
+
function isCoveragePolicyId(value) {
|
|
810
|
+
return value === null || value === "review_deep_v1";
|
|
811
|
+
}
|
|
812
|
+
function isCoverageStatus(value) {
|
|
813
|
+
return value === "satisfied" || value === "degraded" || value === "not_evaluated";
|
|
814
|
+
}
|
|
815
|
+
function isEvidenceClassArray(value) {
|
|
816
|
+
return Array.isArray(value) && value.every(isEvidenceClass);
|
|
817
|
+
}
|
|
818
|
+
function isEvidenceClass(value) {
|
|
819
|
+
return value === "review_target"
|
|
820
|
+
|| value === "public_entrypoint"
|
|
821
|
+
|| value === "reverse_consumer"
|
|
822
|
+
|| value === "configuration"
|
|
823
|
+
|| value === "dependency"
|
|
824
|
+
|| value === "regression_test";
|
|
825
|
+
}
|
|
826
|
+
function budgetCapsFromManifest(value, fallback) {
|
|
827
|
+
if (value === null || typeof value !== "object") {
|
|
828
|
+
return { ...fallback };
|
|
829
|
+
}
|
|
830
|
+
const record = value;
|
|
831
|
+
return {
|
|
832
|
+
...optionalPositiveIntegerCap(record, "max_estimated_tokens"),
|
|
833
|
+
...optionalPositiveIntegerCap(record, "max_files"),
|
|
834
|
+
...optionalPositiveIntegerCap(record, "max_scan_files"),
|
|
835
|
+
...optionalPositiveIntegerCap(record, "max_bytes_per_file"),
|
|
836
|
+
...optionalPositiveIntegerCap(record, "max_total_bytes"),
|
|
837
|
+
...optionalPositiveIntegerCap(record, "max_search_results"),
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
function optionalPositiveIntegerCap(record, key) {
|
|
841
|
+
const value = record[key];
|
|
842
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0
|
|
843
|
+
? { [key]: value }
|
|
844
|
+
: {};
|
|
845
|
+
}
|
|
846
|
+
function nullableNonNegativeNumber(value) {
|
|
847
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
848
|
+
? value
|
|
849
|
+
: null;
|
|
850
|
+
}
|
|
851
|
+
function nonNegativeInteger(value) {
|
|
852
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0
|
|
853
|
+
? value
|
|
854
|
+
: 0;
|
|
855
|
+
}
|
|
856
|
+
async function readManifest(manifestPath) {
|
|
857
|
+
return JSON.parse(await readFile(manifestPath, "utf8"));
|
|
858
|
+
}
|
|
859
|
+
async function resolveSelectedContextPaths(manifest, roots) {
|
|
860
|
+
const selected = Array.isArray(manifest["selected_context"])
|
|
861
|
+
? manifest["selected_context"]
|
|
862
|
+
: [];
|
|
863
|
+
const absolutePaths = [];
|
|
864
|
+
for (const entry of selected) {
|
|
865
|
+
if (entry === null || typeof entry !== "object") {
|
|
866
|
+
throw new ExecutionError("context_builder manifest selected_context entry is invalid");
|
|
867
|
+
}
|
|
868
|
+
const rootIndex = entry.root_index;
|
|
869
|
+
const selectedPath = entry.path;
|
|
870
|
+
if (typeof rootIndex !== "number"
|
|
871
|
+
|| !Number.isInteger(rootIndex)
|
|
872
|
+
|| rootIndex < 0
|
|
873
|
+
|| rootIndex >= roots.length
|
|
874
|
+
|| typeof selectedPath !== "string"
|
|
875
|
+
|| selectedPath.trim() === "") {
|
|
876
|
+
throw new ExecutionError("context_builder manifest selected_context entry is invalid");
|
|
877
|
+
}
|
|
878
|
+
const logicalPath = resolve(roots[rootIndex], selectedPath);
|
|
879
|
+
const realPath = await normalizeExistingPath(logicalPath);
|
|
880
|
+
absolutePaths.push({
|
|
881
|
+
logicalPath,
|
|
882
|
+
realPath,
|
|
883
|
+
traversedSymlink: realPath !== logicalPath,
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
return absolutePaths;
|
|
887
|
+
}
|
|
888
|
+
async function evaluatePostCbPromotionGate(input) {
|
|
889
|
+
try {
|
|
890
|
+
const coveredPaths = await input.signatureCoveredPaths(input.roots);
|
|
891
|
+
const selectedFilesCovered =
|
|
892
|
+
// Empty selections carry no realized-file evidence, so they are not promotable.
|
|
893
|
+
input.selectedPaths.length > 0 &&
|
|
894
|
+
input.selectedPaths.every((path) => !path.traversedSymlink && coveredPaths.has(path.realPath));
|
|
895
|
+
const postSig = await input.workspaceSignature(input.roots);
|
|
896
|
+
return { selectedFilesCovered, postSig };
|
|
897
|
+
}
|
|
898
|
+
catch {
|
|
899
|
+
return undefined;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
async function normalizeCacheRoots(roots) {
|
|
903
|
+
const normalized = [];
|
|
904
|
+
for (const root of roots.length === 0 ? [process.cwd()] : roots) {
|
|
905
|
+
const absolute = resolve(root);
|
|
906
|
+
normalized.push(await normalizeExistingPath(absolute));
|
|
907
|
+
}
|
|
908
|
+
return Array.from(new Set(normalized)).sort();
|
|
909
|
+
}
|
|
910
|
+
async function normalizeExistingPath(path) {
|
|
911
|
+
const absolute = resolve(path);
|
|
912
|
+
try {
|
|
913
|
+
return await realpath(absolute);
|
|
914
|
+
}
|
|
915
|
+
catch {
|
|
916
|
+
return absolute;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
function isPromoteClaimConflict(error) {
|
|
920
|
+
return (error instanceof InvalidParamsError
|
|
921
|
+
&& error.message.startsWith("context_builder run_id already exists:")) || (error instanceof ExecutionError
|
|
922
|
+
&& error.message.startsWith("context_builder run_id conflicts with an incomplete or active run:"));
|
|
923
|
+
}
|
|
924
|
+
function throwIfAborted(signal) {
|
|
925
|
+
if (signal?.aborted === true) {
|
|
926
|
+
throw new CancellationError();
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
function isNodeError(error) {
|
|
930
|
+
return error instanceof Error && "code" in error;
|
|
931
|
+
}
|
|
932
|
+
function generateWorkflowPreflightRunId() {
|
|
933
|
+
return `wfpre-${randomUUID()}`;
|
|
934
|
+
}
|
|
935
|
+
async function resolveFallbackRoot(resolveWorkspaceRoot) {
|
|
936
|
+
const workspaceRoot = resolveWorkspaceRoot?.() ?? resolveWorkflowWorkspaceRoot();
|
|
937
|
+
const resolvedWorkspaceRoot = await realpath(workspaceRoot).catch(() => resolve(workspaceRoot));
|
|
938
|
+
const sourceAllowedRoots = getContextBuilderSourceAllowedRoots();
|
|
939
|
+
if (!isPathWithinAllowedRoots(resolvedWorkspaceRoot, sourceAllowedRoots)) {
|
|
940
|
+
throw new InvalidParamsError(`context_builder fallback root is outside source allowed roots: ${resolvedWorkspaceRoot}. ` +
|
|
941
|
+
`Allowed: ${sourceAllowedRoots.join(", ")}`);
|
|
942
|
+
}
|
|
943
|
+
return resolvedWorkspaceRoot;
|
|
944
|
+
}
|
|
945
|
+
function assertExplicitRootsWithinAllowed(roots) {
|
|
946
|
+
if (roots.length === 0)
|
|
947
|
+
return;
|
|
948
|
+
const allowed = getContextBuilderSourceAllowedRoots();
|
|
949
|
+
for (const root of roots) {
|
|
950
|
+
const resolved = realpathSyncBestEffort(resolve(process.cwd(), root));
|
|
951
|
+
if (!isPathWithinAllowedRoots(resolved, allowed)) {
|
|
952
|
+
throw new InvalidParamsError(`context_builder root is outside allowed roots: ${root}`);
|
|
953
|
+
}
|
|
954
|
+
let stat;
|
|
955
|
+
try {
|
|
956
|
+
stat = statSync(resolved);
|
|
957
|
+
}
|
|
958
|
+
catch {
|
|
959
|
+
throw new InvalidParamsError(`context_builder root does not exist: ${root}`);
|
|
960
|
+
}
|
|
961
|
+
if (!stat.isDirectory()) {
|
|
962
|
+
throw new InvalidParamsError(`context_builder root is not a directory: ${root}`);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function getContextBuilderSourceAllowedRoots() {
|
|
967
|
+
const raw = process.env["CLINKX_ALLOWED_ROOTS"];
|
|
968
|
+
if (raw == null || raw.trim() === "") {
|
|
969
|
+
return getCurrentAllowedRoots();
|
|
970
|
+
}
|
|
971
|
+
const cwd = resolve(process.cwd());
|
|
972
|
+
const roots = [];
|
|
973
|
+
const seen = new Set();
|
|
974
|
+
for (const entry of raw
|
|
975
|
+
.split(",")
|
|
976
|
+
.map((root) => root.trim())
|
|
977
|
+
.filter((root) => root.length > 0)) {
|
|
978
|
+
if (isArtifactOnlyAllowedRootEntry(entry)) {
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
const resolved = resolve(cwd, entry);
|
|
982
|
+
const canonical = realpathSyncBestEffort(resolved);
|
|
983
|
+
if (!seen.has(canonical)) {
|
|
984
|
+
seen.add(canonical);
|
|
985
|
+
roots.push(canonical);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
return roots;
|
|
989
|
+
}
|
|
990
|
+
function realpathSyncBestEffort(path) {
|
|
991
|
+
try {
|
|
992
|
+
return realpathSync(path);
|
|
993
|
+
}
|
|
994
|
+
catch {
|
|
995
|
+
return path;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
function validateProfile(profile) {
|
|
999
|
+
if (profile == null || profile.trim() === "") {
|
|
1000
|
+
return undefined;
|
|
1001
|
+
}
|
|
1002
|
+
if (isContextBuilderProfile(profile)) {
|
|
1003
|
+
return profile;
|
|
1004
|
+
}
|
|
1005
|
+
throw new InvalidParamsError(`Unknown context_builder profile "${profile}". ` +
|
|
1006
|
+
`Allowed: ${CONTEXT_BUILDER_INTENT_PROFILES.join(", ")}`);
|
|
1007
|
+
}
|
|
1008
|
+
function isContextBuilderProfile(profile) {
|
|
1009
|
+
return CONTEXT_BUILDER_INTENT_PROFILES.includes(profile);
|
|
1010
|
+
}
|
|
1011
|
+
async function resolveArtifactPath(artifacts, key, label) {
|
|
1012
|
+
const artifactPath = artifacts[key];
|
|
1013
|
+
if (typeof artifactPath !== "string" || artifactPath.trim() === "") {
|
|
1014
|
+
throw new ExecutionError(`context_builder receipt is missing ${label}`);
|
|
1015
|
+
}
|
|
1016
|
+
return realpath(artifactPath);
|
|
1017
|
+
}
|
|
1018
|
+
async function copyArtifactIntoContextDir(source, contextDir, fileName) {
|
|
1019
|
+
const target = resolve(contextDir, fileName);
|
|
1020
|
+
assertContainedPath(contextDir, target, `context_builder copy target escaped: ${target}`);
|
|
1021
|
+
const tempTarget = resolve(contextDir, `.${fileName}.${process.pid}.${randomUUID()}.tmp`);
|
|
1022
|
+
assertContainedPath(contextDir, tempTarget, `context_builder temp copy target escaped: ${tempTarget}`);
|
|
1023
|
+
try {
|
|
1024
|
+
await copyFile(source, tempTarget);
|
|
1025
|
+
await rename(tempTarget, target);
|
|
1026
|
+
}
|
|
1027
|
+
catch (error) {
|
|
1028
|
+
await rm(tempTarget, { force: true }).catch(() => { });
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
const realTarget = await realpath(target);
|
|
1032
|
+
assertContainedPath(contextDir, realTarget, `context_builder copied artifact escaped context directory: ${realTarget}`);
|
|
1033
|
+
return realTarget;
|
|
1034
|
+
}
|
|
1035
|
+
function assertContainedPath(parent, child, message) {
|
|
1036
|
+
if (!isAbsolute(child)) {
|
|
1037
|
+
throw new ExecutionError(message);
|
|
1038
|
+
}
|
|
1039
|
+
const rel = relative(parent, child);
|
|
1040
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
1041
|
+
throw new ExecutionError(message);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
function parseReceiptResponse(response) {
|
|
1045
|
+
const receiptText = response.content[0]?.text;
|
|
1046
|
+
if (typeof receiptText !== "string") {
|
|
1047
|
+
throw new ExecutionError("context_builder returned no receipt text");
|
|
1048
|
+
}
|
|
1049
|
+
return JSON.parse(receiptText);
|
|
1050
|
+
}
|
|
1051
|
+
//# sourceMappingURL=workflow-runner.js.map
|