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
|
@@ -8,7 +8,8 @@ import { CONTEXT_BUILDER_REQUESTED_EVIDENCE_OMISSION_REASON, requestedEvidenceOm
|
|
|
8
8
|
import { compileContextBuilderGlobs, CONTEXT_BUILDER_DEFAULT_EXCLUDE_GLOBS, } from "./globs.js";
|
|
9
9
|
import { normalizeContextBuilderRootRelativePath, rootRelativePathForAbsolutePath, } from "./paths.js";
|
|
10
10
|
import { directoryDistance, genericPathKind, isTestPath, normalizedPathStem, } from "./path-signals.js";
|
|
11
|
-
import {
|
|
11
|
+
import { buildContextReviewObligations, } from "./review-coverage.js";
|
|
12
|
+
import { sanitizeHighConfidenceSecretContent, scanSecretPath, } from "./secrets.js";
|
|
12
13
|
import { CONTEXT_BUILDER_PUBLIC_BUDGET_HARD_LIMITS, } from "./schema.js";
|
|
13
14
|
const SEARCH_WINDOW_LINES_BEFORE = 19;
|
|
14
15
|
const SEARCH_WINDOW_LINES_AFTER = 20;
|
|
@@ -16,13 +17,28 @@ const SEARCH_BRIDGE_GAP_LINES = 20;
|
|
|
16
17
|
const SEARCH_MAX_MERGED_SPAN_LINES = 160;
|
|
17
18
|
const DEFAULT_MAX_FULL_FOCUS_SLICE_BYTES = 48_000;
|
|
18
19
|
const DEFAULT_MAX_FULL_IMPLEMENTATION_FOCUS_SLICE_BYTES = 96_000;
|
|
20
|
+
// Non-silent, material signal for an explicitly-focused file that exceeded the
|
|
21
|
+
// bounded full-file focus size and had no per-file search evidence: instead of
|
|
22
|
+
// dropping it, we include a bounded head slice and record this reason so the
|
|
23
|
+
// receipt reflects a partial inclusion (not a silent omission).
|
|
24
|
+
const CONTEXT_BUILDER_FOCUS_SLICED_REASON = "focus_sliced";
|
|
25
|
+
// Non-silent, material signal for an explicitly-focused file whose FIRST logical
|
|
26
|
+
// line alone exceeds the bounded focus-slice cap. The line-range model cannot
|
|
27
|
+
// express a partial line, so emitting a head slice would blow the byte bound.
|
|
28
|
+
// We omit the file with this explicit material reason instead — honoring both
|
|
29
|
+
// the byte bound and "never silently drop an explicitly-focused file".
|
|
30
|
+
const CONTEXT_BUILDER_FOCUS_OVER_CAP_REASON = "focus_over_cap";
|
|
19
31
|
const IMPORT_EXPANSION_PASSES = 3;
|
|
32
|
+
const MAX_EXPANDED_SEARCH_TERMS = 128;
|
|
33
|
+
const MAX_EXPANDED_SEARCH_TERM_BYTES = 16_384;
|
|
34
|
+
const MAX_DERIVED_SEARCH_TERM_LENGTH = 256;
|
|
20
35
|
const PROJECT_SUPPORT_FILENAMES = Object.freeze([
|
|
21
36
|
"package.json",
|
|
22
37
|
"vitest.config.ts",
|
|
23
38
|
"vite.config.ts",
|
|
24
39
|
]);
|
|
25
40
|
export async function discoverContextBuilderCandidates(options) {
|
|
41
|
+
const allowSecrets = options.allowSecrets ?? true;
|
|
26
42
|
const internalCaps = options.internal_caps ?? CONTEXT_BUILDER_INTERNAL_CAP_DEFAULTS;
|
|
27
43
|
const matcher = compileContextBuilderGlobs({
|
|
28
44
|
include: [...(options.include_globs ?? [])],
|
|
@@ -37,6 +53,8 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
37
53
|
omissions: [],
|
|
38
54
|
requestedEvidenceOmissionKeys: new Set(),
|
|
39
55
|
processedFileKeys: new Set(),
|
|
56
|
+
traversedDirectoryKeys: new Set(),
|
|
57
|
+
focusScanExemptFiles: 0,
|
|
40
58
|
metrics: {
|
|
41
59
|
files_seen: 0,
|
|
42
60
|
files_considered: 0,
|
|
@@ -57,6 +75,7 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
57
75
|
await processExactFocusFiles({
|
|
58
76
|
root,
|
|
59
77
|
focusPaths: options.focus_paths ?? [],
|
|
78
|
+
allowSecrets,
|
|
60
79
|
matcher,
|
|
61
80
|
budget: options.budget,
|
|
62
81
|
internalCaps,
|
|
@@ -70,12 +89,31 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
70
89
|
},
|
|
71
90
|
state,
|
|
72
91
|
});
|
|
92
|
+
await processFocusDirectories({
|
|
93
|
+
root,
|
|
94
|
+
focusPaths: options.focus_paths ?? [],
|
|
95
|
+
allowSecrets,
|
|
96
|
+
matcher,
|
|
97
|
+
budget: options.budget,
|
|
98
|
+
internalCaps,
|
|
99
|
+
excludedRealRoots: options.excluded_real_roots ?? [],
|
|
100
|
+
...(options.signal == null ? {} : { signal: options.signal }),
|
|
101
|
+
fs: {
|
|
102
|
+
readdir: options.fs?.readdir ?? fsReaddir,
|
|
103
|
+
lstat: options.fs?.lstat ?? fsLstat,
|
|
104
|
+
open: options.fs?.open ?? fsOpen,
|
|
105
|
+
realpath: options.fs?.realpath ?? fsRealpath,
|
|
106
|
+
stat: options.fs?.stat ?? fsStat,
|
|
107
|
+
},
|
|
108
|
+
state,
|
|
109
|
+
});
|
|
73
110
|
await traverseDirectory({
|
|
74
111
|
root,
|
|
75
112
|
absoluteDir: root.path,
|
|
76
113
|
relativeDir: "",
|
|
77
114
|
matcher,
|
|
78
115
|
focusPaths: options.focus_paths ?? [],
|
|
116
|
+
allowSecrets,
|
|
79
117
|
budget: options.budget,
|
|
80
118
|
internalCaps,
|
|
81
119
|
excludedRealRoots: options.excluded_real_roots ?? [],
|
|
@@ -93,6 +131,7 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
93
131
|
root,
|
|
94
132
|
matcher,
|
|
95
133
|
focusPaths: options.focus_paths ?? [],
|
|
134
|
+
allowSecrets,
|
|
96
135
|
budget: options.budget,
|
|
97
136
|
internalCaps,
|
|
98
137
|
...(options.signal == null ? {} : { signal: options.signal }),
|
|
@@ -108,11 +147,12 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
108
147
|
}
|
|
109
148
|
state.tree.sort(compareTreeFiles);
|
|
110
149
|
state.contentCandidates.sort(compareContentCandidates);
|
|
150
|
+
const expandedSearchTerms = expandSearchTerms([...(options.search_terms ?? [])]);
|
|
111
151
|
const search = buildCandidateSearchRecords({
|
|
112
152
|
candidates: state.contentCandidates,
|
|
113
|
-
...(options.task == null ? {} : { task: options.task }),
|
|
114
153
|
focusPaths: [...(options.focus_paths ?? [])],
|
|
115
|
-
searchTerms:
|
|
154
|
+
searchTerms: expandedSearchTerms.terms,
|
|
155
|
+
callerTermCount: expandedSearchTerms.callerTermCount,
|
|
116
156
|
maxSearchResults: options.budget.max_search_results,
|
|
117
157
|
maxPreviewBytes: internalCaps.max_search_preview_bytes,
|
|
118
158
|
maxCandidateBytes: internalCaps.max_candidate_bytes,
|
|
@@ -135,6 +175,24 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
135
175
|
if (slices.capHit) {
|
|
136
176
|
state.metrics.candidate_cap_hit = true;
|
|
137
177
|
}
|
|
178
|
+
const reviewObligations = buildContextReviewObligations({
|
|
179
|
+
candidates: state.contentCandidates,
|
|
180
|
+
focusPaths: (options.focus_paths ?? []).map((focus) => ({
|
|
181
|
+
root_index: focus.root_index,
|
|
182
|
+
path: focus.root_relative_path,
|
|
183
|
+
kind: focus.kind,
|
|
184
|
+
})),
|
|
185
|
+
searchRecords: search.records,
|
|
186
|
+
slices: slices.records,
|
|
187
|
+
policy: options.coverage_policy,
|
|
188
|
+
});
|
|
189
|
+
classifyContextEvidenceCandidates({
|
|
190
|
+
candidates: state.contentCandidates,
|
|
191
|
+
focusPaths: options.focus_paths ?? [],
|
|
192
|
+
searchRecords: search.records,
|
|
193
|
+
policy: options.coverage_policy,
|
|
194
|
+
obligations: reviewObligations,
|
|
195
|
+
});
|
|
138
196
|
auditScanCapFocusedPaths({
|
|
139
197
|
focusPaths: [...(options.focus_paths ?? [])],
|
|
140
198
|
state,
|
|
@@ -146,30 +204,86 @@ export async function discoverContextBuilderCandidates(options) {
|
|
|
146
204
|
slices: slices.records,
|
|
147
205
|
omissions: state.omissions,
|
|
148
206
|
metrics: state.metrics,
|
|
207
|
+
search_coverage: search.coverage,
|
|
208
|
+
...(reviewObligations == null ? {} : { review_obligations: reviewObligations }),
|
|
149
209
|
};
|
|
150
210
|
}
|
|
151
|
-
function expandSearchTerms(searchTerms) {
|
|
211
|
+
export function expandSearchTerms(searchTerms) {
|
|
152
212
|
const expanded = [];
|
|
153
213
|
const seen = new Set();
|
|
214
|
+
let aggregateBytes = 0;
|
|
215
|
+
// Caller terms are admitted first and are never displaced by heuristic
|
|
216
|
+
// expansion. Public post-parse validation owns their individual/aggregate
|
|
217
|
+
// bounds; this function only bounds derived fan-out before stream creation.
|
|
218
|
+
for (const term of searchTerms) {
|
|
219
|
+
const added = addExpandedSearchTerm(expanded, seen, term);
|
|
220
|
+
aggregateBytes += added;
|
|
221
|
+
}
|
|
222
|
+
const callerTermCount = expanded.length;
|
|
154
223
|
for (const term of searchTerms) {
|
|
155
|
-
addExpandedSearchTerm(expanded, seen, term);
|
|
156
224
|
for (const derived of deriveGenericSearchTerms(term)) {
|
|
157
|
-
|
|
225
|
+
const normalized = derived.trim();
|
|
226
|
+
if (normalized.length > MAX_DERIVED_SEARCH_TERM_LENGTH ||
|
|
227
|
+
expanded.length >= MAX_EXPANDED_SEARCH_TERMS) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
const bytes = Buffer.byteLength(normalized, "utf8");
|
|
231
|
+
if (aggregateBytes + bytes > MAX_EXPANDED_SEARCH_TERM_BYTES) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
aggregateBytes += addExpandedSearchTerm(expanded, seen, normalized);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return { terms: expanded, callerTermCount };
|
|
238
|
+
}
|
|
239
|
+
function classifyContextEvidenceCandidates(input) {
|
|
240
|
+
if (input.policy?.id == null) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const directSearchKeys = new Set(input.searchRecords.map(candidateKey));
|
|
244
|
+
const focusedFileKeys = new Set(input.focusPaths
|
|
245
|
+
.filter((focus) => focus.kind === "file")
|
|
246
|
+
.map((focus) => candidateKey({
|
|
247
|
+
root_index: focus.root_index,
|
|
248
|
+
path: focus.root_relative_path,
|
|
249
|
+
})));
|
|
250
|
+
const targetCandidateIds = new Set(input.obligations?.targets.map((target) => target.candidate_id) ?? []);
|
|
251
|
+
const regressionCandidateIds = new Set(input.obligations?.targets.flatMap((target) => target.regression_links.map((link) => link.candidate_id)) ?? []);
|
|
252
|
+
for (const candidate of input.candidates) {
|
|
253
|
+
const classes = [];
|
|
254
|
+
const key = candidateKey(candidate);
|
|
255
|
+
const packetCandidateId = `c:${String(candidate.root_index)}:${candidate.path}`;
|
|
256
|
+
const isReviewTarget = targetCandidateIds.has(packetCandidateId);
|
|
257
|
+
if (isReviewTarget) {
|
|
258
|
+
classes.push("review_target");
|
|
259
|
+
}
|
|
260
|
+
if (isTestPath(candidate.path) && regressionCandidateIds.has(packetCandidateId)) {
|
|
261
|
+
classes.push("regression_test");
|
|
158
262
|
}
|
|
263
|
+
const hasDiscoveryEvidence = directSearchKeys.has(key) ||
|
|
264
|
+
focusedFileKeys.has(key) ||
|
|
265
|
+
candidate.selection_hint != null;
|
|
266
|
+
if (genericPathKind(candidate.path) === "config" && hasDiscoveryEvidence) {
|
|
267
|
+
classes.push("configuration");
|
|
268
|
+
}
|
|
269
|
+
if (candidate.selection_hint === "local_dependency") {
|
|
270
|
+
classes.push("dependency");
|
|
271
|
+
}
|
|
272
|
+
candidate.evidence_classes = classes;
|
|
159
273
|
}
|
|
160
|
-
return expanded;
|
|
161
274
|
}
|
|
162
275
|
function addExpandedSearchTerm(expanded, seen, term) {
|
|
163
276
|
const normalized = term.trim();
|
|
164
277
|
if (normalized.length === 0) {
|
|
165
|
-
return;
|
|
278
|
+
return 0;
|
|
166
279
|
}
|
|
167
280
|
const key = normalized.toLowerCase();
|
|
168
281
|
if (seen.has(key)) {
|
|
169
|
-
return;
|
|
282
|
+
return 0;
|
|
170
283
|
}
|
|
171
284
|
expanded.push(normalized);
|
|
172
285
|
seen.add(key);
|
|
286
|
+
return Buffer.byteLength(normalized, "utf8");
|
|
173
287
|
}
|
|
174
288
|
function deriveGenericSearchTerms(term) {
|
|
175
289
|
const tokens = tokenizeGenericSearchTerm(term);
|
|
@@ -238,6 +352,7 @@ async function processImportAndSupportFiles(input) {
|
|
|
238
352
|
relativePath,
|
|
239
353
|
matcher: input.matcher,
|
|
240
354
|
focusPaths: input.focusPaths,
|
|
355
|
+
allowSecrets: input.allowSecrets,
|
|
241
356
|
budget: input.budget,
|
|
242
357
|
internalCaps: input.internalCaps,
|
|
243
358
|
ignoreIncludeGlob: true,
|
|
@@ -264,6 +379,7 @@ async function processImportAndSupportFiles(input) {
|
|
|
264
379
|
relativePath,
|
|
265
380
|
matcher: input.matcher,
|
|
266
381
|
focusPaths: input.focusPaths,
|
|
382
|
+
allowSecrets: input.allowSecrets,
|
|
267
383
|
budget: input.budget,
|
|
268
384
|
internalCaps: input.internalCaps,
|
|
269
385
|
ignoreIncludeGlob: true,
|
|
@@ -477,9 +593,51 @@ async function processExactFocusFiles(input) {
|
|
|
477
593
|
relativePath: focus.root_relative_path,
|
|
478
594
|
matcher: input.matcher,
|
|
479
595
|
focusPaths: input.focusPaths,
|
|
596
|
+
allowSecrets: input.allowSecrets,
|
|
480
597
|
budget: input.budget,
|
|
481
598
|
internalCaps: input.internalCaps,
|
|
482
|
-
|
|
599
|
+
focusScanExempt: true,
|
|
600
|
+
...(input.signal == null ? {} : { signal: input.signal }),
|
|
601
|
+
fs: input.fs,
|
|
602
|
+
state: input.state,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
// Pre-walk explicitly-focused directories before global traversal so a focus
|
|
607
|
+
// directory late in sort order cannot be starved by max_scan_files exhaustion
|
|
608
|
+
// from unrelated trees. Files processed here are focus-scan-exempt (they never
|
|
609
|
+
// erode traversal headroom) but remain bounded by the discovery byte and
|
|
610
|
+
// candidate caps; glob/secret/binary semantics are unchanged because the walk
|
|
611
|
+
// reuses traverseDirectory/processFile verbatim.
|
|
612
|
+
async function processFocusDirectories(input) {
|
|
613
|
+
const focusDirectories = [...input.focusPaths]
|
|
614
|
+
.filter((focus) => focus.root_index === input.root.root_index)
|
|
615
|
+
.filter((focus) => focus.kind === "directory")
|
|
616
|
+
.sort(compareFocusPathsForDiscovery);
|
|
617
|
+
for (const focus of focusDirectories) {
|
|
618
|
+
assertNotAborted(input.signal);
|
|
619
|
+
// A root-level focus gains nothing from a pre-walk (global traversal
|
|
620
|
+
// starts there immediately), and pre-walking it would exempt the entire
|
|
621
|
+
// root from max_scan_files.
|
|
622
|
+
if (focus.root_relative_path === "") {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
// Leave include-glob-pruned focus directories to global traversal, which
|
|
626
|
+
// emits the existing requested-evidence omission for them.
|
|
627
|
+
if (!input.matcher.canContainIncludedPath(focus.root_relative_path)) {
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
await traverseDirectory({
|
|
631
|
+
root: input.root,
|
|
632
|
+
absoluteDir: focus.absolute_path,
|
|
633
|
+
relativeDir: focus.root_relative_path,
|
|
634
|
+
matcher: input.matcher,
|
|
635
|
+
focusPaths: input.focusPaths,
|
|
636
|
+
allowSecrets: input.allowSecrets,
|
|
637
|
+
budget: input.budget,
|
|
638
|
+
internalCaps: input.internalCaps,
|
|
639
|
+
excludedRealRoots: input.excludedRealRoots,
|
|
640
|
+
focusScanExempt: true,
|
|
483
641
|
...(input.signal == null ? {} : { signal: input.signal }),
|
|
484
642
|
fs: input.fs,
|
|
485
643
|
state: input.state,
|
|
@@ -495,14 +653,41 @@ export function buildCandidateSearchRecords(input) {
|
|
|
495
653
|
let previewBytes = 0;
|
|
496
654
|
let candidateBytes = 0;
|
|
497
655
|
let capHit = false;
|
|
498
|
-
|
|
499
|
-
return { records, capHit, candidateBytes };
|
|
500
|
-
}
|
|
656
|
+
const callerTermCount = Math.max(0, Math.min(input.callerTermCount ?? 0, input.searchTerms.length));
|
|
501
657
|
const searchTerms = input.searchTerms
|
|
502
658
|
.map((term, index) => ({ term, index }))
|
|
503
659
|
.filter(({ term }) => term.trim().length > 0);
|
|
660
|
+
const callerTerms = searchTerms.filter(({ index }) => index < callerTermCount);
|
|
661
|
+
const derivedTerms = searchTerms.filter(({ index }) => index >= callerTermCount);
|
|
662
|
+
// Candidates whose content was examined for at least one term before a hard
|
|
663
|
+
// cap ended the walk. Key set is bounded by the candidate pool; only counts
|
|
664
|
+
// are surfaced.
|
|
665
|
+
const searchedCandidateKeys = new Set();
|
|
666
|
+
const callerTermCoverage = callerTerms.map(({ term, index }) => ({
|
|
667
|
+
term,
|
|
668
|
+
search_term_index: index,
|
|
669
|
+
hit_count: 0,
|
|
670
|
+
scan_complete: false,
|
|
671
|
+
}));
|
|
672
|
+
let callerRecordCount = 0;
|
|
673
|
+
const finalize = () => ({
|
|
674
|
+
records,
|
|
675
|
+
capHit,
|
|
676
|
+
candidateBytes,
|
|
677
|
+
coverage: {
|
|
678
|
+
eligible_candidate_count: input.candidates.length,
|
|
679
|
+
searched_candidate_count: searchedCandidateKeys.size,
|
|
680
|
+
unsearched_candidate_count: input.candidates.length - searchedCandidateKeys.size,
|
|
681
|
+
caller_term_count: callerTerms.length,
|
|
682
|
+
derived_term_count: derivedTerms.length,
|
|
683
|
+
caller_record_count: callerRecordCount,
|
|
684
|
+
derived_record_count: records.length - callerRecordCount,
|
|
685
|
+
caller_coverage_complete: callerTermCoverage.every((coverage) => coverage.scan_complete),
|
|
686
|
+
caller_terms: callerTermCoverage,
|
|
687
|
+
},
|
|
688
|
+
});
|
|
504
689
|
if (searchTerms.length === 0) {
|
|
505
|
-
return
|
|
690
|
+
return finalize();
|
|
506
691
|
}
|
|
507
692
|
const focusRank = new Map();
|
|
508
693
|
for (const focus of input.focusPaths ?? []) {
|
|
@@ -521,70 +706,154 @@ export function buildCandidateSearchRecords(input) {
|
|
|
521
706
|
const leftRank = focusRank.get(candidateKey(left)) ?? Number.MAX_SAFE_INTEGER;
|
|
522
707
|
const rightRank = focusRank.get(candidateKey(right)) ?? Number.MAX_SAFE_INTEGER;
|
|
523
708
|
return (leftRank - rightRank ||
|
|
524
|
-
discoveryTaskClosureRank(left.path, input.task ?? "") -
|
|
525
|
-
discoveryTaskClosureRank(right.path, input.task ?? "") ||
|
|
526
709
|
compareContentCandidates(left, right));
|
|
527
710
|
});
|
|
528
|
-
const
|
|
711
|
+
const candidateLines = [];
|
|
529
712
|
for (const candidate of candidates) {
|
|
530
713
|
assertNotAborted(input.signal);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
714
|
+
candidateLines.push(splitTextLines(candidate.content));
|
|
715
|
+
}
|
|
716
|
+
// Emits one found hit unless a hard cap rejects it. Cap semantics match the
|
|
717
|
+
// pre-phasing scheduler: the record/byte caps are checked after the hit is
|
|
718
|
+
// found, and tripping either one ends the whole search with capHit set.
|
|
719
|
+
const emitSearchHit = (stream, hit) => {
|
|
720
|
+
if (records.length >= input.maxSearchResults) {
|
|
721
|
+
capHit = true;
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
const preview = boundedPreview(hit.line, hit.columnIndex, stream.searchTerm.term.length);
|
|
725
|
+
const previewSize = Buffer.byteLength(preview, "utf8");
|
|
726
|
+
const bounded = previewBytes + previewSize <= maxPreviewBytes ? preview : "";
|
|
727
|
+
const record = {
|
|
728
|
+
root_index: stream.candidate.root_index,
|
|
729
|
+
path: stream.candidate.path,
|
|
730
|
+
line: hit.lineIndex + 1,
|
|
731
|
+
column: hit.columnIndex + 1,
|
|
732
|
+
search_term: stream.searchTerm.term,
|
|
733
|
+
search_term_index: stream.searchTerm.index,
|
|
734
|
+
preview: bounded,
|
|
735
|
+
};
|
|
736
|
+
const recordBytes = Buffer.byteLength(`${JSON.stringify(record)}\n`, "utf8");
|
|
737
|
+
if (candidateBytes + recordBytes > maxCandidateBytes) {
|
|
738
|
+
capHit = true;
|
|
739
|
+
return false;
|
|
740
|
+
}
|
|
741
|
+
previewBytes += Buffer.byteLength(bounded, "utf8");
|
|
742
|
+
candidateBytes += recordBytes;
|
|
743
|
+
records.push(record);
|
|
744
|
+
return true;
|
|
745
|
+
};
|
|
746
|
+
if (callerTerms.length > 0) {
|
|
747
|
+
// Phase 1 — exact caller terms get first claim on the record budget. One
|
|
748
|
+
// cursor per caller term walks the complete candidate list (focus rank
|
|
749
|
+
// first, one hit per candidate per pass), and the scheduler round-robins
|
|
750
|
+
// across the term cursors, so neither a common sibling term nor an early
|
|
751
|
+
// alphabetical candidate prefix can starve a rare late-path caller hit.
|
|
752
|
+
const cursors = callerTermCoverage.map((coverage) => ({
|
|
753
|
+
coverage,
|
|
754
|
+
streams: candidates.map((candidate, candidateIndex) => ({
|
|
534
755
|
candidate,
|
|
535
|
-
searchTerm,
|
|
536
|
-
lines,
|
|
756
|
+
searchTerm: { term: coverage.term, index: coverage.search_term_index },
|
|
757
|
+
lines: candidateLines[candidateIndex] ?? [],
|
|
537
758
|
lineIndex: 0,
|
|
538
759
|
fromIndex: 0,
|
|
539
760
|
done: false,
|
|
540
|
-
})
|
|
761
|
+
})),
|
|
762
|
+
cursor: 0,
|
|
763
|
+
active: candidates.length,
|
|
764
|
+
exhausted: false,
|
|
765
|
+
}));
|
|
766
|
+
let liveCursors = cursors.length;
|
|
767
|
+
while (liveCursors > 0) {
|
|
768
|
+
for (const cursor of cursors) {
|
|
769
|
+
assertNotAborted(input.signal);
|
|
770
|
+
if (cursor.exhausted) {
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
const next = nextCallerTermHit(cursor, searchedCandidateKeys);
|
|
774
|
+
if (next == null) {
|
|
775
|
+
// Natural exhaustion: this term's cursor examined every candidate.
|
|
776
|
+
cursor.exhausted = true;
|
|
777
|
+
cursor.coverage.scan_complete = true;
|
|
778
|
+
liveCursors--;
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (!emitSearchHit(next.stream, next.hit)) {
|
|
782
|
+
return finalize();
|
|
783
|
+
}
|
|
784
|
+
cursor.coverage.hit_count++;
|
|
785
|
+
callerRecordCount++;
|
|
786
|
+
}
|
|
541
787
|
}
|
|
542
788
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
789
|
+
if (derivedTerms.length > 0) {
|
|
790
|
+
// Phase 2 — derived/heuristic terms spend whatever budget remains, using
|
|
791
|
+
// the pre-existing candidate-major one-hit-per-stream round-robin.
|
|
792
|
+
const streams = [];
|
|
793
|
+
for (const [candidateIndex, candidate] of candidates.entries()) {
|
|
547
794
|
assertNotAborted(input.signal);
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
795
|
+
const lines = candidateLines[candidateIndex] ?? [];
|
|
796
|
+
for (const searchTerm of derivedTerms) {
|
|
797
|
+
streams.push({
|
|
798
|
+
candidate,
|
|
799
|
+
searchTerm,
|
|
800
|
+
lines,
|
|
801
|
+
lineIndex: 0,
|
|
802
|
+
fromIndex: 0,
|
|
803
|
+
done: false,
|
|
804
|
+
});
|
|
556
805
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
806
|
+
}
|
|
807
|
+
let activeStreams = streams.length;
|
|
808
|
+
while (activeStreams > 0) {
|
|
809
|
+
let foundInRound = false;
|
|
810
|
+
for (const stream of streams) {
|
|
811
|
+
assertNotAborted(input.signal);
|
|
812
|
+
if (stream.done) {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
searchedCandidateKeys.add(candidateKey(stream.candidate));
|
|
816
|
+
const hit = nextSearchHit(stream);
|
|
817
|
+
if (hit == null) {
|
|
818
|
+
stream.done = true;
|
|
819
|
+
activeStreams--;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
foundInRound = true;
|
|
823
|
+
if (!emitSearchHit(stream, hit)) {
|
|
824
|
+
return finalize();
|
|
825
|
+
}
|
|
561
826
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const bounded = previewBytes + previewSize <= maxPreviewBytes ? preview : "";
|
|
565
|
-
const record = {
|
|
566
|
-
root_index: stream.candidate.root_index,
|
|
567
|
-
path: stream.candidate.path,
|
|
568
|
-
line: hit.lineIndex + 1,
|
|
569
|
-
column: hit.columnIndex + 1,
|
|
570
|
-
search_term: stream.searchTerm.term,
|
|
571
|
-
search_term_index: stream.searchTerm.index,
|
|
572
|
-
preview: bounded,
|
|
573
|
-
};
|
|
574
|
-
const recordBytes = Buffer.byteLength(`${JSON.stringify(record)}\n`, "utf8");
|
|
575
|
-
if (candidateBytes + recordBytes > maxCandidateBytes) {
|
|
576
|
-
capHit = true;
|
|
577
|
-
return { records, capHit, candidateBytes };
|
|
827
|
+
if (!foundInRound) {
|
|
828
|
+
break;
|
|
578
829
|
}
|
|
579
|
-
previewBytes += Buffer.byteLength(bounded, "utf8");
|
|
580
|
-
candidateBytes += recordBytes;
|
|
581
|
-
records.push(record);
|
|
582
830
|
}
|
|
583
|
-
|
|
584
|
-
|
|
831
|
+
}
|
|
832
|
+
return finalize();
|
|
833
|
+
}
|
|
834
|
+
// Advances one caller term's cursor to its next hit, cycling the candidate
|
|
835
|
+
// list one hit per candidate per pass. Scanning is free — only emitted records
|
|
836
|
+
// consume the budget — so a rare term reaches late-sorting candidates even
|
|
837
|
+
// when earlier candidates are saturated with other terms' hits. Returns
|
|
838
|
+
// undefined exactly when every candidate stream is exhausted.
|
|
839
|
+
function nextCallerTermHit(cursor, searchedCandidateKeys) {
|
|
840
|
+
const total = cursor.streams.length;
|
|
841
|
+
for (let visited = 0; visited < total && cursor.active > 0; visited++) {
|
|
842
|
+
const stream = cursor.streams[cursor.cursor];
|
|
843
|
+
cursor.cursor = (cursor.cursor + 1) % total;
|
|
844
|
+
if (stream == null || stream.done) {
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
searchedCandidateKeys.add(candidateKey(stream.candidate));
|
|
848
|
+
const hit = nextSearchHit(stream);
|
|
849
|
+
if (hit == null) {
|
|
850
|
+
stream.done = true;
|
|
851
|
+
cursor.active--;
|
|
852
|
+
continue;
|
|
585
853
|
}
|
|
854
|
+
return { stream, hit };
|
|
586
855
|
}
|
|
587
|
-
return
|
|
856
|
+
return undefined;
|
|
588
857
|
}
|
|
589
858
|
export function buildCandidateSliceRecords(input) {
|
|
590
859
|
const maxCandidateSlices = input.maxCandidateSlices ??
|
|
@@ -603,7 +872,7 @@ export function buildCandidateSliceRecords(input) {
|
|
|
603
872
|
const expectedFocusedSearchRanges = new Map();
|
|
604
873
|
const survivedFocusedSearchRanges = new Map();
|
|
605
874
|
const focusSliceSurvivors = new Set();
|
|
606
|
-
const
|
|
875
|
+
const slicedLargeFocusedCandidates = new Set();
|
|
607
876
|
const omittedRequestedCandidates = new Set();
|
|
608
877
|
const pushRequestedCandidateOmission = (candidate, kind, message) => {
|
|
609
878
|
const key = candidateKey(candidate);
|
|
@@ -701,12 +970,8 @@ export function buildCandidateSliceRecords(input) {
|
|
|
701
970
|
(focus.kind === "directory" &&
|
|
702
971
|
isRootRelativeDescendant(candidate.path, focus.root_relative_path)))) {
|
|
703
972
|
const key = candidateKey(candidate);
|
|
704
|
-
if (candidate.byte_length >
|
|
705
|
-
if (
|
|
706
|
-
pushRequestedCandidateOmission(candidate, "too_large", "focused file exceeded bounded full-file focus size and had no per-file search evidence");
|
|
707
|
-
omittedLargeFocusedCandidates.add(key);
|
|
708
|
-
}
|
|
709
|
-
else if (searchRanges.has(key)) {
|
|
973
|
+
if (candidate.byte_length > maxFullFocusSliceBytes) {
|
|
974
|
+
if (searchRanges.has(key)) {
|
|
710
975
|
focusedLargeSearchCandidates.set(key, candidate);
|
|
711
976
|
expectedFocusedSearchRanges.set(key, mergeLineRanges(searchRanges.get(key) ?? [], {
|
|
712
977
|
bridgeGapLines: SEARCH_BRIDGE_GAP_LINES,
|
|
@@ -714,6 +979,27 @@ export function buildCandidateSliceRecords(input) {
|
|
|
714
979
|
}));
|
|
715
980
|
survivedFocusedSearchRanges.set(key, []);
|
|
716
981
|
}
|
|
982
|
+
else if (!slicedLargeFocusedCandidates.has(key)) {
|
|
983
|
+
// Never silently drop an explicitly-focused file. With no per-file
|
|
984
|
+
// search evidence, include a bounded head slice up to the focus
|
|
985
|
+
// byte cap and record a material, non-silent partial-focus signal
|
|
986
|
+
// instead of a too_large omission.
|
|
987
|
+
if (firstLineExceedsCap(candidate.content, maxFullFocusSliceBytes)) {
|
|
988
|
+
// The first logical line alone exceeds the cap (e.g. a minified
|
|
989
|
+
// single-line file). The line-range model cannot express a partial
|
|
990
|
+
// line, so a head slice would blow the byte bound. Omit the file
|
|
991
|
+
// with an explicit material reason rather than exceeding the bound.
|
|
992
|
+
omissions.push(focusOverCapNotice(candidate, maxFullFocusSliceBytes));
|
|
993
|
+
slicedLargeFocusedCandidates.add(key);
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
const headEndLine = headSliceEndLine(candidate.content, maxFullFocusSliceBytes);
|
|
997
|
+
const ranges = focusRanges.get(key) ?? [];
|
|
998
|
+
ranges.push({ start_line: 1, end_line: headEndLine });
|
|
999
|
+
focusRanges.set(key, ranges);
|
|
1000
|
+
omissions.push(focusSlicedNotice(candidate, headEndLine));
|
|
1001
|
+
slicedLargeFocusedCandidates.add(key);
|
|
1002
|
+
}
|
|
717
1003
|
continue;
|
|
718
1004
|
}
|
|
719
1005
|
const ranges = focusRanges.get(candidateKey(candidate)) ?? [];
|
|
@@ -735,6 +1021,30 @@ export function buildCandidateSliceRecords(input) {
|
|
|
735
1021
|
{ start_line: 1, end_line: Math.max(1, candidate.line_count) },
|
|
736
1022
|
]);
|
|
737
1023
|
}
|
|
1024
|
+
// Focus slices are appended FIRST so max_candidate_slices/max_candidate_bytes
|
|
1025
|
+
// pressure prunes search and dependency material before explicitly-focused
|
|
1026
|
+
// ranges — never the other way around.
|
|
1027
|
+
for (const [key, ranges] of [...focusRanges.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
1028
|
+
assertNotAborted(input.signal);
|
|
1029
|
+
const candidate = candidateByIdentity.get(key);
|
|
1030
|
+
if (candidate == null) {
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
for (const range of mergeLineRanges(ranges)) {
|
|
1034
|
+
if (!append({
|
|
1035
|
+
root_index: candidate.root_index,
|
|
1036
|
+
path: candidate.path,
|
|
1037
|
+
start_line: range.start_line,
|
|
1038
|
+
end_line: range.end_line,
|
|
1039
|
+
source: "focus",
|
|
1040
|
+
content: sliceContent(candidate.content, range.start_line, range.end_line),
|
|
1041
|
+
})) {
|
|
1042
|
+
pushMissingFocusedRangeOmissions(focusRanges.keys());
|
|
1043
|
+
pushMissingFocusedSearchOmissions(focusedLargeSearchCandidates.keys());
|
|
1044
|
+
return { records, capHit, omissions };
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
738
1048
|
for (const [key, ranges] of [...searchRanges.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
739
1049
|
assertNotAborted(input.signal);
|
|
740
1050
|
const candidate = candidateByIdentity.get(key);
|
|
@@ -787,26 +1097,6 @@ export function buildCandidateSliceRecords(input) {
|
|
|
787
1097
|
}
|
|
788
1098
|
}
|
|
789
1099
|
}
|
|
790
|
-
for (const [key, ranges] of [...focusRanges.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
791
|
-
assertNotAborted(input.signal);
|
|
792
|
-
const candidate = candidateByIdentity.get(key);
|
|
793
|
-
if (candidate == null) {
|
|
794
|
-
continue;
|
|
795
|
-
}
|
|
796
|
-
for (const range of mergeLineRanges(ranges)) {
|
|
797
|
-
if (!append({
|
|
798
|
-
root_index: candidate.root_index,
|
|
799
|
-
path: candidate.path,
|
|
800
|
-
start_line: range.start_line,
|
|
801
|
-
end_line: range.end_line,
|
|
802
|
-
source: "focus",
|
|
803
|
-
content: sliceContent(candidate.content, range.start_line, range.end_line),
|
|
804
|
-
})) {
|
|
805
|
-
pushMissingFocusedRangeOmissions(focusRanges.keys());
|
|
806
|
-
return { records, capHit, omissions };
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
1100
|
return { records, capHit, omissions };
|
|
811
1101
|
}
|
|
812
1102
|
export function splitTextLines(text) {
|
|
@@ -859,11 +1149,55 @@ export function mergeLineRanges(ranges, options = {}) {
|
|
|
859
1149
|
}
|
|
860
1150
|
return merged;
|
|
861
1151
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1152
|
+
// Largest 1-based line count whose cumulative UTF-8 bytes (lines joined by
|
|
1153
|
+
// "\n", matching sliceContent) stay within capBytes. Always returns >= 1 so an
|
|
1154
|
+
// explicitly-focused file is never reduced to nothing.
|
|
1155
|
+
// CALLER COUPLING: line 1 is admitted unconditionally (the `count > 0 &&` guard
|
|
1156
|
+
// skips the cap check for the first line), so callers MUST pre-screen with
|
|
1157
|
+
// firstLineExceedsCap — otherwise an over-cap first line silently breaks the
|
|
1158
|
+
// byte bound.
|
|
1159
|
+
function headSliceEndLine(content, capBytes) {
|
|
1160
|
+
const lines = splitTextLines(content);
|
|
1161
|
+
let bytes = 0;
|
|
1162
|
+
let count = 0;
|
|
1163
|
+
for (const line of lines) {
|
|
1164
|
+
const next = bytes + (count === 0 ? 0 : 1) + Buffer.byteLength(line, "utf8");
|
|
1165
|
+
if (count > 0 && next > capBytes) {
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
bytes = next;
|
|
1169
|
+
count++;
|
|
1170
|
+
}
|
|
1171
|
+
return Math.max(1, count);
|
|
1172
|
+
}
|
|
1173
|
+
// True when even the first logical line's own UTF-8 byte length exceeds capBytes,
|
|
1174
|
+
// i.e. no head slice (which always covers at least line 1) can fit within the cap.
|
|
1175
|
+
function firstLineExceedsCap(content, capBytes) {
|
|
1176
|
+
const lines = splitTextLines(content);
|
|
1177
|
+
const first = lines[0];
|
|
1178
|
+
if (first == null) {
|
|
1179
|
+
return false;
|
|
865
1180
|
}
|
|
866
|
-
return
|
|
1181
|
+
return Buffer.byteLength(first, "utf8") > capBytes;
|
|
1182
|
+
}
|
|
1183
|
+
function focusOverCapNotice(candidate, capBytes) {
|
|
1184
|
+
return {
|
|
1185
|
+
root_index: candidate.root_index,
|
|
1186
|
+
reason: CONTEXT_BUILDER_FOCUS_OVER_CAP_REASON,
|
|
1187
|
+
message: "focused file's first line alone exceeded the bounded focus-slice cap " +
|
|
1188
|
+
`(${capBytes} bytes); omitted rather than exceeding the byte bound`,
|
|
1189
|
+
paths: [candidate.path],
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
function focusSlicedNotice(candidate, headEndLine) {
|
|
1193
|
+
return {
|
|
1194
|
+
root_index: candidate.root_index,
|
|
1195
|
+
reason: CONTEXT_BUILDER_FOCUS_SLICED_REASON,
|
|
1196
|
+
message: "focused file exceeded bounded full-file focus size and had no per-file " +
|
|
1197
|
+
`search evidence; included a bounded head slice (lines 1-${headEndLine}) ` +
|
|
1198
|
+
"instead of dropping it",
|
|
1199
|
+
paths: [candidate.path],
|
|
1200
|
+
};
|
|
867
1201
|
}
|
|
868
1202
|
function focusedSearchRangesCovered(expected, survived) {
|
|
869
1203
|
return expected.every((range) => rangeCoveredByRanges(range, survived));
|
|
@@ -889,6 +1223,14 @@ async function traverseDirectory(input) {
|
|
|
889
1223
|
if (input.state.stopped) {
|
|
890
1224
|
return;
|
|
891
1225
|
}
|
|
1226
|
+
const directoryKey = candidateKey({
|
|
1227
|
+
root_index: input.root.root_index,
|
|
1228
|
+
path: input.relativeDir,
|
|
1229
|
+
});
|
|
1230
|
+
if (input.state.traversedDirectoryKeys.has(directoryKey)) {
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
input.state.traversedDirectoryKeys.add(directoryKey);
|
|
892
1234
|
if (input.relativeDir !== "" &&
|
|
893
1235
|
(input.matcher.excludes(input.relativeDir) ||
|
|
894
1236
|
input.matcher.excludes(`${input.relativeDir}/__dir__`))) {
|
|
@@ -1038,7 +1380,7 @@ async function processFile(input) {
|
|
|
1038
1380
|
if (!alreadyProcessed) {
|
|
1039
1381
|
input.state.processedFileKeys.add(fileKey);
|
|
1040
1382
|
}
|
|
1041
|
-
const omitted = (reason, message) => {
|
|
1383
|
+
const omitted = (reason, message, secretFindings) => {
|
|
1042
1384
|
input.state.omissions.push({
|
|
1043
1385
|
root_index: input.root.root_index,
|
|
1044
1386
|
reason,
|
|
@@ -1051,7 +1393,7 @@ async function processFile(input) {
|
|
|
1051
1393
|
focusPaths: input.focusPaths,
|
|
1052
1394
|
state: input.state,
|
|
1053
1395
|
kind: requestedOmissionKindForDiscoveryReason(reason),
|
|
1054
|
-
message: sanitizedFocusedOmissionMessage(reason),
|
|
1396
|
+
message: sanitizedFocusedOmissionMessage(reason, secretFindings),
|
|
1055
1397
|
});
|
|
1056
1398
|
};
|
|
1057
1399
|
const requestedOmitted = (kind, message) => {
|
|
@@ -1103,8 +1445,13 @@ async function processFile(input) {
|
|
|
1103
1445
|
});
|
|
1104
1446
|
return;
|
|
1105
1447
|
}
|
|
1448
|
+
// files_seen stays accurate for observability, but focus-processed files are
|
|
1449
|
+
// subtracted from the cap check so explicit focus never consumes the
|
|
1450
|
+
// max_scan_files headroom reserved for global traversal.
|
|
1106
1451
|
if (input.ignoreScanCap !== true &&
|
|
1107
|
-
input.
|
|
1452
|
+
input.focusScanExempt !== true &&
|
|
1453
|
+
input.state.metrics.files_seen - input.state.focusScanExemptFiles >=
|
|
1454
|
+
input.budget.max_scan_files) {
|
|
1108
1455
|
input.state.metrics.scan_cap_hit = true;
|
|
1109
1456
|
pushRequestedFocusOmission({
|
|
1110
1457
|
root_index: input.root.root_index,
|
|
@@ -1118,9 +1465,12 @@ async function processFile(input) {
|
|
|
1118
1465
|
return;
|
|
1119
1466
|
}
|
|
1120
1467
|
input.state.metrics.files_seen++;
|
|
1121
|
-
|
|
1468
|
+
if (input.focusScanExempt === true) {
|
|
1469
|
+
input.state.focusScanExemptFiles++;
|
|
1470
|
+
}
|
|
1471
|
+
const pathSecrets = input.allowSecrets ? [] : scanSecretPath(input.relativePath);
|
|
1122
1472
|
if (pathSecrets.length > 0) {
|
|
1123
|
-
omitted("secret_path", `Secret-looking path omitted (${pathSecrets[0]?.provenance})
|
|
1473
|
+
omitted("secret_path", `Secret-looking path omitted (${pathSecrets[0]?.provenance})`, pathSecrets);
|
|
1124
1474
|
pushTree({
|
|
1125
1475
|
eligible: false,
|
|
1126
1476
|
content_eligible: false,
|
|
@@ -1235,10 +1585,11 @@ async function processFile(input) {
|
|
|
1235
1585
|
}
|
|
1236
1586
|
const rawContent = contentBuffer.toString("utf8");
|
|
1237
1587
|
input.state.metrics.bytes_read += contentBuffer.byteLength;
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1588
|
+
const sanitized = input.allowSecrets
|
|
1589
|
+
? { status: "unchanged", content: rawContent, findings: [] }
|
|
1590
|
+
: sanitizeHighConfidenceSecretContent(rawContent);
|
|
1591
|
+
if (sanitized.status === "blocked") {
|
|
1592
|
+
omitted("content_secret", `Content omitted due to high-confidence secret (${summarizeSecretFindings(sanitized.findings)})`, sanitized.findings);
|
|
1242
1593
|
pushTree({
|
|
1243
1594
|
size_bytes: read.sizeBytes,
|
|
1244
1595
|
eligible: true,
|
|
@@ -1247,9 +1598,7 @@ async function processFile(input) {
|
|
|
1247
1598
|
});
|
|
1248
1599
|
return;
|
|
1249
1600
|
}
|
|
1250
|
-
const content =
|
|
1251
|
-
? redactHighConfidenceAssignmentSecrets(rawContent)
|
|
1252
|
-
: rawContent;
|
|
1601
|
+
const content = sanitized.content;
|
|
1253
1602
|
const contentBytes = Buffer.byteLength(content, "utf8");
|
|
1254
1603
|
if (input.state.contentCandidates.length >= input.internalCaps.max_discovery_candidates) {
|
|
1255
1604
|
input.state.metrics.discovery_candidate_cap_hit = true;
|
|
@@ -1403,74 +1752,6 @@ function compareTreeFiles(left, right) {
|
|
|
1403
1752
|
function compareContentCandidates(left, right) {
|
|
1404
1753
|
return left.root_index - right.root_index || left.path.localeCompare(right.path);
|
|
1405
1754
|
}
|
|
1406
|
-
function discoveryTaskClosureRank(path, task) {
|
|
1407
|
-
const normalizedTask = task.toLowerCase();
|
|
1408
|
-
if (normalizedTask.length === 0) {
|
|
1409
|
-
return 0;
|
|
1410
|
-
}
|
|
1411
|
-
const taskTokens = new Set(tokenizeGenericSearchTerm(normalizedTask));
|
|
1412
|
-
const normalizedPath = path.toLowerCase();
|
|
1413
|
-
if (/\b(discover|discovery)\b.*\b(provider-specific|provider\s+semantics|providers?|claude|agent|symmetry)\b|\b(provider-specific|provider\s+semantics|providers?|claude|agent|symmetry)\b.*\b(discover|discovery)\b/.test(normalizedTask) &&
|
|
1414
|
-
hasAnyToken(taskTokens, ["provider", "runtime", "claude", "agent", "symmetry"]) &&
|
|
1415
|
-
[/\/claude_agent\.py$/, /\/runtime\/base\.py$/].some((pattern) => pattern.test(normalizedPath))) {
|
|
1416
|
-
return -30;
|
|
1417
|
-
}
|
|
1418
|
-
if (/\b(discover|discovery)\b/.test(normalizedTask) &&
|
|
1419
|
-
hasAnyToken(taskTokens, ["queue", "migration", "runtime", "schema", "setting", "selector"]) &&
|
|
1420
|
-
[
|
|
1421
|
-
/\/tasks\/chat_processor\.py$/,
|
|
1422
|
-
/\/hooks\/usemessageactions\.ts$/,
|
|
1423
|
-
/\/hooks\/usechatstreaming\.ts$/,
|
|
1424
|
-
/\/hooks\/usechatruntimesettings\.ts$/,
|
|
1425
|
-
/\/components\/chat\/chat-window\/chat\.tsx$/,
|
|
1426
|
-
/\/components\/chat\/message-input\/input\.tsx$/,
|
|
1427
|
-
/\/components\/chat\/message-input\/inputsettingspopover\.tsx$/,
|
|
1428
|
-
/\/pages\/chatpage\.tsx$/,
|
|
1429
|
-
/\/landingpage\.tsx$/,
|
|
1430
|
-
/\/models\/db_models\/chat\.py$/,
|
|
1431
|
-
/\/[^/]*(permission|thinking).*selector[^/]*\.(ts|tsx)$/,
|
|
1432
|
-
/\/tests\/test_chat\.py$/,
|
|
1433
|
-
/\/tests?\/.*runtime.*\.(py|ts|tsx)$/,
|
|
1434
|
-
].some((pattern) => pattern.test(normalizedPath))) {
|
|
1435
|
-
return -24;
|
|
1436
|
-
}
|
|
1437
|
-
if (/\breview\b/.test(normalizedTask) &&
|
|
1438
|
-
hasAnyToken(taskTokens, ["codex", "approval", "permission", "session", "runtime"]) &&
|
|
1439
|
-
[
|
|
1440
|
-
/\/api\/endpoints\/permissions\.py$/,
|
|
1441
|
-
/\/services\/runtime\/codex_approval\.py$/,
|
|
1442
|
-
/\/services\/permission_manager\.py$/,
|
|
1443
|
-
/\/services\/chat\.py$/,
|
|
1444
|
-
/\/api\/endpoints\/chat\.py$/,
|
|
1445
|
-
/\/models\/db_models\/ai_model\.py$/,
|
|
1446
|
-
/\/services\/chatservice\.ts$/,
|
|
1447
|
-
/\/types\/chat\.types\.ts$/,
|
|
1448
|
-
/\/core\/config\.py$/,
|
|
1449
|
-
/\/constants\.py$/,
|
|
1450
|
-
/\/hooks\/usepermissionrequest\.ts$/,
|
|
1451
|
-
/\/tests\/test_permissions\.py$/,
|
|
1452
|
-
/(^|\/)docs?\/.*(codex|approval|permission|session|runtime).*\.md$/,
|
|
1453
|
-
].some((pattern) => pattern.test(normalizedPath))) {
|
|
1454
|
-
return -24;
|
|
1455
|
-
}
|
|
1456
|
-
if (/\b(debug|debugging|diagnose|diagnosis|diagnostic)\b/.test(normalizedTask) &&
|
|
1457
|
-
hasAnyToken(taskTokens, ["devtool", "trace", "archive", "message"]) &&
|
|
1458
|
-
[
|
|
1459
|
-
/\/api\/endpoints\/devtools\.py$/,
|
|
1460
|
-
/\/services\/session_trace_archive\.py$/,
|
|
1461
|
-
/\/models\/db_models\/session_trace_archive\.py$/,
|
|
1462
|
-
/\/.*trace.*archive.*\.test\.(ts|tsx|py)$/,
|
|
1463
|
-
/\/tests?\/.*trace.*archive.*\.(py|ts|tsx)$/,
|
|
1464
|
-
/\/messagerenderer\.tsx$/,
|
|
1465
|
-
/\/devtools\.types\.ts$/,
|
|
1466
|
-
].some((pattern) => pattern.test(normalizedPath))) {
|
|
1467
|
-
return -24;
|
|
1468
|
-
}
|
|
1469
|
-
return 0;
|
|
1470
|
-
}
|
|
1471
|
-
function hasAnyToken(tokens, candidates) {
|
|
1472
|
-
return candidates.some((candidate) => tokens.has(candidate));
|
|
1473
|
-
}
|
|
1474
1755
|
function compareSearchRecords(left, right) {
|
|
1475
1756
|
return (left.root_index - right.root_index ||
|
|
1476
1757
|
left.path.localeCompare(right.path) ||
|
|
@@ -1569,14 +1850,14 @@ function requestedEvidenceOmissionKey(rootIndex, relativePath) {
|
|
|
1569
1850
|
function requestedOmissionKindForDiscoveryReason(reason) {
|
|
1570
1851
|
return reason === "file_too_large" ? "too_large" : "unavailable";
|
|
1571
1852
|
}
|
|
1572
|
-
function sanitizedFocusedOmissionMessage(reason) {
|
|
1853
|
+
function sanitizedFocusedOmissionMessage(reason, secretFindings) {
|
|
1573
1854
|
switch (reason) {
|
|
1574
1855
|
case "caller_include_glob":
|
|
1575
1856
|
return "focused path was outside include globs";
|
|
1576
1857
|
case "exclude_glob":
|
|
1577
1858
|
return "focused path was omitted by exclude globs";
|
|
1578
1859
|
case "secret_path":
|
|
1579
|
-
return "focused path was omitted because it matched a secret-path rule";
|
|
1860
|
+
return withSecretFindingProvenance("focused path was omitted because it matched a secret-path rule", secretFindings);
|
|
1580
1861
|
case "symlink_omitted":
|
|
1581
1862
|
return "focused path was omitted because symlinks are not followed";
|
|
1582
1863
|
case "path_escape":
|
|
@@ -1591,13 +1872,32 @@ function sanitizedFocusedOmissionMessage(reason) {
|
|
|
1591
1872
|
case "binary_file":
|
|
1592
1873
|
return "focused binary file cannot be represented as text";
|
|
1593
1874
|
case "content_secret":
|
|
1594
|
-
return "focused file content was omitted because secret-like content was detected";
|
|
1875
|
+
return withSecretFindingProvenance("focused file content was omitted because secret-like content was detected", secretFindings);
|
|
1595
1876
|
case "file_too_large":
|
|
1596
1877
|
return "focused file exceeded max_bytes_per_file";
|
|
1597
1878
|
default:
|
|
1598
1879
|
return "focused path could not be represented as local evidence";
|
|
1599
1880
|
}
|
|
1600
1881
|
}
|
|
1882
|
+
const MAX_SECRET_FINDING_PROVENANCE_DETAILS = 3;
|
|
1883
|
+
// Appends detector provenance labels and line numbers (never matched secret
|
|
1884
|
+
// text or values) to a sanitized focused-omission message, e.g.
|
|
1885
|
+
// "... (aws_access_key_id at line 12)".
|
|
1886
|
+
function withSecretFindingProvenance(base, secretFindings) {
|
|
1887
|
+
const details = [];
|
|
1888
|
+
for (const finding of secretFindings ?? []) {
|
|
1889
|
+
const detail = finding.line == null
|
|
1890
|
+
? finding.provenance
|
|
1891
|
+
: `${finding.provenance} at line ${finding.line}`;
|
|
1892
|
+
if (!details.includes(detail)) {
|
|
1893
|
+
details.push(detail);
|
|
1894
|
+
}
|
|
1895
|
+
if (details.length >= MAX_SECRET_FINDING_PROVENANCE_DETAILS) {
|
|
1896
|
+
break;
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
return details.length === 0 ? base : `${base} (${details.join(", ")})`;
|
|
1900
|
+
}
|
|
1601
1901
|
function candidateKey(candidate) {
|
|
1602
1902
|
return `${candidate.root_index}\u0000${candidate.path}`;
|
|
1603
1903
|
}
|