@quickchatai/quickreview 0.0.0-stage → 1.2.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/LICENSE +23 -0
- package/README.md +401 -2
- package/THIRD-PARTY-NOTICES.md +134 -0
- package/agents/pass-abstraction.md +64 -0
- package/agents/pass-ask-human.md +134 -0
- package/agents/pass-backcompat.md +67 -0
- package/agents/pass-baseline.md +61 -0
- package/agents/pass-behaviour-delta.md +64 -0
- package/agents/pass-bounds.md +36 -0
- package/agents/pass-claims.md +31 -0
- package/agents/pass-concurrency.md +168 -0
- package/agents/pass-consistency.md +57 -0
- package/agents/pass-contracts.md +30 -0
- package/agents/pass-data-safety.md +54 -0
- package/agents/pass-deferred.md +35 -0
- package/agents/pass-delivery.md +37 -0
- package/agents/pass-duplication.md +60 -0
- package/agents/pass-intent.md +63 -0
- package/agents/pass-lint-conformance.md +46 -0
- package/agents/pass-maintainability.md +67 -0
- package/agents/pass-placement.md +68 -0
- package/agents/pass-prod-risk.md +24 -0
- package/agents/pass-rollout.md +32 -0
- package/agents/pass-roundtrip.md +46 -0
- package/agents/pass-security.md +31 -0
- package/agents/pass-simplicity.md +68 -0
- package/agents/pass-statelessness.md +27 -0
- package/agents/pass-style.md +37 -0
- package/agents/pass-sweep.md +57 -0
- package/agents/pass-tests.md +58 -0
- package/agents/pass-ui.md +23 -0
- package/agents/pass-validate.md +50 -0
- package/agents/pass-widened.md +46 -0
- package/agents/scan/pass-scan.md +86 -0
- package/bin/qcr.js +11 -0
- package/config.example.toml +1099 -0
- package/deploy/ansible/README.md +356 -0
- package/deploy/ansible/group_vars/all.yml +212 -0
- package/deploy/ansible/inventory.example.ini +25 -0
- package/deploy/ansible/playbook.yml +360 -0
- package/deploy/collect-secrets.sh +289 -0
- package/deploy/collect-slack-secrets.mjs +1190 -0
- package/deploy/github-app-manifest.json +31 -0
- package/deploy/manifest.schema.json +75 -0
- package/deploy/qcr-update.sh +803 -0
- package/deploy/reviewer/AGENTS.override.md +12 -0
- package/dist/extensions/cli/bash-guard-ambient.js +42 -0
- package/dist/extensions/cli/bash-guard-ambient.js.map +1 -0
- package/dist/extensions/cli/bash-guard.js +5 -0
- package/dist/extensions/cli/bash-guard.js.map +1 -0
- package/dist/extensions/cli/companion-guard.js +5 -0
- package/dist/extensions/cli/companion-guard.js.map +1 -0
- package/dist/extensions/cli/debug-round.js +8 -0
- package/dist/extensions/cli/debug-round.js.map +1 -0
- package/dist/extensions/cli/inject-bridge.js +5 -0
- package/dist/extensions/cli/inject-bridge.js.map +1 -0
- package/dist/extensions/cli/ledger-pin.js +5 -0
- package/dist/extensions/cli/ledger-pin.js.map +1 -0
- package/dist/extensions/cli/lens.js +13 -0
- package/dist/extensions/cli/lens.js.map +1 -0
- package/dist/extensions/cli/login-route.js +5 -0
- package/dist/extensions/cli/login-route.js.map +1 -0
- package/dist/extensions/cli/muted-theme.js +5 -0
- package/dist/extensions/cli/muted-theme.js.map +1 -0
- package/dist/extensions/cli/onboarding.js +5 -0
- package/dist/extensions/cli/onboarding.js.map +1 -0
- package/dist/extensions/cli/setup.js +5 -0
- package/dist/extensions/cli/setup.js.map +1 -0
- package/dist/extensions/cli/tui-view.js +5 -0
- package/dist/extensions/cli/tui-view.js.map +1 -0
- package/dist/extensions/companion-guard.js +361 -0
- package/dist/extensions/companion-guard.js.map +1 -0
- package/dist/extensions/debug-round.js +204 -0
- package/dist/extensions/debug-round.js.map +1 -0
- package/dist/extensions/inject-bridge.js +603 -0
- package/dist/extensions/inject-bridge.js.map +1 -0
- package/dist/extensions/login-route.js +180 -0
- package/dist/extensions/login-route.js.map +1 -0
- package/dist/extensions/muted-theme.js +12 -0
- package/dist/extensions/muted-theme.js.map +1 -0
- package/dist/extensions/onboarding.js +198 -0
- package/dist/extensions/onboarding.js.map +1 -0
- package/dist/extensions/setup-replay.js +269 -0
- package/dist/extensions/setup-replay.js.map +1 -0
- package/dist/extensions/setup-scan.js +998 -0
- package/dist/extensions/setup-scan.js.map +1 -0
- package/dist/extensions/setup-triage.js +175 -0
- package/dist/extensions/setup-triage.js.map +1 -0
- package/dist/extensions/setup.js +1160 -0
- package/dist/extensions/setup.js.map +1 -0
- package/dist/extensions/tui-view.js +389 -0
- package/dist/extensions/tui-view.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/client.js +376 -0
- package/dist/extensions/vendor/openviking-pi/client.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/config.js +189 -0
- package/dist/extensions/vendor/openviking-pi/config.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/index.js +421 -0
- package/dist/extensions/vendor/openviking-pi/index.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +86 -0
- package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs +408 -0
- package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +41 -0
- package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-hint.js +290 -0
- package/dist/extensions/vendor/openviking-pi/qcr-hint.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-honest.js +148 -0
- package/dist/extensions/vendor/openviking-pi/qcr-honest.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-hooks.js +68 -0
- package/dist/extensions/vendor/openviking-pi/qcr-hooks.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-leaf.js +77 -0
- package/dist/extensions/vendor/openviking-pi/qcr-leaf.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-lesson.js +216 -0
- package/dist/extensions/vendor/openviking-pi/qcr-lesson.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js +154 -0
- package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-recall.js +254 -0
- package/dist/extensions/vendor/openviking-pi/qcr-recall.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-shim.js +94 -0
- package/dist/extensions/vendor/openviking-pi/qcr-shim.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/qcr-write.js +333 -0
- package/dist/extensions/vendor/openviking-pi/qcr-write.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/recall.js +108 -0
- package/dist/extensions/vendor/openviking-pi/recall.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs +529 -0
- package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs +205 -0
- package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs +442 -0
- package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs +286 -0
- package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +189 -0
- package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs +580 -0
- package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs +11 -0
- package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs +63 -0
- package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs +58 -0
- package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
- package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs.map +1 -0
- package/dist/extensions/vendor/openviking-pi/sync.js +127 -0
- package/dist/extensions/vendor/openviking-pi/sync.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/takeover.js +25 -0
- package/dist/extensions/vendor/openviking-pi/takeover.js.map +1 -0
- package/dist/extensions/vendor/openviking-pi/tools.js +417 -0
- package/dist/extensions/vendor/openviking-pi/tools.js.map +1 -0
- package/dist/src/anomalies.js +483 -0
- package/dist/src/anomalies.js.map +1 -0
- package/dist/src/answerworker.js +180 -0
- package/dist/src/answerworker.js.map +1 -0
- package/dist/src/appstamp.js +68 -0
- package/dist/src/appstamp.js.map +1 -0
- package/dist/src/archive/admission.js +3 -0
- package/dist/src/archive/admission.js.map +1 -0
- package/dist/src/archive/archivedb.js +474 -0
- package/dist/src/archive/archivedb.js.map +1 -0
- package/dist/src/archive/archiver.js +1770 -0
- package/dist/src/archive/archiver.js.map +1 -0
- package/dist/src/archive/archivewrite.js +198 -0
- package/dist/src/archive/archivewrite.js.map +1 -0
- package/dist/src/archive/bundle.js +266 -0
- package/dist/src/archive/bundle.js.map +1 -0
- package/dist/src/archive/dbmove.js +638 -0
- package/dist/src/archive/dbmove.js.map +1 -0
- package/dist/src/archive/duplicatecounts.js +80 -0
- package/dist/src/archive/duplicatecounts.js.map +1 -0
- package/dist/src/archive/eligibility.js +113 -0
- package/dist/src/archive/eligibility.js.map +1 -0
- package/dist/src/archive/extract.js +288 -0
- package/dist/src/archive/extract.js.map +1 -0
- package/dist/src/archive/fsutil.js +330 -0
- package/dist/src/archive/fsutil.js.map +1 -0
- package/dist/src/archive/gzfile.js +277 -0
- package/dist/src/archive/gzfile.js.map +1 -0
- package/dist/src/archive/kinds.js +22 -0
- package/dist/src/archive/kinds.js.map +1 -0
- package/dist/src/archive/livecheckpoint.js +178 -0
- package/dist/src/archive/livecheckpoint.js.map +1 -0
- package/dist/src/archive/liveretention.js +145 -0
- package/dist/src/archive/liveretention.js.map +1 -0
- package/dist/src/archive/manifest.js +284 -0
- package/dist/src/archive/manifest.js.map +1 -0
- package/dist/src/archive/overseer.js +283 -0
- package/dist/src/archive/overseer.js.map +1 -0
- package/dist/src/archive/piglobal.js +129 -0
- package/dist/src/archive/piglobal.js.map +1 -0
- package/dist/src/archive/plan.js +398 -0
- package/dist/src/archive/plan.js.map +1 -0
- package/dist/src/archive/prarchive.js +831 -0
- package/dist/src/archive/prarchive.js.map +1 -0
- package/dist/src/archive/prfiles.js +303 -0
- package/dist/src/archive/prfiles.js.map +1 -0
- package/dist/src/archive/report.js +169 -0
- package/dist/src/archive/report.js.map +1 -0
- package/dist/src/archive/restore.js +276 -0
- package/dist/src/archive/restore.js.map +1 -0
- package/dist/src/archive/rows.js +106 -0
- package/dist/src/archive/rows.js.map +1 -0
- package/dist/src/archive/seal.js +480 -0
- package/dist/src/archive/seal.js.map +1 -0
- package/dist/src/archive/status.js +528 -0
- package/dist/src/archive/status.js.map +1 -0
- package/dist/src/archive/storepass.js +409 -0
- package/dist/src/archive/storepass.js.map +1 -0
- package/dist/src/backfill.js +217 -0
- package/dist/src/backfill.js.map +1 -0
- package/dist/src/bench/cost.js +87 -0
- package/dist/src/bench/exec.js +76 -0
- package/dist/src/bench/values.js +14 -0
- package/dist/src/botcontrol.js +127 -0
- package/dist/src/botcontrol.js.map +1 -0
- package/dist/src/botworker.js +805 -0
- package/dist/src/botworker.js.map +1 -0
- package/dist/src/capture.js +234 -0
- package/dist/src/capture.js.map +1 -0
- package/dist/src/cases.js +1491 -0
- package/dist/src/cases.js.map +1 -0
- package/dist/src/channelfs.js +27 -0
- package/dist/src/channelfs.js.map +1 -0
- package/dist/src/checklist.js +312 -0
- package/dist/src/checklist.js.map +1 -0
- package/dist/src/ciretry.js +92 -0
- package/dist/src/ciretry.js.map +1 -0
- package/dist/src/cli.js +1947 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/cliops.js +334 -0
- package/dist/src/cliops.js.map +1 -0
- package/dist/src/clonedir.js +15 -0
- package/dist/src/clonedir.js.map +1 -0
- package/dist/src/commandeffects.js +43 -0
- package/dist/src/commandeffects.js.map +1 -0
- package/dist/src/commands.js +1335 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/companioninbox.js +203 -0
- package/dist/src/companioninbox.js.map +1 -0
- package/dist/src/compare.js +673 -0
- package/dist/src/compare.js.map +1 -0
- package/dist/src/config.js +1041 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/configcheck.js +111 -0
- package/dist/src/configcheck.js.map +1 -0
- package/dist/src/coreext.js +43 -0
- package/dist/src/coreext.js.map +1 -0
- package/dist/src/daemon.js +945 -0
- package/dist/src/daemon.js.map +1 -0
- package/dist/src/debuground.js +731 -0
- package/dist/src/debuground.js.map +1 -0
- package/dist/src/debugroundpi.js +223 -0
- package/dist/src/debugroundpi.js.map +1 -0
- package/dist/src/diagnostics.js +14 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/digest.js +139 -0
- package/dist/src/digest.js.map +1 -0
- package/dist/src/dispatch.js +1727 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/engine/answerguard.js +18 -0
- package/dist/src/engine/answerguard.js.map +1 -0
- package/dist/src/engine/botsdk.js +262 -0
- package/dist/src/engine/botsdk.js.map +1 -0
- package/dist/src/engine/caserunner-sdk.js +332 -0
- package/dist/src/engine/caserunner-sdk.js.map +1 -0
- package/dist/src/engine/debugpi.js +206 -0
- package/dist/src/engine/debugpi.js.map +1 -0
- package/dist/src/eod.js +473 -0
- package/dist/src/eod.js.map +1 -0
- package/dist/src/eodpinwatch.js +391 -0
- package/dist/src/eodpinwatch.js.map +1 -0
- package/dist/src/escalation.js +1009 -0
- package/dist/src/escalation.js.map +1 -0
- package/dist/src/eventloop.js +779 -0
- package/dist/src/eventloop.js.map +1 -0
- package/dist/src/execboundary.js +437 -0
- package/dist/src/execboundary.js.map +1 -0
- package/dist/src/feedback.js +915 -0
- package/dist/src/feedback.js.map +1 -0
- package/dist/src/findingscheck.js +200 -0
- package/dist/src/findingscheck.js.map +1 -0
- package/dist/src/fsdenied.js +26 -0
- package/dist/src/fsdenied.js.map +1 -0
- package/dist/src/ghread.js +181 -0
- package/dist/src/ghread.js.map +1 -0
- package/dist/src/github.js +1098 -0
- package/dist/src/github.js.map +1 -0
- package/dist/src/githubtoken.js +346 -0
- package/dist/src/githubtoken.js.map +1 -0
- package/dist/src/homes.js +103 -0
- package/dist/src/homes.js.map +1 -0
- package/dist/src/hostroute.js +24 -0
- package/dist/src/hostroute.js.map +1 -0
- package/dist/src/improvements.js +625 -0
- package/dist/src/improvements.js.map +1 -0
- package/dist/src/install.js +946 -0
- package/dist/src/install.js.map +1 -0
- package/dist/src/installkind.js +40 -0
- package/dist/src/installkind.js.map +1 -0
- package/dist/src/ipc/capability.js +286 -0
- package/dist/src/ipc/capability.js.map +1 -0
- package/dist/src/ipc/client.js +226 -0
- package/dist/src/ipc/client.js.map +1 -0
- package/dist/src/ipc/control.js +70 -0
- package/dist/src/ipc/control.js.map +1 -0
- package/dist/src/ipc/ghreadshim.js +77 -0
- package/dist/src/ipc/ghreadshim.js.map +1 -0
- package/dist/src/ipc/launcher.js +65 -0
- package/dist/src/ipc/launcher.js.map +1 -0
- package/dist/src/ipc/permits.js +293 -0
- package/dist/src/ipc/permits.js.map +1 -0
- package/dist/src/ipc/postshim.js +137 -0
- package/dist/src/ipc/postshim.js.map +1 -0
- package/dist/src/ipc/protocol.js +239 -0
- package/dist/src/ipc/protocol.js.map +1 -0
- package/dist/src/ipc/server.js +312 -0
- package/dist/src/ipc/server.js.map +1 -0
- package/dist/src/ipc/workerspec.js +148 -0
- package/dist/src/ipc/workerspec.js.map +1 -0
- package/dist/src/learner/learner.js +1272 -0
- package/dist/src/learner/learner.js.map +1 -0
- package/dist/src/learner/miner.js +948 -0
- package/dist/src/learner/miner.js.map +1 -0
- package/dist/src/learner/packet.js +216 -0
- package/dist/src/learner/packet.js.map +1 -0
- package/dist/src/learner/receipt.js +135 -0
- package/dist/src/learner/receipt.js.map +1 -0
- package/dist/src/learner/status.js +38 -0
- package/dist/src/learner/status.js.map +1 -0
- package/dist/src/ledgercheck.js +120 -0
- package/dist/src/ledgercheck.js.map +1 -0
- package/dist/src/lessonledger.js +451 -0
- package/dist/src/lessonledger.js.map +1 -0
- package/dist/src/lessonselect.js +639 -0
- package/dist/src/lessonselect.js.map +1 -0
- package/dist/src/lessonshadow.js +540 -0
- package/dist/src/lessonshadow.js.map +1 -0
- package/dist/src/levers.js +302 -0
- package/dist/src/levers.js.map +1 -0
- package/dist/src/live/projection.js +450 -0
- package/dist/src/live/projection.js.map +1 -0
- package/dist/src/live/publish.js +83 -0
- package/dist/src/live/publish.js.map +1 -0
- package/dist/src/live/read.js +60 -0
- package/dist/src/live/read.js.map +1 -0
- package/dist/src/livecli.js +288 -0
- package/dist/src/livecli.js.map +1 -0
- package/dist/src/loginhint.js +47 -0
- package/dist/src/loginhint.js.map +1 -0
- package/dist/src/loginrefresh/atomic.js +66 -0
- package/dist/src/loginrefresh/atomic.js.map +1 -0
- package/dist/src/loginrefresh/lock.js +93 -0
- package/dist/src/loginrefresh/lock.js.map +1 -0
- package/dist/src/loginrefresh/main.js +58 -0
- package/dist/src/loginrefresh/main.js.map +1 -0
- package/dist/src/loginrefresh/pirefresh.js +52 -0
- package/dist/src/loginrefresh/pirefresh.js.map +1 -0
- package/dist/src/loginrefresh/refresher.js +286 -0
- package/dist/src/loginrefresh/refresher.js.map +1 -0
- package/dist/src/loginrefresh/supervisor.js +253 -0
- package/dist/src/loginrefresh/supervisor.js.map +1 -0
- package/dist/src/loginrefresh/types.js +4 -0
- package/dist/src/loginrefresh/types.js.map +1 -0
- package/dist/src/memory/context.js +251 -0
- package/dist/src/memory/context.js.map +1 -0
- package/dist/src/memory/datafence.js +5 -0
- package/dist/src/memory/datafence.js.map +1 -0
- package/dist/src/memory/delivery.js +131 -0
- package/dist/src/memory/delivery.js.map +1 -0
- package/dist/src/memory/eventtags.js +81 -0
- package/dist/src/memory/eventtags.js.map +1 -0
- package/dist/src/memory/health.js +713 -0
- package/dist/src/memory/health.js.map +1 -0
- package/dist/src/memory/import.js +504 -0
- package/dist/src/memory/import.js.map +1 -0
- package/dist/src/memory/layout.js +252 -0
- package/dist/src/memory/layout.js.map +1 -0
- package/dist/src/memory/legacy-file.js +100 -0
- package/dist/src/memory/legacy-file.js.map +1 -0
- package/dist/src/memory/lessons.js +370 -0
- package/dist/src/memory/lessons.js.map +1 -0
- package/dist/src/memory/ovsession.js +449 -0
- package/dist/src/memory/ovsession.js.map +1 -0
- package/dist/src/memory/relayout.js +259 -0
- package/dist/src/memory/relayout.js.map +1 -0
- package/dist/src/memory/roundactivity.js +180 -0
- package/dist/src/memory/roundactivity.js.map +1 -0
- package/dist/src/memory/selection.js +690 -0
- package/dist/src/memory/selection.js.map +1 -0
- package/dist/src/memory/shadowstatus.js +69 -0
- package/dist/src/memory/shadowstatus.js.map +1 -0
- package/dist/src/memory/store.js +83 -0
- package/dist/src/memory/store.js.map +1 -0
- package/dist/src/memory/textidentity.js +8 -0
- package/dist/src/memory/textidentity.js.map +1 -0
- package/dist/src/metrics.js +773 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/missingconfig.js +8 -0
- package/dist/src/missingconfig.js.map +1 -0
- package/dist/src/npmverbs.js +228 -0
- package/dist/src/npmverbs.js.map +1 -0
- package/dist/src/onboard/choices.js +219 -0
- package/dist/src/onboard/choices.js.map +1 -0
- package/dist/src/onboard/engine.js +329 -0
- package/dist/src/onboard/engine.js.map +1 -0
- package/dist/src/onboard/launch.js +75 -0
- package/dist/src/onboard/launch.js.map +1 -0
- package/dist/src/onboard/pipin.js +22 -0
- package/dist/src/onboard/pipin.js.map +1 -0
- package/dist/src/onboard/stepforward.js +41 -0
- package/dist/src/onboard/stepforward.js.map +1 -0
- package/dist/src/onboard/steps/appslug.js +214 -0
- package/dist/src/onboard/steps/appslug.js.map +1 -0
- package/dist/src/onboard/steps/bringup.js +408 -0
- package/dist/src/onboard/steps/bringup.js.map +1 -0
- package/dist/src/onboard/steps/compose.js +372 -0
- package/dist/src/onboard/steps/compose.js.map +1 -0
- package/dist/src/onboard/steps/configdelivery.js +50 -0
- package/dist/src/onboard/steps/configdelivery.js.map +1 -0
- package/dist/src/onboard/steps/configfill.js +1218 -0
- package/dist/src/onboard/steps/configfill.js.map +1 -0
- package/dist/src/onboard/steps/deploysh.js +80 -0
- package/dist/src/onboard/steps/deploysh.js.map +1 -0
- package/dist/src/onboard/steps/embeddings.js +472 -0
- package/dist/src/onboard/steps/embeddings.js.map +1 -0
- package/dist/src/onboard/steps/escalation.js +571 -0
- package/dist/src/onboard/steps/escalation.js.map +1 -0
- package/dist/src/onboard/steps/githubaccount.js +595 -0
- package/dist/src/onboard/steps/githubaccount.js.map +1 -0
- package/dist/src/onboard/steps/githubapp.js +1150 -0
- package/dist/src/onboard/steps/githubapp.js.map +1 -0
- package/dist/src/onboard/steps/golive.js +508 -0
- package/dist/src/onboard/steps/golive.js.map +1 -0
- package/dist/src/onboard/steps/index.js +78 -0
- package/dist/src/onboard/steps/index.js.map +1 -0
- package/dist/src/onboard/steps/ingress.js +817 -0
- package/dist/src/onboard/steps/ingress.js.map +1 -0
- package/dist/src/onboard/steps/inventory.js +420 -0
- package/dist/src/onboard/steps/inventory.js.map +1 -0
- package/dist/src/onboard/steps/llmauth.js +966 -0
- package/dist/src/onboard/steps/llmauth.js.map +1 -0
- package/dist/src/onboard/steps/memory.js +1112 -0
- package/dist/src/onboard/steps/memory.js.map +1 -0
- package/dist/src/onboard/steps/memorykeys.js +43 -0
- package/dist/src/onboard/steps/memorykeys.js.map +1 -0
- package/dist/src/onboard/steps/preflight.js +172 -0
- package/dist/src/onboard/steps/preflight.js.map +1 -0
- package/dist/src/onboard/steps/proof.js +812 -0
- package/dist/src/onboard/steps/proof.js.map +1 -0
- package/dist/src/onboard/steps/ssh.js +300 -0
- package/dist/src/onboard/steps/ssh.js.map +1 -0
- package/dist/src/onboard/steps/topology.js +291 -0
- package/dist/src/onboard/steps/topology.js.map +1 -0
- package/dist/src/onboard/steps/transport.js +519 -0
- package/dist/src/onboard/steps/transport.js.map +1 -0
- package/dist/src/onboard/steps/tuiroute.js +102 -0
- package/dist/src/onboard/steps/tuiroute.js.map +1 -0
- package/dist/src/onboard/steps/verifyup.js +378 -0
- package/dist/src/onboard/steps/verifyup.js.map +1 -0
- package/dist/src/onboard/steps/vmdeploy.js +368 -0
- package/dist/src/onboard/steps/vmdeploy.js.map +1 -0
- package/dist/src/onboard/toml.js +53 -0
- package/dist/src/onboard/toml.js.map +1 -0
- package/dist/src/onboard/toolnames.js +30 -0
- package/dist/src/onboard/toolnames.js.map +1 -0
- package/dist/src/opencli.js +508 -0
- package/dist/src/opencli.js.map +1 -0
- package/dist/src/openpr.js +457 -0
- package/dist/src/openpr.js.map +1 -0
- package/dist/src/openviking/client.js +821 -0
- package/dist/src/openviking/client.js.map +1 -0
- package/dist/src/openviking/context.js +218 -0
- package/dist/src/openviking/context.js.map +1 -0
- package/dist/src/openviking/embedder.js +457 -0
- package/dist/src/openviking/embedder.js.map +1 -0
- package/dist/src/openviking/gapsink.js +38 -0
- package/dist/src/openviking/gapsink.js.map +1 -0
- package/dist/src/openviking/health.js +69 -0
- package/dist/src/openviking/health.js.map +1 -0
- package/dist/src/openviking/index.js +24 -0
- package/dist/src/openviking/index.js.map +1 -0
- package/dist/src/openviking/lessonfind.js +54 -0
- package/dist/src/openviking/lessonfind.js.map +1 -0
- package/dist/src/openviking/probe.js +89 -0
- package/dist/src/openviking/probe.js.map +1 -0
- package/dist/src/openviking/proc.js +95 -0
- package/dist/src/openviking/proc.js.map +1 -0
- package/dist/src/openviking/provisionreport.js +144 -0
- package/dist/src/openviking/provisionreport.js.map +1 -0
- package/dist/src/openviking/reembed.js +317 -0
- package/dist/src/openviking/reembed.js.map +1 -0
- package/dist/src/openviking/relayout.js +153 -0
- package/dist/src/openviking/relayout.js.map +1 -0
- package/dist/src/openviking/sidecar-main.js +39 -0
- package/dist/src/openviking/sidecar-main.js.map +1 -0
- package/dist/src/openviking/sidecar.js +79 -0
- package/dist/src/openviking/sidecar.js.map +1 -0
- package/dist/src/openviking/store.js +1758 -0
- package/dist/src/openviking/store.js.map +1 -0
- package/dist/src/openviking/supervisor.js +422 -0
- package/dist/src/openviking/supervisor.js.map +1 -0
- package/dist/src/openviking/types.js +5 -0
- package/dist/src/openviking/types.js.map +1 -0
- package/dist/src/operator-recovery.js +172 -0
- package/dist/src/operator-recovery.js.map +1 -0
- package/dist/src/operatormessage.js +44 -0
- package/dist/src/operatormessage.js.map +1 -0
- package/dist/src/operatorwrite.js +23 -0
- package/dist/src/operatorwrite.js.map +1 -0
- package/dist/src/outcomes.js +1364 -0
- package/dist/src/outcomes.js.map +1 -0
- package/dist/src/piauthcopy.js +5 -0
- package/dist/src/piauthcopy.js.map +1 -0
- package/dist/src/picli.js +45 -0
- package/dist/src/picli.js.map +1 -0
- package/dist/src/picwd.js +25 -0
- package/dist/src/picwd.js.map +1 -0
- package/dist/src/pilogin.js +35 -0
- package/dist/src/pilogin.js.map +1 -0
- package/dist/src/pingpong.js +1028 -0
- package/dist/src/pingpong.js.map +1 -0
- package/dist/src/posting-journal.js +442 -0
- package/dist/src/posting-journal.js.map +1 -0
- package/dist/src/posting-outbox.js +666 -0
- package/dist/src/posting-outbox.js.map +1 -0
- package/dist/src/posting-receipt.js +216 -0
- package/dist/src/posting-receipt.js.map +1 -0
- package/dist/src/posting.js +348 -0
- package/dist/src/posting.js.map +1 -0
- package/dist/src/postops.js +637 -0
- package/dist/src/postops.js.map +1 -0
- package/dist/src/pr-activity.js +11 -0
- package/dist/src/pr-activity.js.map +1 -0
- package/dist/src/pr-author.js +5 -0
- package/dist/src/pr-author.js.map +1 -0
- package/dist/src/pr-conversation.js +355 -0
- package/dist/src/pr-conversation.js.map +1 -0
- package/dist/src/pr-session-lifecycle.js +542 -0
- package/dist/src/pr-session-lifecycle.js.map +1 -0
- package/dist/src/preflight.js +341 -0
- package/dist/src/preflight.js.map +1 -0
- package/dist/src/priorresolve.js +275 -0
- package/dist/src/priorresolve.js.map +1 -0
- package/dist/src/qcrbin.js +180 -0
- package/dist/src/qcrbin.js.map +1 -0
- package/dist/src/recheck.js +1399 -0
- package/dist/src/recheck.js.map +1 -0
- package/dist/src/reconcile.js +840 -0
- package/dist/src/reconcile.js.map +1 -0
- package/dist/src/recordedfindings.js +15 -0
- package/dist/src/recordedfindings.js.map +1 -0
- package/dist/src/regression.js +546 -0
- package/dist/src/regression.js.map +1 -0
- package/dist/src/replay.js +598 -0
- package/dist/src/replay.js.map +1 -0
- package/dist/src/requiredpasses.js +113 -0
- package/dist/src/requiredpasses.js.map +1 -0
- package/dist/src/resumecheck.js +168 -0
- package/dist/src/resumecheck.js.map +1 -0
- package/dist/src/reviewcli.js +671 -0
- package/dist/src/reviewcli.js.map +1 -0
- package/dist/src/reviewcontext.js +22 -0
- package/dist/src/reviewcontext.js.map +1 -0
- package/dist/src/reviewdetach.js +574 -0
- package/dist/src/reviewdetach.js.map +1 -0
- package/dist/src/reviewhistory.js +310 -0
- package/dist/src/reviewhistory.js.map +1 -0
- package/dist/src/reviewhome.js +26 -0
- package/dist/src/reviewhome.js.map +1 -0
- package/dist/src/reviewmemory.js +110 -0
- package/dist/src/reviewmemory.js.map +1 -0
- package/dist/src/reviewnow.js +45 -0
- package/dist/src/reviewnow.js.map +1 -0
- package/dist/src/reviewrendercli.js +104 -0
- package/dist/src/reviewrendercli.js.map +1 -0
- package/dist/src/round-work.js +20 -0
- package/dist/src/round-work.js.map +1 -0
- package/dist/src/runhost.js +72 -0
- package/dist/src/runhost.js.map +1 -0
- package/dist/src/scanauth.js +25 -0
- package/dist/src/scanauth.js.map +1 -0
- package/dist/src/scanbox.js +846 -0
- package/dist/src/scanbox.js.map +1 -0
- package/dist/src/scancli.js +1074 -0
- package/dist/src/scancli.js.map +1 -0
- package/dist/src/scandriverlog.js +30 -0
- package/dist/src/scandriverlog.js.map +1 -0
- package/dist/src/session-bridge.js +75 -0
- package/dist/src/session-bridge.js.map +1 -0
- package/dist/src/session-command-payload.js +29 -0
- package/dist/src/session-command-payload.js.map +1 -0
- package/dist/src/session-command-supervisor.js +939 -0
- package/dist/src/session-command-supervisor.js.map +1 -0
- package/dist/src/sessionjsonl.js +85 -0
- package/dist/src/sessionjsonl.js.map +1 -0
- package/dist/src/sessions.js +541 -0
- package/dist/src/sessions.js.map +1 -0
- package/dist/src/setup/adapters.js +330 -0
- package/dist/src/setup/adapters.js.map +1 -0
- package/dist/src/setup/baselines.js +64 -0
- package/dist/src/setup/baselines.js.map +1 -0
- package/dist/src/setup/caserunner.js +554 -0
- package/dist/src/setup/caserunner.js.map +1 -0
- package/dist/src/setup/configcommit.js +358 -0
- package/dist/src/setup/configcommit.js.map +1 -0
- package/dist/src/setup/engine.js +672 -0
- package/dist/src/setup/engine.js.map +1 -0
- package/dist/src/setup/facts.js +593 -0
- package/dist/src/setup/facts.js.map +1 -0
- package/dist/src/setup/findings.js +948 -0
- package/dist/src/setup/findings.js.map +1 -0
- package/dist/src/setup/history.js +338 -0
- package/dist/src/setup/history.js.map +1 -0
- package/dist/src/setup/interview.js +185 -0
- package/dist/src/setup/interview.js.map +1 -0
- package/dist/src/setup/ledger.js +207 -0
- package/dist/src/setup/ledger.js.map +1 -0
- package/dist/src/setup/pins.js +43 -0
- package/dist/src/setup/pins.js.map +1 -0
- package/dist/src/setup/portrait.js +432 -0
- package/dist/src/setup/portrait.js.map +1 -0
- package/dist/src/setup/presentation.js +9 -0
- package/dist/src/setup/presentation.js.map +1 -0
- package/dist/src/setup/profile.js +417 -0
- package/dist/src/setup/profile.js.map +1 -0
- package/dist/src/setup/replay.js +240 -0
- package/dist/src/setup/replay.js.map +1 -0
- package/dist/src/setup/replaybuild.js +311 -0
- package/dist/src/setup/replaybuild.js.map +1 -0
- package/dist/src/setup/replayrun.js +806 -0
- package/dist/src/setup/replayrun.js.map +1 -0
- package/dist/src/setup/replaysource.js +169 -0
- package/dist/src/setup/replaysource.js.map +1 -0
- package/dist/src/setup/retune.js +333 -0
- package/dist/src/setup/retune.js.map +1 -0
- package/dist/src/setup/retunelog.js +51 -0
- package/dist/src/setup/retunelog.js.map +1 -0
- package/dist/src/setup/scan.js +725 -0
- package/dist/src/setup/scan.js.map +1 -0
- package/dist/src/setup/scanbuild.js +133 -0
- package/dist/src/setup/scanbuild.js.map +1 -0
- package/dist/src/setup/scanfacts.js +96 -0
- package/dist/src/setup/scanfacts.js.map +1 -0
- package/dist/src/setup/scanlease.js +251 -0
- package/dist/src/setup/scanlease.js.map +1 -0
- package/dist/src/setup/scanreport.js +289 -0
- package/dist/src/setup/scanreport.js.map +1 -0
- package/dist/src/setup/scanrun.js +1733 -0
- package/dist/src/setup/scanrun.js.map +1 -0
- package/dist/src/setup/scantree.js +257 -0
- package/dist/src/setup/scantree.js.map +1 -0
- package/dist/src/setup/stage2.js +617 -0
- package/dist/src/setup/stage2.js.map +1 -0
- package/dist/src/setup/stage2request.js +259 -0
- package/dist/src/setup/stage2request.js.map +1 -0
- package/dist/src/setup/survey.js +307 -0
- package/dist/src/setup/survey.js.map +1 -0
- package/dist/src/setup/surveyrun.js +549 -0
- package/dist/src/setup/surveyrun.js.map +1 -0
- package/dist/src/setup/textsniff.js +89 -0
- package/dist/src/setup/textsniff.js.map +1 -0
- package/dist/src/setup/trackersink.js +395 -0
- package/dist/src/setup/trackersink.js.map +1 -0
- package/dist/src/setup/triage.js +636 -0
- package/dist/src/setup/triage.js.map +1 -0
- package/dist/src/setup/tuning.js +585 -0
- package/dist/src/setup/tuning.js.map +1 -0
- package/dist/src/setup/unitcut.js +437 -0
- package/dist/src/setup/unitcut.js.map +1 -0
- package/dist/src/singleflight.js +72 -0
- package/dist/src/singleflight.js.map +1 -0
- package/dist/src/slack/announce.js +725 -0
- package/dist/src/slack/announce.js.map +1 -0
- package/dist/src/slack/api.js +227 -0
- package/dist/src/slack/api.js.map +1 -0
- package/dist/src/slack/messages.js +158 -0
- package/dist/src/slack/messages.js.map +1 -0
- package/dist/src/slack/origin.js +550 -0
- package/dist/src/slack/origin.js.map +1 -0
- package/dist/src/slack/policy.js +225 -0
- package/dist/src/slack/policy.js.map +1 -0
- package/dist/src/slack/reply.js +153 -0
- package/dist/src/slack/reply.js.map +1 -0
- package/dist/src/slack/router.js +189 -0
- package/dist/src/slack/router.js.map +1 -0
- package/dist/src/slack/socket.js +323 -0
- package/dist/src/slack/socket.js.map +1 -0
- package/dist/src/slack/types.js +11 -0
- package/dist/src/slack/types.js.map +1 -0
- package/dist/src/sqlitehint.js +30 -0
- package/dist/src/sqlitehint.js.map +1 -0
- package/dist/src/ssh-observation.js +25 -0
- package/dist/src/ssh-observation.js.map +1 -0
- package/dist/src/state.js +5869 -0
- package/dist/src/state.js.map +1 -0
- package/dist/src/statemachine.js +223 -0
- package/dist/src/statemachine.js.map +1 -0
- package/dist/src/stubs.js +52 -0
- package/dist/src/stubs.js.map +1 -0
- package/dist/src/takeover.js +506 -0
- package/dist/src/takeover.js.map +1 -0
- package/dist/src/takeoverpi.js +262 -0
- package/dist/src/takeoverpi.js.map +1 -0
- package/dist/src/terminal-failure.js +26 -0
- package/dist/src/terminal-failure.js.map +1 -0
- package/dist/src/thread-resolution-refusal.js +4 -0
- package/dist/src/thread-resolution-refusal.js.map +1 -0
- package/dist/src/tmux.js +126 -0
- package/dist/src/tmux.js.map +1 -0
- package/dist/src/trackerid.js +43 -0
- package/dist/src/trackerid.js.map +1 -0
- package/dist/src/transcriptindex.js +512 -0
- package/dist/src/transcriptindex.js.map +1 -0
- package/dist/src/tui/actions.js +404 -0
- package/dist/src/tui/actions.js.map +1 -0
- package/dist/src/tui/alerts.js +523 -0
- package/dist/src/tui/alerts.js.map +1 -0
- package/dist/src/tui/app.js +1884 -0
- package/dist/src/tui/app.js.map +1 -0
- package/dist/src/tui/archiveops.js +164 -0
- package/dist/src/tui/archiveops.js.map +1 -0
- package/dist/src/tui/autofile.js +191 -0
- package/dist/src/tui/autofile.js.map +1 -0
- package/dist/src/tui/board.js +1219 -0
- package/dist/src/tui/board.js.map +1 -0
- package/dist/src/tui/candidates.js +699 -0
- package/dist/src/tui/candidates.js.map +1 -0
- package/dist/src/tui/cellwidth.js +151 -0
- package/dist/src/tui/cellwidth.js.map +1 -0
- package/dist/src/tui/changelog-store.js +404 -0
- package/dist/src/tui/changelog-store.js.map +1 -0
- package/dist/src/tui/chord.js +26 -0
- package/dist/src/tui/chord.js.map +1 -0
- package/dist/src/tui/clipboard.js +81 -0
- package/dist/src/tui/clipboard.js.map +1 -0
- package/dist/src/tui/cmdbar.js +256 -0
- package/dist/src/tui/cmdbar.js.map +1 -0
- package/dist/src/tui/companion.js +1339 -0
- package/dist/src/tui/companion.js.map +1 -0
- package/dist/src/tui/companionplan.js +200 -0
- package/dist/src/tui/companionplan.js.map +1 -0
- package/dist/src/tui/companiontab.js +61 -0
- package/dist/src/tui/companiontab.js.map +1 -0
- package/dist/src/tui/confighome.js +105 -0
- package/dist/src/tui/confighome.js.map +1 -0
- package/dist/src/tui/connect.js +50 -0
- package/dist/src/tui/connect.js.map +1 -0
- package/dist/src/tui/deploy-ceremony.js +75 -0
- package/dist/src/tui/deploy-ceremony.js.map +1 -0
- package/dist/src/tui/deploy-drain.js +93 -0
- package/dist/src/tui/deploy-drain.js.map +1 -0
- package/dist/src/tui/deploy-process.js +234 -0
- package/dist/src/tui/deploy-process.js.map +1 -0
- package/dist/src/tui/deploytab.js +1263 -0
- package/dist/src/tui/deploytab.js.map +1 -0
- package/dist/src/tui/design.js +111 -0
- package/dist/src/tui/design.js.map +1 -0
- package/dist/src/tui/digesttab.js +148 -0
- package/dist/src/tui/digesttab.js.map +1 -0
- package/dist/src/tui/emptystate.js +32 -0
- package/dist/src/tui/emptystate.js.map +1 -0
- package/dist/src/tui/evidence.js +790 -0
- package/dist/src/tui/evidence.js.map +1 -0
- package/dist/src/tui/feed.js +415 -0
- package/dist/src/tui/feed.js.map +1 -0
- package/dist/src/tui/feedbacktab.js +907 -0
- package/dist/src/tui/feedbacktab.js.map +1 -0
- package/dist/src/tui/filters.js +75 -0
- package/dist/src/tui/filters.js.map +1 -0
- package/dist/src/tui/ghread.js +328 -0
- package/dist/src/tui/ghread.js.map +1 -0
- package/dist/src/tui/historypull.js +61 -0
- package/dist/src/tui/historypull.js.map +1 -0
- package/dist/src/tui/inboxpull.js +197 -0
- package/dist/src/tui/inboxpull.js.map +1 -0
- package/dist/src/tui/index.js +1511 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/issuesink.js +206 -0
- package/dist/src/tui/issuesink.js.map +1 -0
- package/dist/src/tui/jsonfile.js +32 -0
- package/dist/src/tui/jsonfile.js.map +1 -0
- package/dist/src/tui/keys.js +97 -0
- package/dist/src/tui/keys.js.map +1 -0
- package/dist/src/tui/layout.js +70 -0
- package/dist/src/tui/layout.js.map +1 -0
- package/dist/src/tui/learning.js +469 -0
- package/dist/src/tui/learning.js.map +1 -0
- package/dist/src/tui/lessonswitch.js +103 -0
- package/dist/src/tui/lessonswitch.js.map +1 -0
- package/dist/src/tui/livecontrol.js +167 -0
- package/dist/src/tui/livecontrol.js.map +1 -0
- package/dist/src/tui/memforward.js +347 -0
- package/dist/src/tui/memforward.js.map +1 -0
- package/dist/src/tui/memincident.js +287 -0
- package/dist/src/tui/memincident.js.map +1 -0
- package/dist/src/tui/memory.js +485 -0
- package/dist/src/tui/memory.js.map +1 -0
- package/dist/src/tui/memtab.js +513 -0
- package/dist/src/tui/memtab.js.map +1 -0
- package/dist/src/tui/metricstab.js +979 -0
- package/dist/src/tui/metricstab.js.map +1 -0
- package/dist/src/tui/model.js +129 -0
- package/dist/src/tui/model.js.map +1 -0
- package/dist/src/tui/mouse.js +83 -0
- package/dist/src/tui/mouse.js.map +1 -0
- package/dist/src/tui/msg.js +196 -0
- package/dist/src/tui/msg.js.map +1 -0
- package/dist/src/tui/nativecompanion.js +321 -0
- package/dist/src/tui/nativecompanion.js.map +1 -0
- package/dist/src/tui/openurl.js +17 -0
- package/dist/src/tui/openurl.js.map +1 -0
- package/dist/src/tui/paint.js +501 -0
- package/dist/src/tui/paint.js.map +1 -0
- package/dist/src/tui/panes.js +74 -0
- package/dist/src/tui/panes.js.map +1 -0
- package/dist/src/tui/pipane.js +166 -0
- package/dist/src/tui/pipane.js.map +1 -0
- package/dist/src/tui/poll-hooks.js +11 -0
- package/dist/src/tui/poll-hooks.js.map +1 -0
- package/dist/src/tui/poll.js +113 -0
- package/dist/src/tui/poll.js.map +1 -0
- package/dist/src/tui/proposals.js +715 -0
- package/dist/src/tui/proposals.js.map +1 -0
- package/dist/src/tui/prpause.js +139 -0
- package/dist/src/tui/prpause.js.map +1 -0
- package/dist/src/tui/reload.js +351 -0
- package/dist/src/tui/reload.js.map +1 -0
- package/dist/src/tui/remote.js +318 -0
- package/dist/src/tui/remote.js.map +1 -0
- package/dist/src/tui/rollover.js +767 -0
- package/dist/src/tui/rollover.js.map +1 -0
- package/dist/src/tui/route.js +143 -0
- package/dist/src/tui/route.js.map +1 -0
- package/dist/src/tui/scantab.js +1053 -0
- package/dist/src/tui/scantab.js.map +1 -0
- package/dist/src/tui/setupentry.js +81 -0
- package/dist/src/tui/setupentry.js.map +1 -0
- package/dist/src/tui/setupstate.js +29 -0
- package/dist/src/tui/setupstate.js.map +1 -0
- package/dist/src/tui/sidebar.js +602 -0
- package/dist/src/tui/sidebar.js.map +1 -0
- package/dist/src/tui/sshtriage.js +490 -0
- package/dist/src/tui/sshtriage.js.map +1 -0
- package/dist/src/tui/startup.js +172 -0
- package/dist/src/tui/startup.js.map +1 -0
- package/dist/src/tui/tabs.js +41 -0
- package/dist/src/tui/tabs.js.map +1 -0
- package/dist/src/tui/termmirror.js +217 -0
- package/dist/src/tui/termmirror.js.map +1 -0
- package/dist/src/tui/theme.js +96 -0
- package/dist/src/tui/theme.js.map +1 -0
- package/dist/src/tui/ticketstab.js +224 -0
- package/dist/src/tui/ticketstab.js.map +1 -0
- package/dist/src/tui/tmuxsocket.js +101 -0
- package/dist/src/tui/tmuxsocket.js.map +1 -0
- package/dist/src/tui/trackertickets.js +77 -0
- package/dist/src/tui/trackertickets.js.map +1 -0
- package/dist/src/tui/unwedge.js +235 -0
- package/dist/src/tui/unwedge.js.map +1 -0
- package/dist/src/tui/viewer.js +479 -0
- package/dist/src/tui/viewer.js.map +1 -0
- package/dist/src/tui/viewerinput.js +125 -0
- package/dist/src/tui/viewerinput.js.map +1 -0
- package/dist/src/updatenotice.js +143 -0
- package/dist/src/updatenotice.js.map +1 -0
- package/dist/src/usage.js +1007 -0
- package/dist/src/usage.js.map +1 -0
- package/dist/src/verdicts.js +3860 -0
- package/dist/src/verdicts.js.map +1 -0
- package/dist/src/version.js +58 -0
- package/dist/src/version.js.map +1 -0
- package/dist/src/wakes.js +411 -0
- package/dist/src/wakes.js.map +1 -0
- package/dist/src/webhook.js +736 -0
- package/dist/src/webhook.js.map +1 -0
- package/dist/src/webhookheal.js +238 -0
- package/dist/src/webhookheal.js.map +1 -0
- package/dist/src/wire.js +1823 -0
- package/dist/src/wire.js.map +1 -0
- package/dist/src/worker-session-host.js +531 -0
- package/dist/src/worker-session-host.js.map +1 -0
- package/dist/src/workerbreaker.js +112 -0
- package/dist/src/workerbreaker.js.map +1 -0
- package/dist/src/workercontrol.js +49 -0
- package/dist/src/workercontrol.js.map +1 -0
- package/dist/src/workerlease.js +351 -0
- package/dist/src/workerlease.js.map +1 -0
- package/dist/src/workerliveness.js +84 -0
- package/dist/src/workerliveness.js.map +1 -0
- package/dist/src/workerlog.js +65 -0
- package/dist/src/workerlog.js.map +1 -0
- package/dist/src/workerruntime.js +10 -0
- package/dist/src/workerruntime.js.map +1 -0
- package/dist/src/workersupervisor.js +1206 -0
- package/dist/src/workersupervisor.js.map +1 -0
- package/dist/src/workerusage.js +23 -0
- package/dist/src/workerusage.js.map +1 -0
- package/dist/src/workerworld.js +338 -0
- package/dist/src/workerworld.js.map +1 -0
- package/dist/src/worktrees.js +984 -0
- package/dist/src/worktrees.js.map +1 -0
- package/docker/Dockerfile +284 -0
- package/docker/Dockerfile.dockerignore +35 -0
- package/docker/README.md +221 -0
- package/docker/companion/Dockerfile +139 -0
- package/docker/companion/agents/evidence.md +34 -0
- package/docker/companion/agents/explore.md +26 -0
- package/docker/companion/agents/pass-survey.md +49 -0
- package/docker/companion/agents/study.md +26 -0
- package/docker/companion/entrypoint.sh +362 -0
- package/docker/companion/memory-health.mjs +269 -0
- package/docker/entrypoint.sh +799 -0
- package/docker/memory/Dockerfile +191 -0
- package/docker/memory/Dockerfile.dockerignore +20 -0
- package/docker/memory/README.md +60 -0
- package/docker/memory/entrypoint.sh +163 -0
- package/docker/setid/qcr-setid.c +109 -0
- package/docker/tunnel/Dockerfile.cloudflared +51 -0
- package/docker/tunnel/Dockerfile.ngrok +40 -0
- package/docker/tunnel/sidecar.mjs +411 -0
- package/docker/vm/tmux.conf +26 -0
- package/docker-compose.yml +348 -0
- package/extensions/cli/bash-guard-ambient.ts +71 -0
- package/extensions/cli/bash-guard.ts +12 -0
- package/extensions/cli/companion-guard.ts +8 -0
- package/extensions/cli/debug-round.ts +9 -0
- package/extensions/cli/inject-bridge.ts +8 -0
- package/extensions/cli/ledger-pin.ts +13 -0
- package/extensions/cli/lens.ts +22 -0
- package/extensions/cli/login-route.ts +10 -0
- package/extensions/cli/muted-theme.ts +9 -0
- package/extensions/cli/onboarding.ts +8 -0
- package/extensions/cli/setup.ts +8 -0
- package/extensions/cli/tui-view.ts +8 -0
- package/extensions/companion-guard.ts +411 -0
- package/extensions/debug-round.ts +281 -0
- package/extensions/inject-bridge.ts +630 -0
- package/extensions/inline-bash.ts +102 -0
- package/extensions/login-route.ts +220 -0
- package/extensions/muted-theme.json +68 -0
- package/extensions/muted-theme.ts +23 -0
- package/extensions/onboarding.ts +262 -0
- package/extensions/setup-replay.ts +336 -0
- package/extensions/setup-scan.ts +1236 -0
- package/extensions/setup-triage.ts +190 -0
- package/extensions/setup.ts +1428 -0
- package/extensions/tui-view.ts +489 -0
- package/extensions/vendor/openviking-pi/LICENSE +201 -0
- package/extensions/vendor/openviking-pi/NOTICE +68 -0
- package/extensions/vendor/openviking-pi/README.md +550 -0
- package/extensions/vendor/openviking-pi/client.ts +588 -0
- package/extensions/vendor/openviking-pi/config.json +28 -0
- package/extensions/vendor/openviking-pi/config.ts +271 -0
- package/extensions/vendor/openviking-pi/index.ts +523 -0
- package/extensions/vendor/openviking-pi/lib/capture-adapter.d.mts +10 -0
- package/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +88 -0
- package/extensions/vendor/openviking-pi/lib/takeover-core.d.mts +80 -0
- package/extensions/vendor/openviking-pi/lib/takeover-core.mjs +406 -0
- package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.d.mts +1 -0
- package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +42 -0
- package/extensions/vendor/openviking-pi/patches/0000-vendoring-and-build-conformance.patch +726 -0
- package/extensions/vendor/openviking-pi/patches/0001-remove-session-before-compact-handler.patch +101 -0
- package/extensions/vendor/openviking-pi/patches/0002-no-ambient-work-in-subagent-leaves.patch +202 -0
- package/extensions/vendor/openviking-pi/patches/0003-never-auto-create-openviking-sessions.patch +120 -0
- package/extensions/vendor/openviking-pi/patches/0004-viking-write-durable-batch-write.patch +521 -0
- package/extensions/vendor/openviking-pi/patches/0005-second-memory-namespace.patch +786 -0
- package/extensions/vendor/openviking-pi/patches/0006-writes-that-stick-and-honest-errors.patch +996 -0
- package/extensions/vendor/openviking-pi/patches/0007-bounded-recall-no-commit.patch +794 -0
- package/extensions/vendor/openviking-pi/patches/0008-pr-derived-recall.patch +379 -0
- package/extensions/vendor/openviking-pi/patches/0009-pr-session-tools-in-round-areas.patch +375 -0
- package/extensions/vendor/openviking-pi/patches/0010-typed-lessons.patch +448 -0
- package/extensions/vendor/openviking-pi/patches/0011-review-session-memory-boundary.patch +382 -0
- package/extensions/vendor/openviking-pi/patches/0012-typecheck-against-the-real-pi.patch +129 -0
- package/extensions/vendor/openviking-pi/patches/0013-createopenviking-factory.patch +1168 -0
- package/extensions/vendor/openviking-pi/qcr-hint.ts +313 -0
- package/extensions/vendor/openviking-pi/qcr-honest.ts +183 -0
- package/extensions/vendor/openviking-pi/qcr-hooks.ts +87 -0
- package/extensions/vendor/openviking-pi/qcr-leaf.ts +78 -0
- package/extensions/vendor/openviking-pi/qcr-lesson.ts +231 -0
- package/extensions/vendor/openviking-pi/qcr-namespaces.ts +198 -0
- package/extensions/vendor/openviking-pi/qcr-recall.ts +288 -0
- package/extensions/vendor/openviking-pi/qcr-shim.ts +142 -0
- package/extensions/vendor/openviking-pi/qcr-write.ts +427 -0
- package/extensions/vendor/openviking-pi/recall.ts +149 -0
- package/extensions/vendor/openviking-pi/shared/capture-utils.d.mts +9 -0
- package/extensions/vendor/openviking-pi/shared/capture-utils.mjs +515 -0
- package/extensions/vendor/openviking-pi/shared/credentials.d.mts +14 -0
- package/extensions/vendor/openviking-pi/shared/credentials.mjs +228 -0
- package/extensions/vendor/openviking-pi/shared/pending-queue.d.mts +19 -0
- package/extensions/vendor/openviking-pi/shared/pending-queue.mjs +458 -0
- package/extensions/vendor/openviking-pi/shared/profile-inject.d.mts +17 -0
- package/extensions/vendor/openviking-pi/shared/profile-inject.mjs +294 -0
- package/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +195 -0
- package/extensions/vendor/openviking-pi/shared/recall-core.d.mts +13 -0
- package/extensions/vendor/openviking-pi/shared/recall-core.mjs +609 -0
- package/extensions/vendor/openviking-pi/shared/retryable.mjs +9 -0
- package/extensions/vendor/openviking-pi/shared/session-model.d.mts +3 -0
- package/extensions/vendor/openviking-pi/shared/session-model.mjs +57 -0
- package/extensions/vendor/openviking-pi/shared/uri-guard.mjs +56 -0
- package/extensions/vendor/openviking-pi/shared/workspace-peer.d.mts +5 -0
- package/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
- package/extensions/vendor/openviking-pi/sync.ts +163 -0
- package/extensions/vendor/openviking-pi/takeover.ts +36 -0
- package/extensions/vendor/openviking-pi/tools.ts +479 -0
- package/extensions/vendor/openviking-pi/upstream.json +48 -0
- package/package.json +138 -4
- package/profiles/default/README.md +21 -0
- package/profiles/default/addenda/.gitkeep +0 -0
- package/profiles/default/profile.toml +17 -0
- package/profiles/example-django/README.md +21 -0
- package/profiles/example-django/addenda/10-migration-discipline.md +13 -0
- package/profiles/example-django/addenda/20-new-column-nullability.md +12 -0
- package/profiles/example-django/addenda/30-test-doctrine.md +12 -0
- package/profiles/example-django/addenda/40-orm-usage.md +19 -0
- package/profiles/example-django/addenda/50-declared-shape.md +10 -0
- package/profiles/example-django/addenda/60-config-placement.md +14 -0
- package/profiles/example-django/heuristics.toml +24 -0
- package/profiles/example-django/profile.toml +9 -0
- package/profiles/fast/README.md +24 -0
- package/profiles/fast/profile.toml +59 -0
- package/profiles/minimal/README.md +17 -0
- package/profiles/minimal/addenda/.gitkeep +0 -0
- package/profiles/minimal/profile.toml +8 -0
- package/profiles/snappy/README.md +24 -0
- package/profiles/snappy/addenda/10-race-as-question.md +6 -0
- package/profiles/snappy/profile.toml +46 -0
- package/prompts/companion-day-open.md +46 -0
- package/prompts/companion-first-run.md +104 -0
- package/prompts/companion.md +821 -0
- package/prompts/conversation-system.md +117 -0
- package/prompts/eod-sweep.md +120 -0
- package/prompts/onboarding.md +113 -0
- package/prompts/pass-common.md +52 -0
- package/prompts/pass-quality-common.md +22 -0
- package/prompts/round-first.md +874 -0
- package/prompts/round-follow-up.md +991 -0
- package/prompts/round-re-review.md +889 -0
- package/prompts/round-recheck.md +196 -0
- package/prompts/round-staleness.md +856 -0
- package/schemas/review-result.v1.json +391 -0
- package/schemas/scan-result.v1.json +421 -0
- package/schemas/version.v1.json +57 -0
- package/scripts/approve-pr.sh +16 -0
- package/scripts/build-stamp.mjs +67 -0
- package/scripts/commit-verdict.sh +155 -0
- package/scripts/companion-e2e.sh +250 -0
- package/scripts/companion-memory-forward.mjs +1966 -0
- package/scripts/config-fingerprint.sh +28 -0
- package/scripts/deploy-manifest.mjs +141 -0
- package/scripts/deploy.sh +1435 -0
- package/scripts/directory-lock.mjs +193 -0
- package/scripts/heartbeat-fresh.mjs +54 -0
- package/scripts/install-locator.sh +328 -0
- package/scripts/install-wrapper.sh +76 -0
- package/scripts/memory-search-check.mjs +98 -0
- package/scripts/mint-token.sh +233 -0
- package/scripts/openviking-embedder.py +392 -0
- package/scripts/openviking-ov-conf.mjs +161 -0
- package/scripts/openviking-provision.mjs +1122 -0
- package/scripts/openviking-reembed.mjs +1154 -0
- package/scripts/post-review.sh +16 -0
- package/scripts/pr-checks.sh +256 -0
- package/scripts/pr-context.py +174 -0
- package/scripts/pr-context.sh +63 -0
- package/scripts/pr-self.sh +144 -0
- package/scripts/pr-threads.sh +145 -0
- package/scripts/qcr +15 -0
- package/scripts/qcr-host.sh +769 -0
- package/scripts/render-review.sh +24 -0
- package/scripts/reply-thread.sh +16 -0
- package/scripts/required-passes.py +112 -0
- package/scripts/smoke-companion.sh +211 -0
- package/scripts/tui-deploy-runner.mjs +61 -0
- package/scripts/verify-dist.mjs +201 -0
- package/scripts/vm-ghcr-login.sh +188 -0
- package/seeds/agents/pass-baseline.md +61 -0
- package/seeds/agents/pass-contracts.md +30 -0
- package/seeds/agents/pass-data-safety.md +54 -0
- package/seeds/agents/pass-delivery.md +37 -0
- package/seeds/agents/pass-prod-risk.md +24 -0
- package/seeds/agents/pass-security.md +31 -0
- package/seeds/agents/pass-statelessness.md +27 -0
- package/seeds/agents/pass-ui.md +23 -0
- package/seeds/agents/pass-validate.md +50 -0
- package/seeds/prompts/conversation-system.md +117 -0
- package/seeds/prompts/eod-sweep.md +120 -0
- package/seeds/prompts/pass-common.md +52 -0
- package/skills/companion/adjudicate/SKILL.md +247 -0
- package/skills/companion/evidence/SKILL.md +150 -0
- package/skills/companion/land/SKILL.md +200 -0
- package/skills/companion/replay/SKILL.md +138 -0
- package/skills/companion/setup/SKILL.md +167 -0
- package/skills/companion/survey/SKILL.md +160 -0
- package/skills/selfimprove/README.md +34 -0
- package/skills/selfimprove/SKILL.md +127 -0
- package/skills/selfimprove/agents/openai.yaml +2 -0
- package/skills/selfimprove/commands/selfimprove.md +6 -0
- package/skills/selfimprove/references/fix-loop.md +49 -0
- package/skills/selfimprove/references/ledger.md +20 -0
- package/skills/selfimprove/references/setup.md +40 -0
- package/src/anomalies.ts +566 -0
- package/src/answerworker.ts +251 -0
- package/src/appstamp.ts +65 -0
- package/src/archive/admission.ts +3 -0
- package/src/archive/archivedb.ts +548 -0
- package/src/archive/archiver.ts +1963 -0
- package/src/archive/archivewrite.ts +279 -0
- package/src/archive/bundle.ts +333 -0
- package/src/archive/dbmove.ts +911 -0
- package/src/archive/duplicatecounts.ts +98 -0
- package/src/archive/eligibility.ts +181 -0
- package/src/archive/extract.ts +342 -0
- package/src/archive/fsutil.ts +415 -0
- package/src/archive/gzfile.ts +370 -0
- package/src/archive/kinds.ts +21 -0
- package/src/archive/livecheckpoint.ts +217 -0
- package/src/archive/liveretention.ts +180 -0
- package/src/archive/manifest.ts +519 -0
- package/src/archive/overseer.ts +336 -0
- package/src/archive/piglobal.ts +174 -0
- package/src/archive/plan.ts +612 -0
- package/src/archive/prarchive.ts +984 -0
- package/src/archive/prfiles.ts +406 -0
- package/src/archive/report.ts +252 -0
- package/src/archive/restore.ts +330 -0
- package/src/archive/rows.ts +187 -0
- package/src/archive/seal.ts +630 -0
- package/src/archive/status.ts +719 -0
- package/src/archive/storepass.ts +581 -0
- package/src/backfill.ts +362 -0
- package/src/bench/cost.ts +113 -0
- package/src/bench/exec.ts +90 -0
- package/src/bench/values.ts +13 -0
- package/src/botcontrol.ts +176 -0
- package/src/botworker.ts +953 -0
- package/src/capture.ts +321 -0
- package/src/cases.ts +1789 -0
- package/src/channelfs.ts +26 -0
- package/src/checklist.ts +506 -0
- package/src/ciretry.ts +142 -0
- package/src/cli.ts +2306 -0
- package/src/cliops.ts +385 -0
- package/src/clonedir.ts +15 -0
- package/src/commandeffects.ts +57 -0
- package/src/commands.ts +1704 -0
- package/src/companioninbox.ts +239 -0
- package/src/compare.ts +957 -0
- package/src/config.ts +2070 -0
- package/src/configcheck.ts +133 -0
- package/src/coreext.ts +47 -0
- package/src/daemon.ts +1327 -0
- package/src/debuground.ts +927 -0
- package/src/debugroundpi.ts +272 -0
- package/src/diagnostics.ts +14 -0
- package/src/digest.ts +183 -0
- package/src/dispatch.ts +2251 -0
- package/src/engine/answerguard.ts +27 -0
- package/src/engine/botsdk.ts +336 -0
- package/src/engine/caserunner-sdk.ts +423 -0
- package/src/engine/debugpi.ts +247 -0
- package/src/eod.ts +669 -0
- package/src/eodpinwatch.ts +556 -0
- package/src/escalation.ts +1253 -0
- package/src/eventloop.ts +1045 -0
- package/src/execboundary.ts +645 -0
- package/src/feedback.ts +1162 -0
- package/src/findingscheck.ts +298 -0
- package/src/fsdenied.ts +24 -0
- package/src/ghread.ts +242 -0
- package/src/github.ts +1539 -0
- package/src/githubtoken.ts +435 -0
- package/src/homes.ts +175 -0
- package/src/hostroute.ts +53 -0
- package/src/improvements.ts +787 -0
- package/src/install.ts +1103 -0
- package/src/installkind.ts +50 -0
- package/src/ipc/capability.ts +333 -0
- package/src/ipc/client.ts +269 -0
- package/src/ipc/control.ts +90 -0
- package/src/ipc/ghreadshim.ts +94 -0
- package/src/ipc/launcher.ts +65 -0
- package/src/ipc/permits.ts +362 -0
- package/src/ipc/postshim.ts +164 -0
- package/src/ipc/protocol.ts +342 -0
- package/src/ipc/server.ts +371 -0
- package/src/ipc/workerspec.ts +218 -0
- package/src/learner/learner.ts +1655 -0
- package/src/learner/miner.ts +1290 -0
- package/src/learner/packet.ts +340 -0
- package/src/learner/receipt.ts +168 -0
- package/src/learner/status.ts +107 -0
- package/src/ledgercheck.ts +157 -0
- package/src/lessonledger.ts +703 -0
- package/src/lessonselect.ts +888 -0
- package/src/lessonshadow.ts +810 -0
- package/src/levers.ts +393 -0
- package/src/live/projection.ts +491 -0
- package/src/live/publish.ts +92 -0
- package/src/live/read.ts +86 -0
- package/src/livecli.ts +336 -0
- package/src/loginhint.ts +61 -0
- package/src/loginrefresh/atomic.ts +76 -0
- package/src/loginrefresh/lock.ts +104 -0
- package/src/loginrefresh/main.ts +59 -0
- package/src/loginrefresh/pirefresh.ts +60 -0
- package/src/loginrefresh/refresher.ts +326 -0
- package/src/loginrefresh/supervisor.ts +273 -0
- package/src/loginrefresh/types.ts +35 -0
- package/src/memory/context.ts +385 -0
- package/src/memory/datafence.ts +9 -0
- package/src/memory/delivery.ts +171 -0
- package/src/memory/eventtags.ts +80 -0
- package/src/memory/health.ts +953 -0
- package/src/memory/import.ts +664 -0
- package/src/memory/layout.ts +261 -0
- package/src/memory/legacy-file.ts +104 -0
- package/src/memory/lessons.ts +447 -0
- package/src/memory/ovsession.ts +601 -0
- package/src/memory/relayout.ts +335 -0
- package/src/memory/roundactivity.ts +209 -0
- package/src/memory/selection.ts +989 -0
- package/src/memory/shadowstatus.ts +125 -0
- package/src/memory/store.ts +275 -0
- package/src/memory/textidentity.ts +8 -0
- package/src/metrics.ts +1056 -0
- package/src/missingconfig.ts +7 -0
- package/src/npmverbs.ts +266 -0
- package/src/onboard/choices.ts +255 -0
- package/src/onboard/engine.ts +537 -0
- package/src/onboard/launch.ts +103 -0
- package/src/onboard/pipin.ts +31 -0
- package/src/onboard/stepforward.ts +61 -0
- package/src/onboard/steps/appslug.ts +268 -0
- package/src/onboard/steps/bringup.ts +482 -0
- package/src/onboard/steps/compose.ts +490 -0
- package/src/onboard/steps/configdelivery.ts +58 -0
- package/src/onboard/steps/configfill.ts +1440 -0
- package/src/onboard/steps/deploysh.ts +105 -0
- package/src/onboard/steps/embeddings.ts +550 -0
- package/src/onboard/steps/escalation.ts +640 -0
- package/src/onboard/steps/githubaccount.ts +716 -0
- package/src/onboard/steps/githubapp.ts +1498 -0
- package/src/onboard/steps/golive.ts +579 -0
- package/src/onboard/steps/index.ts +82 -0
- package/src/onboard/steps/ingress.ts +974 -0
- package/src/onboard/steps/inventory.ts +526 -0
- package/src/onboard/steps/llmauth.ts +1180 -0
- package/src/onboard/steps/memory.ts +1347 -0
- package/src/onboard/steps/memorykeys.ts +85 -0
- package/src/onboard/steps/preflight.ts +191 -0
- package/src/onboard/steps/proof.ts +1042 -0
- package/src/onboard/steps/ssh.ts +377 -0
- package/src/onboard/steps/topology.ts +338 -0
- package/src/onboard/steps/transport.ts +680 -0
- package/src/onboard/steps/tuiroute.ts +119 -0
- package/src/onboard/steps/verifyup.ts +467 -0
- package/src/onboard/steps/vmdeploy.ts +442 -0
- package/src/onboard/toml.ts +50 -0
- package/src/onboard/toolnames.ts +34 -0
- package/src/opencli.ts +591 -0
- package/src/openpr.ts +568 -0
- package/src/openviking/client.ts +1131 -0
- package/src/openviking/context.ts +263 -0
- package/src/openviking/embedder.ts +516 -0
- package/src/openviking/gapsink.ts +63 -0
- package/src/openviking/health.ts +83 -0
- package/src/openviking/index.ts +119 -0
- package/src/openviking/lessonfind.ts +92 -0
- package/src/openviking/probe.ts +129 -0
- package/src/openviking/proc.ts +110 -0
- package/src/openviking/provisionreport.ts +160 -0
- package/src/openviking/reembed.ts +412 -0
- package/src/openviking/relayout.ts +177 -0
- package/src/openviking/sidecar-main.ts +38 -0
- package/src/openviking/sidecar.ts +106 -0
- package/src/openviking/store.ts +2025 -0
- package/src/openviking/supervisor.ts +474 -0
- package/src/openviking/types.ts +174 -0
- package/src/operator-recovery.ts +237 -0
- package/src/operatormessage.ts +52 -0
- package/src/operatorwrite.ts +25 -0
- package/src/outcomes.ts +1677 -0
- package/src/piauthcopy.ts +12 -0
- package/src/picli.ts +49 -0
- package/src/picwd.ts +25 -0
- package/src/pilogin.ts +37 -0
- package/src/pingpong.ts +1339 -0
- package/src/posting-journal.ts +554 -0
- package/src/posting-outbox.ts +810 -0
- package/src/posting-receipt.ts +341 -0
- package/src/posting.ts +603 -0
- package/src/postops.ts +832 -0
- package/src/pr-activity.ts +20 -0
- package/src/pr-author.ts +6 -0
- package/src/pr-conversation.ts +432 -0
- package/src/pr-session-lifecycle.ts +631 -0
- package/src/preflight.ts +391 -0
- package/src/priorresolve.ts +343 -0
- package/src/qcrbin.ts +186 -0
- package/src/recheck.ts +1776 -0
- package/src/reconcile.ts +1056 -0
- package/src/recordedfindings.ts +27 -0
- package/src/regression.ts +833 -0
- package/src/replay.ts +816 -0
- package/src/requiredpasses.ts +148 -0
- package/src/resumecheck.ts +246 -0
- package/src/reviewcli.ts +787 -0
- package/src/reviewcontext.ts +35 -0
- package/src/reviewdetach.ts +734 -0
- package/src/reviewhistory.ts +441 -0
- package/src/reviewhome.ts +36 -0
- package/src/reviewmemory.ts +133 -0
- package/src/reviewnow.ts +76 -0
- package/src/reviewrendercli.ts +139 -0
- package/src/round-work.ts +42 -0
- package/src/runhost.ts +108 -0
- package/src/scanauth.ts +36 -0
- package/src/scanbox.ts +1081 -0
- package/src/scancli.ts +1296 -0
- package/src/scandriverlog.ts +32 -0
- package/src/session-bridge.ts +139 -0
- package/src/session-command-payload.ts +35 -0
- package/src/session-command-supervisor.ts +1142 -0
- package/src/sessionjsonl.ts +88 -0
- package/src/sessions.ts +659 -0
- package/src/setup/adapters.ts +335 -0
- package/src/setup/baselines.ts +110 -0
- package/src/setup/caserunner.ts +611 -0
- package/src/setup/configcommit.ts +443 -0
- package/src/setup/engine.ts +1001 -0
- package/src/setup/facts.ts +627 -0
- package/src/setup/findings.ts +1264 -0
- package/src/setup/history.ts +443 -0
- package/src/setup/interview.ts +243 -0
- package/src/setup/ledger.ts +324 -0
- package/src/setup/pins.ts +66 -0
- package/src/setup/portrait.ts +635 -0
- package/src/setup/presentation.ts +18 -0
- package/src/setup/profile.ts +508 -0
- package/src/setup/replay.ts +370 -0
- package/src/setup/replaybuild.ts +392 -0
- package/src/setup/replayrun.ts +1096 -0
- package/src/setup/replaysource.ts +198 -0
- package/src/setup/retune.ts +415 -0
- package/src/setup/retunelog.ts +95 -0
- package/src/setup/scan.ts +1033 -0
- package/src/setup/scanbuild.ts +168 -0
- package/src/setup/scanfacts.ts +107 -0
- package/src/setup/scanlease.ts +297 -0
- package/src/setup/scanreport.ts +373 -0
- package/src/setup/scanrun.ts +2268 -0
- package/src/setup/scantree.ts +259 -0
- package/src/setup/stage2.ts +926 -0
- package/src/setup/stage2request.ts +347 -0
- package/src/setup/survey.ts +458 -0
- package/src/setup/surveyrun.ts +758 -0
- package/src/setup/textsniff.ts +95 -0
- package/src/setup/trackersink.ts +433 -0
- package/src/setup/triage.ts +768 -0
- package/src/setup/tuning.ts +766 -0
- package/src/setup/unitcut.ts +523 -0
- package/src/singleflight.ts +86 -0
- package/src/slack/announce.ts +911 -0
- package/src/slack/api.ts +303 -0
- package/src/slack/messages.ts +288 -0
- package/src/slack/origin.ts +599 -0
- package/src/slack/policy.ts +354 -0
- package/src/slack/reply.ts +201 -0
- package/src/slack/router.ts +285 -0
- package/src/slack/socket.ts +384 -0
- package/src/slack/types.ts +108 -0
- package/src/sqlitehint.ts +32 -0
- package/src/ssh-observation.ts +30 -0
- package/src/state.ts +8261 -0
- package/src/statemachine.ts +372 -0
- package/src/stubs.ts +68 -0
- package/src/takeover.ts +634 -0
- package/src/takeoverpi.ts +306 -0
- package/src/terminal-failure.ts +41 -0
- package/src/thread-resolution-refusal.ts +2 -0
- package/src/tmux.ts +153 -0
- package/src/trackerid.ts +41 -0
- package/src/transcriptindex.ts +665 -0
- package/src/tui/actions.ts +484 -0
- package/src/tui/alerts.ts +666 -0
- package/src/tui/app.ts +2026 -0
- package/src/tui/archiveops.ts +192 -0
- package/src/tui/autofile.ts +233 -0
- package/src/tui/board.ts +1529 -0
- package/src/tui/candidates.ts +889 -0
- package/src/tui/cellwidth.ts +148 -0
- package/src/tui/changelog-store.ts +503 -0
- package/src/tui/chord.ts +25 -0
- package/src/tui/clipboard.ts +92 -0
- package/src/tui/cmdbar.ts +299 -0
- package/src/tui/companion.ts +1495 -0
- package/src/tui/companionplan.ts +247 -0
- package/src/tui/companiontab.ts +83 -0
- package/src/tui/confighome.ts +155 -0
- package/src/tui/connect.ts +74 -0
- package/src/tui/deploy-ceremony.ts +104 -0
- package/src/tui/deploy-drain.ts +129 -0
- package/src/tui/deploy-process.ts +265 -0
- package/src/tui/deploytab.ts +1523 -0
- package/src/tui/design.ts +125 -0
- package/src/tui/digesttab.ts +214 -0
- package/src/tui/emptystate.ts +39 -0
- package/src/tui/evidence.ts +999 -0
- package/src/tui/feed.ts +604 -0
- package/src/tui/feedbacktab.ts +1077 -0
- package/src/tui/filters.ts +94 -0
- package/src/tui/ghread.ts +388 -0
- package/src/tui/historypull.ts +81 -0
- package/src/tui/inboxpull.ts +236 -0
- package/src/tui/index.ts +1656 -0
- package/src/tui/issuesink.ts +238 -0
- package/src/tui/jsonfile.ts +42 -0
- package/src/tui/keys.ts +109 -0
- package/src/tui/layout.ts +108 -0
- package/src/tui/learning.ts +627 -0
- package/src/tui/lessonswitch.ts +118 -0
- package/src/tui/livecontrol.ts +228 -0
- package/src/tui/memforward.ts +492 -0
- package/src/tui/memincident.ts +363 -0
- package/src/tui/memory.ts +620 -0
- package/src/tui/memtab.ts +606 -0
- package/src/tui/metricstab.ts +1177 -0
- package/src/tui/model.ts +165 -0
- package/src/tui/mouse.ts +98 -0
- package/src/tui/msg.ts +268 -0
- package/src/tui/nativecompanion.ts +417 -0
- package/src/tui/openurl.ts +21 -0
- package/src/tui/paint.ts +511 -0
- package/src/tui/panes.ts +98 -0
- package/src/tui/pipane.ts +219 -0
- package/src/tui/poll-hooks.ts +12 -0
- package/src/tui/poll.ts +147 -0
- package/src/tui/proposals.ts +838 -0
- package/src/tui/prpause.ts +159 -0
- package/src/tui/reload.ts +436 -0
- package/src/tui/remote.ts +421 -0
- package/src/tui/rollover.ts +969 -0
- package/src/tui/route.ts +173 -0
- package/src/tui/scantab.ts +1290 -0
- package/src/tui/setupentry.ts +93 -0
- package/src/tui/setupstate.ts +52 -0
- package/src/tui/sidebar.ts +749 -0
- package/src/tui/sshtriage.ts +631 -0
- package/src/tui/startup.ts +231 -0
- package/src/tui/tabs.ts +45 -0
- package/src/tui/termmirror.ts +224 -0
- package/src/tui/theme.ts +96 -0
- package/src/tui/ticketstab.ts +310 -0
- package/src/tui/tmuxsocket.ts +129 -0
- package/src/tui/trackertickets.ts +84 -0
- package/src/tui/unwedge.ts +274 -0
- package/src/tui/viewer.ts +575 -0
- package/src/tui/viewerinput.ts +173 -0
- package/src/updatenotice.ts +178 -0
- package/src/usage.ts +1154 -0
- package/src/verdicts.ts +4707 -0
- package/src/version.ts +80 -0
- package/src/wakes.ts +476 -0
- package/src/webhook.ts +951 -0
- package/src/webhookheal.ts +276 -0
- package/src/wire.ts +2182 -0
- package/src/worker-session-host.ts +602 -0
- package/src/workerbreaker.ts +156 -0
- package/src/workercontrol.ts +104 -0
- package/src/workerlease.ts +441 -0
- package/src/workerliveness.ts +103 -0
- package/src/workerlog.ts +79 -0
- package/src/workerruntime.ts +30 -0
- package/src/workersupervisor.ts +1538 -0
- package/src/workerusage.ts +42 -0
- package/src/workerworld.ts +433 -0
- package/src/worktrees.ts +1138 -0
- package/tests/fixtures/regression-cases.json +795 -0
- package/tests/fixtures/seed-manifest.json +19 -0
|
@@ -0,0 +1,1041 @@
|
|
|
1
|
+
// Typed access to config.toml — the single source of every runtime knob.
|
|
2
|
+
// The review sections (their types, defaults and parsers) live in
|
|
3
|
+
// packages/pi-plugin/src/reviewconfig.ts, the core's half; this module adds every other
|
|
4
|
+
// surface's, the install homes and the live config's loader, and re-exports
|
|
5
|
+
// the review half so its importers need not know where a knob lives.
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { resolve, dirname, isAbsolute, join } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { parse } from "smol-toml";
|
|
11
|
+
import { locateConfig, locateSecrets, missingConfigMessage, strandedCheckoutConfig, } from "./install.js";
|
|
12
|
+
import { packageRootFrom } from "@quickchatai/pi-quickreview/src/assetroot.js";
|
|
13
|
+
import { repoCloneDirName } from "./clonedir.js";
|
|
14
|
+
import { MissingConfigError } from "./missingconfig.js";
|
|
15
|
+
import { DEFAULT_LENS_GRANT_STAGGER_MS, DEFAULT_LENS_PERMITS } from "./ipc/permits.js";
|
|
16
|
+
import { configDeprecations, foldLegacyOwnerSlackId, MEMORY_DELIVERY_MODES, parseEngine, parseEscalation, parseGithubSection, parseGuardsSection, parseModels, parseOwnerSection, parsePiSection, parseReviewSection, parseScan, presetOf, req, requireGithubKeys, REVIEW_PRESETS, validateReviewSection, } from "@quickchatai/pi-quickreview/src/reviewconfig.js";
|
|
17
|
+
export * from "@quickchatai/pi-quickreview/src/reviewconfig.js";
|
|
18
|
+
/** Directory name of the base clone: `[github] clone_dir` when set, else the
|
|
19
|
+
* repo slug's basename ("owner/name" → "name"; a URL's trailing path segment,
|
|
20
|
+
* `.git` stripped), e.g. "acme/webapp" ⇒ "webapp". */
|
|
21
|
+
export function githubCloneDir(g) {
|
|
22
|
+
// ?? "": hand-rolled configs (tests) may omit both keys.
|
|
23
|
+
const explicit = (g.clone_dir ?? "").trim();
|
|
24
|
+
if (explicit)
|
|
25
|
+
return explicit;
|
|
26
|
+
return repoCloneDirName(g.repo ?? "");
|
|
27
|
+
}
|
|
28
|
+
/** Per-cause defaults. Absent causes fall back to `default_cooldown_min`. */
|
|
29
|
+
export const SLACK_CAUSE_DEFAULTS = {
|
|
30
|
+
"round.overdue": { enabled: true, cooldown_min: 60 },
|
|
31
|
+
"round.malformed_verdict": { enabled: true, cooldown_min: 60 },
|
|
32
|
+
"review.failed_loud": { enabled: true, cooldown_min: 60 },
|
|
33
|
+
"pr.not_picked_up": { enabled: true, cooldown_min: 120 },
|
|
34
|
+
"daemon.up": { enabled: true, cooldown_min: 0 },
|
|
35
|
+
"daemon.stopping": { enabled: true, cooldown_min: 0 },
|
|
36
|
+
"slack.cap_reached": { enabled: true, cooldown_min: 0 },
|
|
37
|
+
"reconcile.storm": { enabled: false, cooldown_min: 180 },
|
|
38
|
+
"digest.eod": { enabled: false, cooldown_min: 0 },
|
|
39
|
+
"pr.awaiting_author_stale": { enabled: false, cooldown_min: 1440 },
|
|
40
|
+
};
|
|
41
|
+
export const SLACK_POLICY_DEFAULTS = {
|
|
42
|
+
daily_turns: 80,
|
|
43
|
+
per_user_daily_turns: 20,
|
|
44
|
+
thread_replies_per_day: 6,
|
|
45
|
+
soft_exchange_limit: 3,
|
|
46
|
+
announcements_per_hour: 20,
|
|
47
|
+
default_cooldown_min: 60,
|
|
48
|
+
// Effective value comes from [slack.policy] timezone, else [ops] timezone
|
|
49
|
+
// (parseSlack) — this static default (= OPS_DEFAULTS.timezone, declared
|
|
50
|
+
// below) only reaches direct constructions that bypass parseConfig.
|
|
51
|
+
timezone: "UTC",
|
|
52
|
+
pickup_grace_min: 20,
|
|
53
|
+
downtime_notice_min: 5,
|
|
54
|
+
heartbeat_interval_min: 5,
|
|
55
|
+
storm_corrections: 5,
|
|
56
|
+
awaiting_author_stale_h: 48,
|
|
57
|
+
broadcast_verdicts: "never",
|
|
58
|
+
causes: SLACK_CAUSE_DEFAULTS,
|
|
59
|
+
};
|
|
60
|
+
/** [slack] is optional in config.toml, exactly like [tui] / [companion]. */
|
|
61
|
+
export const SLACK_DEFAULTS = {
|
|
62
|
+
enabled: false,
|
|
63
|
+
channel: "",
|
|
64
|
+
channel_kind: "public",
|
|
65
|
+
bot_token_file: "slack_bot_token",
|
|
66
|
+
app_token_file: "slack_app_token",
|
|
67
|
+
post_min_interval_ms: 1100,
|
|
68
|
+
reconnect_backoff_ms: [1000, 2000, 5000, 15000, 30000],
|
|
69
|
+
server_ping_timeout_ms: 30000,
|
|
70
|
+
catchup_max_age_s: 300,
|
|
71
|
+
max_reply_chars: 3000,
|
|
72
|
+
name_cache_ttl_s: 86400,
|
|
73
|
+
users: {},
|
|
74
|
+
policy: SLACK_POLICY_DEFAULTS,
|
|
75
|
+
};
|
|
76
|
+
export const RECHECK_DEFAULTS = {
|
|
77
|
+
enabled: true,
|
|
78
|
+
on_push: true,
|
|
79
|
+
on_ci: true,
|
|
80
|
+
on_base_advance: true,
|
|
81
|
+
};
|
|
82
|
+
export const OPENVIKING_ENDPOINTS = ["local", "remote"];
|
|
83
|
+
export const EMBEDDING_PROVIDERS = ["local", "openai"];
|
|
84
|
+
/**
|
|
85
|
+
* The LOCAL ENGLISH EMBEDDER: the model
|
|
86
|
+
* `embedding_provider = "local"` runs, served on loopback by
|
|
87
|
+
* `scripts/openviking-embedder.py` from the GGUF the image pins. Chosen by an
|
|
88
|
+
* offline retrieval evaluation over the reviewer's own memory
|
|
89
|
+
* (docs/memory-embeddings.md: MRR@10 0.56 against 0.34 for the engine's
|
|
90
|
+
* built-in Chinese-first model; ~25 ms per round query on one thread). The
|
|
91
|
+
* service's model table (`--describe`) carries the same name and dimension
|
|
92
|
+
* plus the query instruction; `tests/openviking-embedder.test.ts` holds the
|
|
93
|
+
* two together. Mirrored by `LOCAL_EMBEDDER` in scripts/openviking-reembed.mjs.
|
|
94
|
+
*/
|
|
95
|
+
export const LOCAL_EMBEDDING = Object.freeze({ model: "bge-small-en-v1.5-f16", dimension: 384 });
|
|
96
|
+
/** The engine's BUILT-IN local embedder — the retired meaning of `local`, and
|
|
97
|
+
* what an older store was embedded under. A config.toml that still spells it
|
|
98
|
+
* under `local` is read as the current local embedder rather than refused: the
|
|
99
|
+
* daemon must not stop booting over a value an earlier release required. The
|
|
100
|
+
* re-embed migration carries the store across. */
|
|
101
|
+
export const RETIRED_LOCAL_EMBEDDING = Object.freeze({
|
|
102
|
+
model: "bge-small-zh-v1.5-f16",
|
|
103
|
+
dimension: 512,
|
|
104
|
+
});
|
|
105
|
+
/** What an `openai` opt-in runs unless the operator names another model. */
|
|
106
|
+
export const HOSTED_EMBEDDING = Object.freeze({ model: "text-embedding-3-small", dimension: 1536 });
|
|
107
|
+
/** ov.conf's `embedding.dense.provider` under `local`: the engine's OpenAI-
|
|
108
|
+
* COMPATIBLE client — its async embedder — pointed at the loopback service.
|
|
109
|
+
* The wire format, never a destination. */
|
|
110
|
+
export const LOCAL_EMBEDDER_WIRE_PROVIDER = "openai";
|
|
111
|
+
/** `http://127.0.0.1:<port>/v1` — ov.conf's `api_base` under `local`. */
|
|
112
|
+
export function localEmbedderBaseUrl(c) {
|
|
113
|
+
return `http://127.0.0.1:${c.local_embedder_port}/v1`;
|
|
114
|
+
}
|
|
115
|
+
export function ovConfEmbedder(c) {
|
|
116
|
+
if (c.embedding_provider === "local")
|
|
117
|
+
return {
|
|
118
|
+
provider: LOCAL_EMBEDDER_WIRE_PROVIDER,
|
|
119
|
+
model: c.embedding_model,
|
|
120
|
+
dimension: c.embedding_dimension,
|
|
121
|
+
api_base: localEmbedderBaseUrl(c),
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
provider: c.embedding_provider,
|
|
125
|
+
model: c.embedding_model,
|
|
126
|
+
dimension: c.embedding_dimension,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** The three memory timeouts are BOUNDED — memory must never
|
|
130
|
+
* hold a round past a budget an operator can read off the config, and a
|
|
131
|
+
* mistyped 0 must not turn every seed memory-less. Inclusive ms. */
|
|
132
|
+
export const CONTEXT_TIMEOUT_BOUNDS_MS = { min: 100, max: 15_000 };
|
|
133
|
+
export const SEARCH_TIMEOUT_BOUNDS_MS = { min: 100, max: 15_000 };
|
|
134
|
+
export const HEALTH_TIMEOUT_BOUNDS_MS = { min: 100, max: 20_000 };
|
|
135
|
+
export const CASE_EMBED_TAIL_MAX_MS = 30_000;
|
|
136
|
+
/** `v` as an integer inside `bounds`, or `fallback` when it is not a finite
|
|
137
|
+
* number at all. */
|
|
138
|
+
function clampMs(v, bounds, fallback) {
|
|
139
|
+
const n = typeof v === "number" ? v : Number.NaN;
|
|
140
|
+
if (!Number.isFinite(n))
|
|
141
|
+
return fallback;
|
|
142
|
+
return Math.max(bounds.min, Math.min(bounds.max, Math.floor(n)));
|
|
143
|
+
}
|
|
144
|
+
/** The contract's hard ceiling on the lesson prefetch. */
|
|
145
|
+
export const LESSON_PREFETCH_MAX_MS = 2000;
|
|
146
|
+
/** The shadow prefetch's ceiling and default. The default covers
|
|
147
|
+
* the live VM's measured worst case — a find's 2.5 s p90 behind a case batch
|
|
148
|
+
* already on the embedder (two ~3.4 s embeddings, src/cases.ts). */
|
|
149
|
+
export const LESSON_SHADOW_PREFETCH_MAX_MS = 20_000;
|
|
150
|
+
export const LESSON_SHADOW_PREFETCH_DEFAULT_MS = 10_000;
|
|
151
|
+
/**
|
|
152
|
+
* The [memory] block, defaults filled and the delivery switch checked: an
|
|
153
|
+
* unknown `delivery` value REFUSES to load (a misspelt `"onn"` must not
|
|
154
|
+
* quietly mean shadow, or off), and the prefetch budget is clamped to the
|
|
155
|
+
* contract's ceiling.
|
|
156
|
+
*/
|
|
157
|
+
export function parseMemory(raw) {
|
|
158
|
+
const m = { ...MEMORY_DEFAULTS, ...raw };
|
|
159
|
+
if (!MEMORY_DELIVERY_MODES.includes(m.delivery))
|
|
160
|
+
throw new Error(`[memory] delivery must be one of ${MEMORY_DELIVERY_MODES.map((v) => `"${v}"`).join(", ")} (got ${JSON.stringify(m.delivery)})`);
|
|
161
|
+
const budget = Number(m.delivery_budget_ms);
|
|
162
|
+
m.delivery_budget_ms = Number.isFinite(budget)
|
|
163
|
+
? Math.max(1, Math.min(LESSON_PREFETCH_MAX_MS, Math.floor(budget)))
|
|
164
|
+
: LESSON_PREFETCH_MAX_MS;
|
|
165
|
+
const shadow = Number(m.shadow_budget_ms);
|
|
166
|
+
m.shadow_budget_ms = Number.isFinite(shadow)
|
|
167
|
+
? Math.max(1, Math.min(LESSON_SHADOW_PREFETCH_MAX_MS, Math.floor(shadow)))
|
|
168
|
+
: LESSON_SHADOW_PREFETCH_DEFAULT_MS;
|
|
169
|
+
m.context_timeout_ms = clampMs(m.context_timeout_ms, CONTEXT_TIMEOUT_BOUNDS_MS, MEMORY_DEFAULTS.context_timeout_ms);
|
|
170
|
+
m.case_embed_tail_ms = clampMs(m.case_embed_tail_ms, { min: 0, max: CASE_EMBED_TAIL_MAX_MS }, MEMORY_DEFAULTS.case_embed_tail_ms);
|
|
171
|
+
return m;
|
|
172
|
+
}
|
|
173
|
+
/** The quota a round's context search gives each area it searches when
|
|
174
|
+
* `[memory] context_quotas` names none (the round context assembler reads
|
|
175
|
+
* this same constant). */
|
|
176
|
+
export const DEFAULT_ROUND_QUOTA = 24;
|
|
177
|
+
export const MEMORY_DEFAULTS = {
|
|
178
|
+
context_tokens: 2000,
|
|
179
|
+
context_timeout_ms: 9000,
|
|
180
|
+
case_embed_tail_ms: 4000,
|
|
181
|
+
probe_interval_s: 120,
|
|
182
|
+
down_after_min: 10,
|
|
183
|
+
boot_grace_min: 5,
|
|
184
|
+
rewake_h: 6,
|
|
185
|
+
incident_ticket_after_min: 120,
|
|
186
|
+
backfill_interval_s: 60,
|
|
187
|
+
write_backlog_after_min: 120,
|
|
188
|
+
cases_interval_s: 120,
|
|
189
|
+
cases_backfill_days: 60,
|
|
190
|
+
lessons_mine_lead_min: 15,
|
|
191
|
+
lessons_mine_days: 45,
|
|
192
|
+
lessons_receipt_wait_min: 180,
|
|
193
|
+
lessons_expiry_ops_days: 7,
|
|
194
|
+
lessons_packet_new_max: 40,
|
|
195
|
+
lessons_recall_window_days: 14,
|
|
196
|
+
lessons_recurrence_days: 90,
|
|
197
|
+
lessons_digest_backfill_from: "2026-08-31",
|
|
198
|
+
lessons_digest_backfill_to: "2026-10-02",
|
|
199
|
+
context_quotas: { experiences: DEFAULT_ROUND_QUOTA },
|
|
200
|
+
delivery: "shadow",
|
|
201
|
+
delivery_budget_ms: LESSON_PREFETCH_MAX_MS,
|
|
202
|
+
shadow_budget_ms: LESSON_SHADOW_PREFETCH_DEFAULT_MS,
|
|
203
|
+
};
|
|
204
|
+
/** [openviking] is optional in config.toml — the defaults ARE the shipped
|
|
205
|
+
* configuration, exactly like [tui]/[companion]. */
|
|
206
|
+
export const OPENVIKING_DEFAULTS = {
|
|
207
|
+
enabled: true,
|
|
208
|
+
endpoint: "local",
|
|
209
|
+
version: "0.4.15",
|
|
210
|
+
llama_cpp_python_version: "0.3.35",
|
|
211
|
+
extension_commit: "d436baa23c83938b22bb0aab08b0ce48568b5ff4",
|
|
212
|
+
user: "reviewer",
|
|
213
|
+
account: "",
|
|
214
|
+
reviewer_key_file: "openviking_reviewer_key",
|
|
215
|
+
auth_mode: "api_key",
|
|
216
|
+
root_key_file: "openviking_root_key",
|
|
217
|
+
provision_users: ["reviewer", "companion"],
|
|
218
|
+
request_timeout_ms: 10000,
|
|
219
|
+
search_timeout_ms: 8000,
|
|
220
|
+
default_category: "experiences",
|
|
221
|
+
read_cache_ttl_ms: 15000,
|
|
222
|
+
host: "127.0.0.1",
|
|
223
|
+
port: 1933,
|
|
224
|
+
bin: "/opt/openviking/venv/bin/openviking-server",
|
|
225
|
+
home: "/opt/quickreview/state/openviking",
|
|
226
|
+
config_file: "", // → <home>/ov.conf
|
|
227
|
+
workspace: "", // → <home>/workspace
|
|
228
|
+
workers: 1,
|
|
229
|
+
queue_concurrency: 2,
|
|
230
|
+
health_interval_s: 30,
|
|
231
|
+
health_timeout_ms: 6000,
|
|
232
|
+
restart_backoff_ms: [1000, 2000, 5000, 15000, 30000, 60000],
|
|
233
|
+
restart_reset_after_s: 120,
|
|
234
|
+
embedding_provider: "local",
|
|
235
|
+
embedding_model: LOCAL_EMBEDDING.model,
|
|
236
|
+
embedding_dimension: LOCAL_EMBEDDING.dimension,
|
|
237
|
+
embedding_key_file: "openai_embeddings_api_key",
|
|
238
|
+
local_embedder_file: `/opt/openviking/models/${LOCAL_EMBEDDING.model}.gguf`,
|
|
239
|
+
local_embedder_url: `https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/d32f8c040ea3b516330eeb75b72bcc2d3a780ab7/${LOCAL_EMBEDDING.model}.gguf`,
|
|
240
|
+
local_embedder_sha256: "f0b2fef971e8366438bfd2d9aefea1b0115919389448806d290237f638bae999",
|
|
241
|
+
local_embedder_port: 1934,
|
|
242
|
+
local_embedder_threads: 1,
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* The [openviking] block, defaults filled and the embedder checked.
|
|
246
|
+
*
|
|
247
|
+
* The embedder is validated at LOAD time because the boot validates it too,
|
|
248
|
+
* and a memory engine that refuses to start is a silent outage: an unknown
|
|
249
|
+
* provider, a non-positive dimension, a `local` model/dimension that is not
|
|
250
|
+
* the local embedder's, or a local model-file pin that does not name that
|
|
251
|
+
* model are all config errors here.
|
|
252
|
+
*/
|
|
253
|
+
export function parseOpenViking(raw) {
|
|
254
|
+
const merged = { ...OPENVIKING_DEFAULTS, ...raw };
|
|
255
|
+
if (!OPENVIKING_ENDPOINTS.includes(merged.endpoint)) {
|
|
256
|
+
throw new Error(`config.toml: [openviking] endpoint must be one of ${OPENVIKING_ENDPOINTS.join(", ")} (got '${String(merged.endpoint)}')`);
|
|
257
|
+
}
|
|
258
|
+
// Bounded, never a tight loop or an unbounded wait.
|
|
259
|
+
merged.search_timeout_ms = clampMs(merged.search_timeout_ms, SEARCH_TIMEOUT_BOUNDS_MS, OPENVIKING_DEFAULTS.search_timeout_ms);
|
|
260
|
+
merged.health_timeout_ms = clampMs(merged.health_timeout_ms, HEALTH_TIMEOUT_BOUNDS_MS, OPENVIKING_DEFAULTS.health_timeout_ms);
|
|
261
|
+
// The defaults are the LOCAL embedder: a hosted opt-in that omits the model
|
|
262
|
+
// runs HOSTED_EMBEDDING, never the local model (which no hosted API serves).
|
|
263
|
+
// A named hosted model with no dimension has no default to fall back on.
|
|
264
|
+
if (merged.embedding_provider !== "local") {
|
|
265
|
+
if (raw.embedding_model === undefined) {
|
|
266
|
+
merged.embedding_model = HOSTED_EMBEDDING.model;
|
|
267
|
+
if (raw.embedding_dimension === undefined)
|
|
268
|
+
merged.embedding_dimension = HOSTED_EMBEDDING.dimension;
|
|
269
|
+
}
|
|
270
|
+
else if (raw.embedding_dimension === undefined) {
|
|
271
|
+
if (merged.embedding_model !== HOSTED_EMBEDDING.model)
|
|
272
|
+
throw new Error(`config.toml: [openviking] embedding_model = "${String(merged.embedding_model)}" needs its embedding_dimension set too`);
|
|
273
|
+
merged.embedding_dimension = HOSTED_EMBEDDING.dimension;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (merged.embedding_model === RETIRED_LOCAL_EMBEDDING.model &&
|
|
277
|
+
(raw.embedding_dimension === undefined ||
|
|
278
|
+
merged.embedding_dimension === RETIRED_LOCAL_EMBEDDING.dimension)) {
|
|
279
|
+
// An earlier release required this spelling under `local`. It means the
|
|
280
|
+
// current local embedder — the boot renders the same, and the re-embed
|
|
281
|
+
// migration moves the store across.
|
|
282
|
+
merged.embedding_model = LOCAL_EMBEDDING.model;
|
|
283
|
+
merged.embedding_dimension = LOCAL_EMBEDDING.dimension;
|
|
284
|
+
}
|
|
285
|
+
if (!EMBEDDING_PROVIDERS.includes(merged.embedding_provider)) {
|
|
286
|
+
throw new Error(`config.toml: [openviking] embedding_provider must be one of ${EMBEDDING_PROVIDERS.join(", ")} (got '${String(merged.embedding_provider)}')`);
|
|
287
|
+
}
|
|
288
|
+
if (!Number.isInteger(merged.embedding_dimension) || merged.embedding_dimension <= 0) {
|
|
289
|
+
throw new Error(`config.toml: [openviking] embedding_dimension must be a positive integer (got '${String(merged.embedding_dimension)}')`);
|
|
290
|
+
}
|
|
291
|
+
if (merged.embedding_provider === "local" &&
|
|
292
|
+
(merged.embedding_model !== LOCAL_EMBEDDING.model ||
|
|
293
|
+
merged.embedding_dimension !== LOCAL_EMBEDDING.dimension)) {
|
|
294
|
+
throw new Error(`config.toml: [openviking] embedding_provider = "local" runs the local English embedder, ${LOCAL_EMBEDDING.model} at ${LOCAL_EMBEDDING.dimension} dims — ` +
|
|
295
|
+
`the only local model the image pins; set embedding_model/embedding_dimension to it, or opt into a hosted provider`);
|
|
296
|
+
}
|
|
297
|
+
if (typeof merged.embedding_key_file !== "string" ||
|
|
298
|
+
merged.embedding_key_file.trim() === "" ||
|
|
299
|
+
merged.embedding_key_file.includes("/")) {
|
|
300
|
+
throw new Error("config.toml: [openviking] embedding_key_file must be a bare file name inside the secrets dir");
|
|
301
|
+
}
|
|
302
|
+
checkLocalEmbedderPin(merged);
|
|
303
|
+
return resolveOpenVikingPaths(merged);
|
|
304
|
+
}
|
|
305
|
+
/** The local embedder's model-file pin and service knobs. The
|
|
306
|
+
* file and the URL must both name `LOCAL_EMBEDDING.model`: a pin for another
|
|
307
|
+
* model would put a file the service's model table does not describe under a
|
|
308
|
+
* name the vector store trusts. */
|
|
309
|
+
function checkLocalEmbedderPin(c) {
|
|
310
|
+
const gguf = `${LOCAL_EMBEDDING.model}.gguf`;
|
|
311
|
+
const file = c.local_embedder_file;
|
|
312
|
+
if (typeof file !== "string" || !file.startsWith("/") || !file.endsWith(`/${gguf}`)) {
|
|
313
|
+
throw new Error(`config.toml: [openviking] local_embedder_file must be an absolute container path ending in /${gguf} (got '${String(file)}')`);
|
|
314
|
+
}
|
|
315
|
+
const url = c.local_embedder_url;
|
|
316
|
+
if (typeof url !== "string" || !url.startsWith("https://") || !url.endsWith(`/${gguf}`)) {
|
|
317
|
+
throw new Error(`config.toml: [openviking] local_embedder_url must be an https URL ending in /${gguf} (got '${String(url)}')`);
|
|
318
|
+
}
|
|
319
|
+
if (typeof c.local_embedder_sha256 !== "string" ||
|
|
320
|
+
!/^[0-9a-f]{64}$/.test(c.local_embedder_sha256)) {
|
|
321
|
+
throw new Error("config.toml: [openviking] local_embedder_sha256 must be the file's sha256, 64 lowercase hex digits");
|
|
322
|
+
}
|
|
323
|
+
const port = c.local_embedder_port;
|
|
324
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535 || port === c.port) {
|
|
325
|
+
throw new Error(`config.toml: [openviking] local_embedder_port must be a TCP port other than the server's own ${c.port} (got '${String(port)}')`);
|
|
326
|
+
}
|
|
327
|
+
const threads = c.local_embedder_threads;
|
|
328
|
+
if (!Number.isInteger(threads) || threads < 1 || threads > 16) {
|
|
329
|
+
throw new Error(`config.toml: [openviking] local_embedder_threads must be an integer in 1..16 (got '${String(threads)}')`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/** Derived paths: `config_file`/`workspace` default off `home`, so the three
|
|
333
|
+
* never drift apart in a hand-edited config. */
|
|
334
|
+
export function resolveOpenVikingPaths(c) {
|
|
335
|
+
const home = expandHome(c.home);
|
|
336
|
+
return {
|
|
337
|
+
...c,
|
|
338
|
+
home,
|
|
339
|
+
config_file: c.config_file ? expandHome(c.config_file) : join(home, "ov.conf"),
|
|
340
|
+
workspace: c.workspace ? expandHome(c.workspace) : join(home, "workspace"),
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** `http://host:port` — the one place the base URL is spelled. */
|
|
344
|
+
export function openVikingBaseUrl(c) {
|
|
345
|
+
return `http://${c.host}:${c.port}`;
|
|
346
|
+
}
|
|
347
|
+
/** `[eod] pinned_watchdog_window_min`'s default, and the watchdog's own. */
|
|
348
|
+
export const EOD_PINNED_WATCHDOG_WINDOW_MIN = 90;
|
|
349
|
+
/** Neutral default — a config that never names a zone runs on UTC days. */
|
|
350
|
+
export const OPS_DEFAULTS = { timezone: "UTC" };
|
|
351
|
+
/** The same Intl-based check the EOD machinery relies on (src/eod.ts builds
|
|
352
|
+
* an Intl.DateTimeFormat per zone): an unknown zone throws RangeError at
|
|
353
|
+
* formatter construction, so validate at parse time rather than at 18:00. */
|
|
354
|
+
export function assertIanaTimeZone(tz, where) {
|
|
355
|
+
try {
|
|
356
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
throw new Error(`config.toml: ${where} '${tz}' is not a valid IANA timezone`);
|
|
360
|
+
}
|
|
361
|
+
return tz;
|
|
362
|
+
}
|
|
363
|
+
/** A section carrying its own `timezone` (defaulted from [ops]), returned
|
|
364
|
+
* once that zone passes `assertIanaTimeZone`. */
|
|
365
|
+
function checkSectionTimeZone(section, where) {
|
|
366
|
+
assertIanaTimeZone(String(section.timezone), where);
|
|
367
|
+
return section;
|
|
368
|
+
}
|
|
369
|
+
export const INGRESS_DEFAULTS = {
|
|
370
|
+
shape: "none",
|
|
371
|
+
hostname_file: "",
|
|
372
|
+
debounce_ms: 3000,
|
|
373
|
+
sweep_interval_s: 300,
|
|
374
|
+
};
|
|
375
|
+
/** Does this install take webhooks at all? Not under the polling shape
|
|
376
|
+
* (and so never under `[github] auth = "user"`, which requires it): there the
|
|
377
|
+
* `/webhook` route refuses every delivery and no webhook secret is read. */
|
|
378
|
+
export function webhooksEnabled(cfg) {
|
|
379
|
+
return cfg.ingress.shape !== "polling";
|
|
380
|
+
}
|
|
381
|
+
/** The hostname file's resolved path — the one place the default is spelled. */
|
|
382
|
+
export function ingressHostnameFile(cfg, root) {
|
|
383
|
+
const configured = cfg.ingress.hostname_file.trim();
|
|
384
|
+
return configured ? expandHome(configured) : join(root, "state", "ingress", "hostname");
|
|
385
|
+
}
|
|
386
|
+
export const LOGIN_REFRESH_DEFAULTS = Object.freeze({
|
|
387
|
+
enabled: false,
|
|
388
|
+
margin_min: 90,
|
|
389
|
+
});
|
|
390
|
+
/** Parse `[login_refresh]`; with the refresher enabled, a margin that does not
|
|
391
|
+
* outlast the longest worker cap REFUSES to load (a worker would then outlive
|
|
392
|
+
* the token it borrowed). Disabled, nothing borrows, so the rule is not checked. */
|
|
393
|
+
export function parseLoginRefresh(raw, roundDeadlineMin) {
|
|
394
|
+
const enabled = raw.enabled ?? LOGIN_REFRESH_DEFAULTS.enabled;
|
|
395
|
+
if (typeof enabled !== "boolean")
|
|
396
|
+
throw new Error(`config.toml [login_refresh]: enabled must be true or false`);
|
|
397
|
+
const m = raw.margin_min ?? LOGIN_REFRESH_DEFAULTS.margin_min;
|
|
398
|
+
const margin = typeof m === "bigint" ? Number(m) : m;
|
|
399
|
+
if (typeof margin !== "number" || !Number.isFinite(margin) || margin > 1440)
|
|
400
|
+
throw new Error(`config.toml [login_refresh]: margin_min must be a number of minutes up to 1440 (got ${JSON.stringify(typeof m === "bigint" ? String(m) : m)})`);
|
|
401
|
+
if (enabled && margin <= roundDeadlineMin)
|
|
402
|
+
throw new Error(`config.toml [login_refresh]: margin_min (${margin}) must exceed [daemon] round_deadline_min (${roundDeadlineMin}), the longest worker cap`);
|
|
403
|
+
return { enabled, margin_min: margin };
|
|
404
|
+
}
|
|
405
|
+
/** Where a `qcr scan start` driver runs. `docker`: in a throwaway
|
|
406
|
+
* container from the scan sandbox image that mounts only the reviewed repo
|
|
407
|
+
* (read-only), the state home, the scan's own pi home and the config
|
|
408
|
+
* (src/scanbox.ts). `host`: a detached process on this machine. */
|
|
409
|
+
export const SCAN_SANDBOXES = ["docker", "host"];
|
|
410
|
+
/** The scan sandbox's own image (docker/companion/Dockerfile, built by
|
|
411
|
+
* `qcr scan rebuild`). Not the companion's: now that is the release
|
|
412
|
+
* image in `companion` mode, which the sandbox's one-shot entrypoint does not
|
|
413
|
+
* serve. */
|
|
414
|
+
export const SCAN_IMAGE_DEFAULT = "qcr-scan";
|
|
415
|
+
export const SCAN_SANDBOX_DEFAULTS = {
|
|
416
|
+
sandbox: "docker",
|
|
417
|
+
sandbox_set: false,
|
|
418
|
+
};
|
|
419
|
+
/** `[scan] sandbox / pihome_volume / image`; the pi home volume defaults to
|
|
420
|
+
* the companion's, the image to `SCAN_IMAGE_DEFAULT`. */
|
|
421
|
+
export function parseScanSandbox(raw, companion) {
|
|
422
|
+
const t = (typeof raw === "object" && raw !== null ? raw : {});
|
|
423
|
+
const name = (key, fallback) => {
|
|
424
|
+
const v = t[key];
|
|
425
|
+
if (v === undefined)
|
|
426
|
+
return fallback;
|
|
427
|
+
if (typeof v !== "string" || v.trim() === "")
|
|
428
|
+
throw new Error(`config.toml [scan] ${key} must be a non-empty name (got ${JSON.stringify(v)})`);
|
|
429
|
+
return v.trim();
|
|
430
|
+
};
|
|
431
|
+
const sandbox = t["sandbox"] ?? SCAN_SANDBOX_DEFAULTS.sandbox;
|
|
432
|
+
if (typeof sandbox !== "string" || !SCAN_SANDBOXES.includes(sandbox))
|
|
433
|
+
throw new Error(`config.toml [scan] sandbox must be "docker" or "host" (got ${JSON.stringify(sandbox)})`);
|
|
434
|
+
return {
|
|
435
|
+
sandbox: sandbox,
|
|
436
|
+
sandbox_set: t["sandbox"] !== undefined,
|
|
437
|
+
pihome_volume: name("pihome_volume", companion.pihome_volume),
|
|
438
|
+
image: name("image", SCAN_IMAGE_DEFAULT),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
export const LEVERS_DEFAULTS = {
|
|
442
|
+
session_drain_max_min: 30,
|
|
443
|
+
session_drain_budget_min_per_day: 90,
|
|
444
|
+
session_pause_max_min: 240,
|
|
445
|
+
session_pause_budget_min_per_day: 480,
|
|
446
|
+
};
|
|
447
|
+
/** Parse `[levers]`; a bound that is not a positive integer, or a budget
|
|
448
|
+
* smaller than its cap, refuses to load — a lever bound of zero or a budget
|
|
449
|
+
* that can never fund one full grant is a misconfiguration, not a setting. */
|
|
450
|
+
export function parseLevers(raw) {
|
|
451
|
+
const cfg = { ...LEVERS_DEFAULTS, ...raw };
|
|
452
|
+
for (const key of Object.keys(LEVERS_DEFAULTS)) {
|
|
453
|
+
const v = cfg[key];
|
|
454
|
+
if (!Number.isInteger(v) || v < 1) {
|
|
455
|
+
throw new Error(`config.toml [levers]: ${key} must be a positive integer number of minutes (got ${JSON.stringify(v)})`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
if (cfg.session_drain_budget_min_per_day < cfg.session_drain_max_min) {
|
|
459
|
+
throw new Error("config.toml [levers]: session_drain_budget_min_per_day must be at least session_drain_max_min");
|
|
460
|
+
}
|
|
461
|
+
if (cfg.session_pause_budget_min_per_day < cfg.session_pause_max_min) {
|
|
462
|
+
throw new Error("config.toml [levers]: session_pause_budget_min_per_day must be at least session_pause_max_min");
|
|
463
|
+
}
|
|
464
|
+
return cfg;
|
|
465
|
+
}
|
|
466
|
+
/** The values `[archive] mode` takes (docs/archiving.md §12). */
|
|
467
|
+
export const ARCHIVE_MODES = ["off", "plan", "on"];
|
|
468
|
+
export const ARCHIVE_DEFAULTS = Object.freeze({
|
|
469
|
+
mode: "plan",
|
|
470
|
+
after_days: 14,
|
|
471
|
+
events_after_days: 35,
|
|
472
|
+
interval_s: 60,
|
|
473
|
+
start_delay_min: 10,
|
|
474
|
+
tick_budget_s: 20,
|
|
475
|
+
max_prs_per_tick: 5,
|
|
476
|
+
max_mb_per_s: 8,
|
|
477
|
+
disk_headroom_gb: 2,
|
|
478
|
+
db_batch_rows: 500,
|
|
479
|
+
gzip_level: 6,
|
|
480
|
+
live_retention_days: 30,
|
|
481
|
+
live_cap_gb: 20,
|
|
482
|
+
});
|
|
483
|
+
/** Each numeric `[archive]` key's range, and whether it is a whole number. */
|
|
484
|
+
export const ARCHIVE_LIMITS = Object.freeze({
|
|
485
|
+
after_days: [7, 3650, true],
|
|
486
|
+
events_after_days: [31, 3650, true],
|
|
487
|
+
interval_s: [10, 3600, true],
|
|
488
|
+
start_delay_min: [0, 1440, true],
|
|
489
|
+
tick_budget_s: [1, 300, true],
|
|
490
|
+
max_prs_per_tick: [1, 100, true],
|
|
491
|
+
max_mb_per_s: [1, 200, false],
|
|
492
|
+
disk_headroom_gb: [0.5, 1024, false],
|
|
493
|
+
db_batch_rows: [100, 2000, true],
|
|
494
|
+
gzip_level: [1, 9, true],
|
|
495
|
+
live_retention_days: [7, 3650, true],
|
|
496
|
+
live_cap_gb: [0, 4096, false],
|
|
497
|
+
});
|
|
498
|
+
/**
|
|
499
|
+
* Parse `[archive]`. An unknown `mode` REFUSES to load (a misspelt `"onn"`
|
|
500
|
+
* must not quietly mean plan, or off), and so does a key that is not a
|
|
501
|
+
* number; a number out of its range is CLAMPED into it (`ARCHIVE_LIMITS`).
|
|
502
|
+
*/
|
|
503
|
+
export function parseArchive(raw) {
|
|
504
|
+
const mode = raw.mode ?? ARCHIVE_DEFAULTS.mode;
|
|
505
|
+
if (!ARCHIVE_MODES.includes(mode))
|
|
506
|
+
throw new Error(`config.toml [archive]: mode must be one of ${ARCHIVE_MODES.map((v) => `"${v}"`).join(", ")} (got ${JSON.stringify(mode)})`);
|
|
507
|
+
const out = { ...ARCHIVE_DEFAULTS, mode: mode };
|
|
508
|
+
for (const [key, [min, max, int]] of Object.entries(ARCHIVE_LIMITS)) {
|
|
509
|
+
const v = raw[key];
|
|
510
|
+
if (v === undefined)
|
|
511
|
+
continue;
|
|
512
|
+
const n = typeof v === "bigint" ? Number(v) : v;
|
|
513
|
+
if (typeof n !== "number" || !Number.isFinite(n))
|
|
514
|
+
throw new Error(`config.toml [archive]: ${key} must be a number (got ${JSON.stringify(typeof v === "bigint" ? String(v) : v)})`);
|
|
515
|
+
out[key] = Math.min(max, Math.max(min, int ? Math.floor(n) : n));
|
|
516
|
+
}
|
|
517
|
+
return out;
|
|
518
|
+
}
|
|
519
|
+
/** The team slug a configured `org/team` review team is requested as — the
|
|
520
|
+
* one rule the webhook's trigger and withdrawal, the trigger consumption and
|
|
521
|
+
* the backfill all match on. A bare slug is its own slug. */
|
|
522
|
+
export function reviewTeamSlug(reviewTeam) {
|
|
523
|
+
return reviewTeam.split("/")[1] ?? reviewTeam;
|
|
524
|
+
}
|
|
525
|
+
/** Defaults for [backfill], derived from the already-parsed [github] block. */
|
|
526
|
+
export function backfillDefaults(github) {
|
|
527
|
+
return {
|
|
528
|
+
bot_login: github.bot_login,
|
|
529
|
+
bot_actor: github.app_slug,
|
|
530
|
+
reviewed_label: github.reviewed_label,
|
|
531
|
+
trigger_label: github.trigger_label,
|
|
532
|
+
in_progress_label: github.in_progress_label,
|
|
533
|
+
review_team_slug: reviewTeamSlug(github.review_team),
|
|
534
|
+
concurrency: 2,
|
|
535
|
+
max_search_pages: 10,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
/** [tui] is optional in config.toml — the TUI is an operator convenience and
|
|
539
|
+
* older configs must keep parsing. */
|
|
540
|
+
export const TUI_DEFAULTS = {
|
|
541
|
+
target: "ssh",
|
|
542
|
+
ssh_host: "my-vm",
|
|
543
|
+
container: "quickreview-sandbox",
|
|
544
|
+
memory_container: "",
|
|
545
|
+
remote_state_dir: "/opt/quickreview/state",
|
|
546
|
+
remote_sandbox_root: "",
|
|
547
|
+
sudo_docker: true,
|
|
548
|
+
poll_interval_s: 3,
|
|
549
|
+
stale_after_s: 90,
|
|
550
|
+
msg_timeout_s: 30,
|
|
551
|
+
evidence_timeout_s: 60,
|
|
552
|
+
evidence_why_interval_s: 10,
|
|
553
|
+
};
|
|
554
|
+
/** The local companion image's tag: the release image (docker/Dockerfile) in
|
|
555
|
+
* `companion` mode, built on the host. */
|
|
556
|
+
export const COMPANION_IMAGE = "qcr-companion:release";
|
|
557
|
+
/** [companion] is optional in config.toml, exactly like [tui]. */
|
|
558
|
+
export const COMPANION_DEFAULTS = {
|
|
559
|
+
enabled: true,
|
|
560
|
+
container_name: "qcr-companion",
|
|
561
|
+
// The release image, locally built (`qcr companion rebuild`). A tag of its own:
|
|
562
|
+
// the name `qcr-companion` is the retired companion image on an existing
|
|
563
|
+
// PC, which the new container's entrypoint modes do not serve, so a
|
|
564
|
+
// recreate must find no image here and build the right one.
|
|
565
|
+
image: COMPANION_IMAGE,
|
|
566
|
+
pihome_volume: "companion-pihome",
|
|
567
|
+
session: "companion",
|
|
568
|
+
model: "openai-codex/gpt-6.1-sol:medium",
|
|
569
|
+
repo_dir: "", // → sandboxRoot()
|
|
570
|
+
tracker_dir: "", // → /tracker (rw) when set; empty = no tracker mount
|
|
571
|
+
tracker_docs_dir: "", // → /tracker-docs (ro) when set
|
|
572
|
+
reviewed_repo_dir: "", // → /reviewed-repo (ro) when set and present
|
|
573
|
+
evidence_dir: "~/.local/share/qcr/evidence", // → /evidence (ro)
|
|
574
|
+
feed_dir: "", // → <root>/state/companion/feed
|
|
575
|
+
alerts_dir: "", // → <root>/state/companion/alerts
|
|
576
|
+
ssh_dir: "~/.ssh",
|
|
577
|
+
build_context: "", // → <root> (the release image is built from it; Dockerfile at docker/Dockerfile)
|
|
578
|
+
overdue_grace_min: 30,
|
|
579
|
+
stale_alert_s: 300,
|
|
580
|
+
awaiting_age_h: 24,
|
|
581
|
+
cooldown_min: 20,
|
|
582
|
+
};
|
|
583
|
+
export const SINK_DEFAULTS = {
|
|
584
|
+
kind: "none",
|
|
585
|
+
root: "",
|
|
586
|
+
effort: "",
|
|
587
|
+
parent: "",
|
|
588
|
+
tickets_effort: "",
|
|
589
|
+
};
|
|
590
|
+
/** [sink] parse + validation. Misconfig is loud at boot, not a quiet no-op:
|
|
591
|
+
* a `wayfinder` sink missing its effort or parent would otherwise silently
|
|
592
|
+
* file nothing (or file into a nameless effort) forever. */
|
|
593
|
+
function parseSink(raw, companion) {
|
|
594
|
+
const sink = { ...SINK_DEFAULTS, ...raw };
|
|
595
|
+
if (!["wayfinder", "github", "none"].includes(sink.kind)) {
|
|
596
|
+
throw new Error(`config.toml [sink]: kind must be "wayfinder", "github" or "none" (got ${JSON.stringify(sink.kind)})`);
|
|
597
|
+
}
|
|
598
|
+
sink.root = sink.root ? expandHome(sink.root) : companion.tracker_dir;
|
|
599
|
+
if (sink.kind === "wayfinder") {
|
|
600
|
+
if (!sink.root.trim())
|
|
601
|
+
throw new Error('config.toml [sink]: kind = "wayfinder" requires a `root` (or a [companion] tracker_dir to default from)');
|
|
602
|
+
if (!sink.effort.trim())
|
|
603
|
+
throw new Error('config.toml [sink]: kind = "wayfinder" requires a non-empty `effort`');
|
|
604
|
+
if (!sink.parent.trim())
|
|
605
|
+
throw new Error('config.toml [sink]: kind = "wayfinder" requires a non-empty `parent`');
|
|
606
|
+
}
|
|
607
|
+
return sink;
|
|
608
|
+
}
|
|
609
|
+
/** The ticket projection's effort — its own key when set, else the filer's.
|
|
610
|
+
* Empty ⇒ the projection has nothing configured to read. */
|
|
611
|
+
export function sinkTicketsEffort(cfg) {
|
|
612
|
+
return cfg.sink.tickets_effort.trim() || cfg.sink.effort.trim();
|
|
613
|
+
}
|
|
614
|
+
/** Default lost-prompt grace when [daemon] carries no
|
|
615
|
+
* `round_stall_grace_min`: long enough that a slow first tool call is never
|
|
616
|
+
* mistaken for a dropped prompt, far shorter than the round deadline. */
|
|
617
|
+
export const DEFAULT_ROUND_STALL_GRACE_MIN = 10;
|
|
618
|
+
/** Default self-requeue budget per PR head when [daemon] carries no
|
|
619
|
+
* `max_self_requeues`. */
|
|
620
|
+
export const DEFAULT_MAX_SELF_REQUEUES = 2;
|
|
621
|
+
/** Default prompt-redelivery budget per round. Two is enough to cover
|
|
622
|
+
* a delivery that raced a busy session and one that raced a session restart;
|
|
623
|
+
* a third failure is no longer a delivery problem, so escalating beats
|
|
624
|
+
* re-sending the same file forever. */
|
|
625
|
+
export const DEFAULT_MAX_PROMPT_REDELIVERIES = 2;
|
|
626
|
+
/** Finite daemon→pi stage bounds. The 45-minute hard run cap is above the
|
|
627
|
+
* measured live maximum (~23 minutes) yet materially below the 75-minute
|
|
628
|
+
* defense-in-depth round deadline. */
|
|
629
|
+
export const DEFAULT_SESSION_COMMAND_START_LEASE_S = 120;
|
|
630
|
+
export const DEFAULT_SESSION_BRIDGE_READY_TIMEOUT_S = 30;
|
|
631
|
+
export const DEFAULT_SESSION_COMMAND_RUNNING_MAX_MIN = 45;
|
|
632
|
+
export const DEFAULT_ROUND_FIRST_PASS_MAX_MIN = 5;
|
|
633
|
+
export const DEFAULT_ROUND_PASSES_MAX_MIN = 35;
|
|
634
|
+
export const DEFAULT_ROUND_FINALIZE_GRACE_MIN = 5;
|
|
635
|
+
/** Measured posting→verdict tails run to ~6.5 min; 15 is over twice that and
|
|
636
|
+
* still well inside the 75-minute round deadline. */
|
|
637
|
+
export const DEFAULT_ROUND_POSTED_TAIL_GRACE_MIN = 15;
|
|
638
|
+
/** `[daemon] follow_up_sweep_extra_min`'s default. */
|
|
639
|
+
export const DEFAULT_FOLLOW_UP_SWEEP_EXTRA_MIN = 20;
|
|
640
|
+
/** The round stage bounds in minutes, each with its code default: the one
|
|
641
|
+
* resolution status publication and the stage supervisor both use. */
|
|
642
|
+
export function resolveRoundStageBounds(daemon) {
|
|
643
|
+
return {
|
|
644
|
+
first_pass_max_min: daemon.round_first_pass_max_min ?? DEFAULT_ROUND_FIRST_PASS_MAX_MIN,
|
|
645
|
+
passes_max_min: daemon.round_passes_max_min ?? DEFAULT_ROUND_PASSES_MAX_MIN,
|
|
646
|
+
running_max_min: daemon.session_command_running_max_min ?? DEFAULT_SESSION_COMMAND_RUNNING_MAX_MIN,
|
|
647
|
+
follow_up_sweep_extra_min: daemon.follow_up_sweep_extra_min ?? DEFAULT_FOLLOW_UP_SWEEP_EXTRA_MIN,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
export const DEFAULT_POSTING_RECEIPT_GRACE_S = 120;
|
|
651
|
+
/** Three retries, exponential,
|
|
652
|
+
* all inside an hour of the first failure. */
|
|
653
|
+
export const DEFAULT_POSTING_RETRY_OFFSETS_MIN = [4, 12, 36];
|
|
654
|
+
export const DEFAULT_POSTING_RETRY_WINDOW_MIN = 60;
|
|
655
|
+
export const DEFAULT_SESSION_COMMAND_UNKNOWN_GRACE_S = 60;
|
|
656
|
+
export const DEFAULT_SESSION_COMMAND_UNKNOWN_MAX_CHECKS = 1;
|
|
657
|
+
export const DEFAULT_SESSION_COMMAND_MAX_START_RETRIES = 2;
|
|
658
|
+
/** A post-verdict compaction can take over a minute with the container
|
|
659
|
+
* CPU-starved; ten minutes is several times the worst seen and still well
|
|
660
|
+
* inside the 75-minute round deadline. */
|
|
661
|
+
export const DEFAULT_SESSION_COMPACTION_MAX_S = 600;
|
|
662
|
+
/** The idle-PR answer worker: ten minutes of wall clock, two dollars. */
|
|
663
|
+
export const DEFAULT_ANSWER_TIMEOUT_S = 600;
|
|
664
|
+
export const DEFAULT_ANSWER_CAP_USD = 2;
|
|
665
|
+
export const DEFAULT_ROUND_STAGE_SUPERVISOR_STALE_S = 180;
|
|
666
|
+
/** The app's root: the checkout (or image tree) this module runs from. The
|
|
667
|
+
* review core's shipped data is found through `assetRoot` (packages/pi-plugin/src/assetroot.ts). */
|
|
668
|
+
export function sandboxRoot() {
|
|
669
|
+
return packageRootFrom(dirname(fileURLToPath(import.meta.url)), "sandbox root");
|
|
670
|
+
}
|
|
671
|
+
export function expandHome(p) {
|
|
672
|
+
return p.startsWith("~/") || p === "~" ? resolve(homedir(), p.slice(2)) : p;
|
|
673
|
+
}
|
|
674
|
+
/** Host paths for every companion mount: a set path gets its `~` expanded (a relative one stays relative); "" means derive from root. */
|
|
675
|
+
export function resolveCompanionPaths(c, root = sandboxRoot()) {
|
|
676
|
+
return {
|
|
677
|
+
...c,
|
|
678
|
+
repo_dir: c.repo_dir ? expandHome(c.repo_dir) : root,
|
|
679
|
+
tracker_dir: c.tracker_dir ? expandHome(c.tracker_dir) : "",
|
|
680
|
+
tracker_docs_dir: c.tracker_docs_dir ? expandHome(c.tracker_docs_dir) : "",
|
|
681
|
+
reviewed_repo_dir: expandHome(c.reviewed_repo_dir),
|
|
682
|
+
evidence_dir: c.evidence_dir ? expandHome(c.evidence_dir) : resolve(root, "evidence"),
|
|
683
|
+
feed_dir: c.feed_dir ? expandHome(c.feed_dir) : resolve(root, "state", "companion", "feed"),
|
|
684
|
+
alerts_dir: c.alerts_dir
|
|
685
|
+
? expandHome(c.alerts_dir)
|
|
686
|
+
: resolve(root, "state", "companion", "alerts"),
|
|
687
|
+
ssh_dir: expandHome(c.ssh_dir),
|
|
688
|
+
build_context: c.build_context ? expandHome(c.build_context) : root,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* `[caps]` parsed with each numeric cap CHECKED, not cast: a key missing
|
|
693
|
+
* from an operator's file must never reach `checkDiffstat` as `undefined`,
|
|
694
|
+
* where `files > undefined` is `false` and the cap would pass. A cap the
|
|
695
|
+
* daemon cannot compare against is a startup refusal: the improvement
|
|
696
|
+
* channel is the one place this system pushes code, and it must never run uncapped.
|
|
697
|
+
*/
|
|
698
|
+
export function parseCaps(raw) {
|
|
699
|
+
const cap = (key) => {
|
|
700
|
+
const v = raw[key];
|
|
701
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < 0) {
|
|
702
|
+
throw new Error(`config.toml [caps]: ${key} must be a non-negative number (got ${JSON.stringify(v)})`);
|
|
703
|
+
}
|
|
704
|
+
return v;
|
|
705
|
+
};
|
|
706
|
+
const isStrings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
707
|
+
const denyPrefixes = () => {
|
|
708
|
+
const prefixes = raw.improvement_pr_deny_prefixes;
|
|
709
|
+
if (prefixes === undefined)
|
|
710
|
+
return [...IMPROVEMENT_DENY_PREFIXES_DEFAULT];
|
|
711
|
+
if (isStrings(prefixes))
|
|
712
|
+
return [...prefixes];
|
|
713
|
+
throw new Error(`config.toml [caps]: improvement_pr_deny_prefixes must be an array of strings (got ${JSON.stringify(prefixes)})`);
|
|
714
|
+
};
|
|
715
|
+
return {
|
|
716
|
+
improvement_pr_max_lines: cap("improvement_pr_max_lines"),
|
|
717
|
+
improvement_pr_max_files: cap("improvement_pr_max_files"),
|
|
718
|
+
improvement_pr_per_day: cap("improvement_pr_per_day"),
|
|
719
|
+
improvement_pr_per_week: cap("improvement_pr_per_week"),
|
|
720
|
+
issues_per_day: cap("issues_per_day"),
|
|
721
|
+
improvement_pr_deny_prefixes: denyPrefixes(),
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
/** The shipped improvement-PR path denylist. Lives here (not in
|
|
725
|
+
* improvements.ts) so config carries the default without a runtime import cycle. */
|
|
726
|
+
export const IMPROVEMENT_DENY_PREFIXES_DEFAULT = [
|
|
727
|
+
"migrations/",
|
|
728
|
+
"infra/",
|
|
729
|
+
"ansible/",
|
|
730
|
+
".github/workflows/",
|
|
731
|
+
];
|
|
732
|
+
export function parseConfig(toml) {
|
|
733
|
+
const raw = parse(toml);
|
|
734
|
+
for (const line of configDeprecations(raw))
|
|
735
|
+
console.warn(`[quickreviewd] ${line}`);
|
|
736
|
+
const github = parseGithubSection(raw);
|
|
737
|
+
const preset = presetOf(raw);
|
|
738
|
+
const engine = parseEngine((raw.engine ?? {}));
|
|
739
|
+
const companion = resolveCompanionPaths({
|
|
740
|
+
...COMPANION_DEFAULTS,
|
|
741
|
+
...(raw.companion ?? {}),
|
|
742
|
+
});
|
|
743
|
+
// [ops] is optional so older configs keep parsing; [eod] and
|
|
744
|
+
// [slack.policy] timezones default from it below, own-section value wins.
|
|
745
|
+
const ops = {
|
|
746
|
+
timezone: assertIanaTimeZone(String((raw.ops ?? {}).timezone ?? OPS_DEFAULTS.timezone), "[ops] timezone"),
|
|
747
|
+
};
|
|
748
|
+
// [ingress] is optional: absent ⇒ shape "none", nothing starts.
|
|
749
|
+
const ingress = {
|
|
750
|
+
...INGRESS_DEFAULTS,
|
|
751
|
+
...(raw.ingress ?? {}),
|
|
752
|
+
};
|
|
753
|
+
if (!["none", "tunnel-file", "polling"].includes(ingress.shape)) {
|
|
754
|
+
throw new Error(`config.toml [ingress]: shape must be "none", "tunnel-file" or "polling" (got ${JSON.stringify(ingress.shape)})`);
|
|
755
|
+
}
|
|
756
|
+
// The person's own credential has no webhook: GitHub delivers webhooks to
|
|
757
|
+
// an App, and the person has none. So that mode is polling-only, and any
|
|
758
|
+
// other shape is refused here rather than left to run half-wired.
|
|
759
|
+
if (github.auth === "user" && ingress.shape !== "polling") {
|
|
760
|
+
throw new Error(`config.toml: [github] auth = "user" runs polling-only — set [ingress] shape = "polling" ` +
|
|
761
|
+
`(got ${JSON.stringify(ingress.shape)}${raw.ingress === undefined ? ", the default for an absent [ingress]" : ""}). ` +
|
|
762
|
+
`Webhooks and the webhook self-heal need a GitHub App: use auth = "app" for them.`);
|
|
763
|
+
}
|
|
764
|
+
const cfg = {
|
|
765
|
+
dry_run: Boolean(req(raw, "dry_run")),
|
|
766
|
+
ops,
|
|
767
|
+
ingress,
|
|
768
|
+
github,
|
|
769
|
+
server: { ...req(raw, "server") },
|
|
770
|
+
// Every optional knob defaults so older configs keep parsing.
|
|
771
|
+
daemon: {
|
|
772
|
+
max_self_requeues: DEFAULT_MAX_SELF_REQUEUES,
|
|
773
|
+
expire_overdue_after_h: 24,
|
|
774
|
+
session_command_start_lease_s: DEFAULT_SESSION_COMMAND_START_LEASE_S,
|
|
775
|
+
session_bridge_ready_timeout_s: DEFAULT_SESSION_BRIDGE_READY_TIMEOUT_S,
|
|
776
|
+
session_command_running_max_min: DEFAULT_SESSION_COMMAND_RUNNING_MAX_MIN,
|
|
777
|
+
round_first_pass_max_min: DEFAULT_ROUND_FIRST_PASS_MAX_MIN,
|
|
778
|
+
round_passes_max_min: DEFAULT_ROUND_PASSES_MAX_MIN,
|
|
779
|
+
round_finalize_grace_min: DEFAULT_ROUND_FINALIZE_GRACE_MIN,
|
|
780
|
+
round_posted_tail_grace_min: DEFAULT_ROUND_POSTED_TAIL_GRACE_MIN,
|
|
781
|
+
follow_up_sweep_extra_min: DEFAULT_FOLLOW_UP_SWEEP_EXTRA_MIN,
|
|
782
|
+
posting_receipt_grace_s: DEFAULT_POSTING_RECEIPT_GRACE_S,
|
|
783
|
+
posting_retry_offsets_min: [...DEFAULT_POSTING_RETRY_OFFSETS_MIN],
|
|
784
|
+
posting_retry_window_min: DEFAULT_POSTING_RETRY_WINDOW_MIN,
|
|
785
|
+
session_command_unknown_grace_s: DEFAULT_SESSION_COMMAND_UNKNOWN_GRACE_S,
|
|
786
|
+
session_command_unknown_max_checks: DEFAULT_SESSION_COMMAND_UNKNOWN_MAX_CHECKS,
|
|
787
|
+
session_command_max_start_retries: DEFAULT_SESSION_COMMAND_MAX_START_RETRIES,
|
|
788
|
+
session_compaction_max_s: DEFAULT_SESSION_COMPACTION_MAX_S,
|
|
789
|
+
lens_permits: DEFAULT_LENS_PERMITS,
|
|
790
|
+
lens_grant_stagger_ms: DEFAULT_LENS_GRANT_STAGGER_MS,
|
|
791
|
+
answer_timeout_s: DEFAULT_ANSWER_TIMEOUT_S,
|
|
792
|
+
answer_cap_usd: DEFAULT_ANSWER_CAP_USD,
|
|
793
|
+
round_stage_supervisor_stale_s: DEFAULT_ROUND_STAGE_SUPERVISOR_STALE_S,
|
|
794
|
+
...req(raw, "daemon"),
|
|
795
|
+
},
|
|
796
|
+
// heartbeat_time defaults so older configs keep parsing; the timezone
|
|
797
|
+
// defaults from [ops], own [eod] value wins — and is checked as [ops] is.
|
|
798
|
+
eod: checkSectionTimeZone({
|
|
799
|
+
heartbeat_time: "09:00",
|
|
800
|
+
pinned_watchdog: true,
|
|
801
|
+
pinned_watchdog_window_min: EOD_PINNED_WATCHDOG_WINDOW_MIN,
|
|
802
|
+
timezone: ops.timezone,
|
|
803
|
+
...req(raw, "eod"),
|
|
804
|
+
}, "[eod] timezone"),
|
|
805
|
+
caps: parseCaps(req(raw, "caps")),
|
|
806
|
+
models: parseModels(req(raw, "models"), REVIEW_PRESETS[preset].effort),
|
|
807
|
+
engine,
|
|
808
|
+
pi: parsePiSection(raw),
|
|
809
|
+
openviking: parseOpenViking((raw.openviking ?? {})),
|
|
810
|
+
memory: parseMemory((raw.memory ?? {})),
|
|
811
|
+
tui: { ...TUI_DEFAULTS, ...(raw.tui ?? {}) },
|
|
812
|
+
companion,
|
|
813
|
+
sink: parseSink((raw.sink ?? {}), companion),
|
|
814
|
+
backfill: { ...backfillDefaults(github), ...(raw.backfill ?? {}) },
|
|
815
|
+
guards: parseGuardsSection(raw),
|
|
816
|
+
recheck: { ...RECHECK_DEFAULTS, ...(raw.recheck ?? {}) },
|
|
817
|
+
review: parseReviewSection(raw, preset),
|
|
818
|
+
escalation: parseEscalation((raw.escalation ?? {})),
|
|
819
|
+
levers: parseLevers((raw.levers ?? {})),
|
|
820
|
+
slack: parseSlack((raw.slack ?? {}), ops.timezone),
|
|
821
|
+
owner: parseOwnerSection(raw),
|
|
822
|
+
scan: parseScan(raw.scan),
|
|
823
|
+
scan_sandbox: parseScanSandbox(raw.scan, companion),
|
|
824
|
+
archive: parseArchive((raw.archive ?? {})),
|
|
825
|
+
login_refresh: parseLoginRefresh((raw.login_refresh ?? {}), Number(req(raw, "daemon").round_deadline_min ?? 75)),
|
|
826
|
+
};
|
|
827
|
+
validateReviewSection(cfg);
|
|
828
|
+
foldLegacyOwnerSlackId(raw, cfg.owner);
|
|
829
|
+
requireGithubKeys(cfg.github);
|
|
830
|
+
// Every secrets reader in the daemon reads THIS field, so the
|
|
831
|
+
// install locator decides it here, once, for all of them.
|
|
832
|
+
cfg.github.secrets_dir = locateSecrets({
|
|
833
|
+
configured: typeof cfg.github.secrets_dir === "string" ? cfg.github.secrets_dir : "",
|
|
834
|
+
}).path;
|
|
835
|
+
if (cfg.tui.target !== "ssh" && cfg.tui.target !== "local") {
|
|
836
|
+
throw new Error(`config.toml [tui]: target must be "ssh" or "local" (got ${JSON.stringify(cfg.tui.target)})`);
|
|
837
|
+
}
|
|
838
|
+
const firstPass = cfg.daemon.round_first_pass_max_min ?? DEFAULT_ROUND_FIRST_PASS_MAX_MIN;
|
|
839
|
+
const passes = cfg.daemon.round_passes_max_min ?? DEFAULT_ROUND_PASSES_MAX_MIN;
|
|
840
|
+
const running = cfg.daemon.session_command_running_max_min ?? DEFAULT_SESSION_COMMAND_RUNNING_MAX_MIN;
|
|
841
|
+
const finalize = cfg.daemon.round_finalize_grace_min ?? DEFAULT_ROUND_FINALIZE_GRACE_MIN;
|
|
842
|
+
const stageBounds = [firstPass, passes, running, finalize];
|
|
843
|
+
if (!(stageBounds.every((v) => typeof v === "number" && Number.isFinite(v)) &&
|
|
844
|
+
firstPass > 0 &&
|
|
845
|
+
firstPass < passes &&
|
|
846
|
+
passes < running &&
|
|
847
|
+
finalize > 0 &&
|
|
848
|
+
finalize < running)) {
|
|
849
|
+
throw new Error("config.toml: require finite numbers 0 < round_first_pass_max_min < round_passes_max_min < session_command_running_max_min and 0 < round_finalize_grace_min < session_command_running_max_min");
|
|
850
|
+
}
|
|
851
|
+
// The two second-scale daemon→pi bounds become command deadlines
|
|
852
|
+
// (`toISOString`), which a non-finite value would throw at the first command.
|
|
853
|
+
for (const key of ["session_command_start_lease_s", "session_bridge_ready_timeout_s"]) {
|
|
854
|
+
const v = cfg.daemon[key];
|
|
855
|
+
if (!(typeof v === "number" && Number.isFinite(v) && v > 0))
|
|
856
|
+
throw new Error(`config.toml: require a finite number [daemon] ${key} > 0`);
|
|
857
|
+
}
|
|
858
|
+
const postedTail = cfg.daemon.round_posted_tail_grace_min ?? DEFAULT_ROUND_POSTED_TAIL_GRACE_MIN;
|
|
859
|
+
if (!(typeof postedTail === "number" && Number.isFinite(postedTail) && postedTail > 0)) {
|
|
860
|
+
throw new Error("config.toml: require round_posted_tail_grace_min > 0");
|
|
861
|
+
}
|
|
862
|
+
const sweepExtra = cfg.daemon.follow_up_sweep_extra_min ?? DEFAULT_FOLLOW_UP_SWEEP_EXTRA_MIN;
|
|
863
|
+
if (!(typeof sweepExtra === "number" && Number.isFinite(sweepExtra) && sweepExtra >= 0)) {
|
|
864
|
+
throw new Error("config.toml: require follow_up_sweep_extra_min >= 0");
|
|
865
|
+
}
|
|
866
|
+
const retryWindow = cfg.daemon.posting_retry_window_min ?? DEFAULT_POSTING_RETRY_WINDOW_MIN;
|
|
867
|
+
const retryOffsets = cfg.daemon.posting_retry_offsets_min ?? DEFAULT_POSTING_RETRY_OFFSETS_MIN;
|
|
868
|
+
if (!(typeof retryWindow === "number" && Number.isFinite(retryWindow) && retryWindow > 0) ||
|
|
869
|
+
!Array.isArray(retryOffsets) ||
|
|
870
|
+
retryOffsets.length === 0 ||
|
|
871
|
+
!retryOffsets.every((m, i) => typeof m === "number" &&
|
|
872
|
+
Number.isFinite(m) &&
|
|
873
|
+
m > 0 &&
|
|
874
|
+
m < retryWindow &&
|
|
875
|
+
(i === 0 || m > retryOffsets[i - 1]))) {
|
|
876
|
+
throw new Error("config.toml: require posting_retry_offsets_min = a non-empty, strictly increasing list of minutes, each > 0 and < posting_retry_window_min (> 0)");
|
|
877
|
+
}
|
|
878
|
+
const lensPermits = cfg.daemon.lens_permits ?? DEFAULT_LENS_PERMITS;
|
|
879
|
+
if (!(Number.isSafeInteger(lensPermits) && lensPermits >= 1)) {
|
|
880
|
+
throw new Error("config.toml: require an integer [daemon] lens_permits >= 1");
|
|
881
|
+
}
|
|
882
|
+
const lensStagger = cfg.daemon.lens_grant_stagger_ms ?? DEFAULT_LENS_GRANT_STAGGER_MS;
|
|
883
|
+
if (!(typeof lensStagger === "number" && Number.isFinite(lensStagger) && lensStagger >= 0)) {
|
|
884
|
+
throw new Error("config.toml: require a finite number [daemon] lens_grant_stagger_ms >= 0");
|
|
885
|
+
}
|
|
886
|
+
const answerTimeout = cfg.daemon.answer_timeout_s ?? DEFAULT_ANSWER_TIMEOUT_S;
|
|
887
|
+
if (!(typeof answerTimeout === "number" && Number.isFinite(answerTimeout) && answerTimeout > 0)) {
|
|
888
|
+
throw new Error("config.toml: require a finite number [daemon] answer_timeout_s > 0");
|
|
889
|
+
}
|
|
890
|
+
const answerCap = cfg.daemon.answer_cap_usd ?? DEFAULT_ANSWER_CAP_USD;
|
|
891
|
+
if (!(typeof answerCap === "number" && Number.isFinite(answerCap) && answerCap > 0)) {
|
|
892
|
+
throw new Error("config.toml: require a finite number [daemon] answer_cap_usd > 0");
|
|
893
|
+
}
|
|
894
|
+
const compactionMax = cfg.daemon.session_compaction_max_s ?? DEFAULT_SESSION_COMPACTION_MAX_S;
|
|
895
|
+
if (!(typeof compactionMax === "number" && Number.isFinite(compactionMax) && compactionMax > 0)) {
|
|
896
|
+
throw new Error("config.toml: require session_compaction_max_s > 0");
|
|
897
|
+
}
|
|
898
|
+
// Shape checks are pure, so they fire on every parse (tests included);
|
|
899
|
+
// the token-file check is I/O and lives in validateSlackConfig.
|
|
900
|
+
checkSlackShape(cfg.slack, cfg.owner);
|
|
901
|
+
delete cfg.daemon["overseer_rotation_days"];
|
|
902
|
+
return cfg;
|
|
903
|
+
}
|
|
904
|
+
function parseSlack(raw, defaultTimezone) {
|
|
905
|
+
// Inbound turns went with the overseer: nothing routes a Slack message to a
|
|
906
|
+
// model any more. A config that still asks for it is refused, not ignored,
|
|
907
|
+
// so nobody believes the bot is listening.
|
|
908
|
+
if (raw.inbound !== undefined && raw.inbound !== false) {
|
|
909
|
+
throw new Error("config.toml [slack]: `inbound` is retired — Slack inbound turns went with the overseer " +
|
|
910
|
+
"(the router refuses them: dropped_no_overseer); outbound announcements are unchanged. Remove the key.");
|
|
911
|
+
}
|
|
912
|
+
const rawPolicy = (raw.policy ?? {});
|
|
913
|
+
// A cause with no cooldown of its own takes the configured default — the
|
|
914
|
+
// same one an unlisted cause gets (`causePolicy`).
|
|
915
|
+
const defaultCooldown = rawPolicy.default_cooldown_min ?? SLACK_POLICY_DEFAULTS.default_cooldown_min;
|
|
916
|
+
const causes = { ...SLACK_CAUSE_DEFAULTS };
|
|
917
|
+
for (const [cause, v] of Object.entries((rawPolicy.causes ?? {}))) {
|
|
918
|
+
causes[cause] = {
|
|
919
|
+
enabled: v.enabled ?? causes[cause]?.enabled ?? true,
|
|
920
|
+
cooldown_min: Number(v.cooldown_min ?? causes[cause]?.cooldown_min ?? defaultCooldown),
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
const { causes: _drop, ...policyScalars } = rawPolicy;
|
|
924
|
+
// `legacy_owner_slack_id` is the legacy alias for [owner] slack_id —
|
|
925
|
+
// consumed by parseConfig's fold, never carried on the parsed shape.
|
|
926
|
+
const { legacy_owner_slack_id: _legacyOwnerId, inbound: _retiredInbound, ...rawScalars } = raw;
|
|
927
|
+
const slack = {
|
|
928
|
+
...SLACK_DEFAULTS,
|
|
929
|
+
...rawScalars,
|
|
930
|
+
users: { ...(raw.users ?? {}) },
|
|
931
|
+
// The day boundary defaults from [ops]; an explicit
|
|
932
|
+
// [slack.policy] timezone still wins.
|
|
933
|
+
policy: {
|
|
934
|
+
...SLACK_POLICY_DEFAULTS,
|
|
935
|
+
timezone: defaultTimezone,
|
|
936
|
+
...policyScalars,
|
|
937
|
+
causes,
|
|
938
|
+
},
|
|
939
|
+
};
|
|
940
|
+
// An explicit zone is checked as [ops]'s is — when the concierge is on;
|
|
941
|
+
// a switched-off section is a draft, and nothing reads its clock.
|
|
942
|
+
if (slack.enabled)
|
|
943
|
+
checkSectionTimeZone(slack.policy, "[slack.policy] timezone");
|
|
944
|
+
// Token *files* are names under secrets_dir, but an absolute or ~-rooted
|
|
945
|
+
// override must still work — expand here so every reader sees one shape.
|
|
946
|
+
slack.bot_token_file = expandHome(slack.bot_token_file);
|
|
947
|
+
slack.app_token_file = expandHome(slack.app_token_file);
|
|
948
|
+
return slack;
|
|
949
|
+
}
|
|
950
|
+
/** Absolute path of a Slack token file: a bare name resolves under
|
|
951
|
+
* [github].secrets_dir, an absolute/~ path is taken as given. */
|
|
952
|
+
export function slackTokenPath(cfg, which) {
|
|
953
|
+
const name = which === "bot" ? cfg.slack.bot_token_file : cfg.slack.app_token_file;
|
|
954
|
+
return isAbsolute(name) ? name : join(cfg.github.secrets_dir, name);
|
|
955
|
+
}
|
|
956
|
+
/** Pure (I/O-free) part of Slack boot validation. When disabled, nothing at
|
|
957
|
+
* all is required — the concierge is simply not there. When enabled, the
|
|
958
|
+
* owner's Slack id (`[owner] slack_id`, legacy alias
|
|
959
|
+
* `[slack] legacy_owner_slack_id`) must be set and be a key of [slack.users]. */
|
|
960
|
+
function checkSlackShape(slack, owner) {
|
|
961
|
+
if (!slack.enabled)
|
|
962
|
+
return;
|
|
963
|
+
const fail = (msg) => {
|
|
964
|
+
throw new Error(`config.toml [slack]: ${msg}`);
|
|
965
|
+
};
|
|
966
|
+
if (!slack.channel.trim())
|
|
967
|
+
fail("enabled = true requires a non-empty `channel`");
|
|
968
|
+
if (slack.channel_kind !== "public" && slack.channel_kind !== "private") {
|
|
969
|
+
fail(`channel_kind must be "public" or "private" (got ${JSON.stringify(slack.channel_kind)})`);
|
|
970
|
+
}
|
|
971
|
+
if (!owner.slack_id.trim())
|
|
972
|
+
fail("enabled = true requires a non-empty `[owner] slack_id`");
|
|
973
|
+
if (!(owner.slack_id in slack.users)) {
|
|
974
|
+
fail(`[owner] slack_id '${owner.slack_id}' must appear as a key in [slack.users] (it is the only source of own-PR rights)`);
|
|
975
|
+
}
|
|
976
|
+
for (const key of [
|
|
977
|
+
"daily_turns",
|
|
978
|
+
"per_user_daily_turns",
|
|
979
|
+
"thread_replies_per_day",
|
|
980
|
+
"announcements_per_hour",
|
|
981
|
+
]) {
|
|
982
|
+
const cap = slack.policy[key];
|
|
983
|
+
if (typeof cap !== "number" || !Number.isFinite(cap) || cap < 0)
|
|
984
|
+
fail(`policy.${key} must be a finite non-negative number`);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
export const fsSecretReader = (path) => {
|
|
988
|
+
let v;
|
|
989
|
+
try {
|
|
990
|
+
v = readFileSync(path, "utf8").trim();
|
|
991
|
+
}
|
|
992
|
+
catch (err) {
|
|
993
|
+
if (err.code === "ENOENT")
|
|
994
|
+
return undefined;
|
|
995
|
+
throw new Error(`cannot read secret file '${path}': ${err.message}`, { cause: err });
|
|
996
|
+
}
|
|
997
|
+
return v.length > 0 ? v : undefined;
|
|
998
|
+
};
|
|
999
|
+
/**
|
|
1000
|
+
* Full Slack boot validation — shape plus token-file presence. A missing or
|
|
1001
|
+
* empty token is a HARD startup error: the concierge never degrades silently
|
|
1002
|
+
* into a read-only half-presence in the channel. Disabled ⇒ nothing is read.
|
|
1003
|
+
*/
|
|
1004
|
+
export function validateSlackConfig(cfg, deps = {}) {
|
|
1005
|
+
checkSlackShape(cfg.slack, cfg.owner);
|
|
1006
|
+
if (!cfg.slack.enabled)
|
|
1007
|
+
return;
|
|
1008
|
+
const read = deps.readSecret ?? fsSecretReader;
|
|
1009
|
+
for (const which of ["bot", "app"]) {
|
|
1010
|
+
const path = slackTokenPath(cfg, which);
|
|
1011
|
+
if (!read(path)) {
|
|
1012
|
+
throw new Error(`config.toml [slack]: ${which} token file '${path}' is missing or empty — Slack cannot start`);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
let cached = null;
|
|
1017
|
+
/**
|
|
1018
|
+
* The live config's path for this process, decided by the install locator:
|
|
1019
|
+
* `$QCR_CONFIG`, else the install's config home — never the checkout's
|
|
1020
|
+
* `config.toml`. The ONE answer every no-argument
|
|
1021
|
+
* `loadConfig()` reads, and the one the daemon hands its sessions.
|
|
1022
|
+
*/
|
|
1023
|
+
export function liveConfigPath() {
|
|
1024
|
+
return locateConfig().path;
|
|
1025
|
+
}
|
|
1026
|
+
export function loadConfig(path) {
|
|
1027
|
+
if (cached && !path)
|
|
1028
|
+
return cached;
|
|
1029
|
+
const p = path ?? liveConfigPath();
|
|
1030
|
+
if (!path && !existsSync(p)) {
|
|
1031
|
+
// A missing live config says where it was looked for, and — when the
|
|
1032
|
+
// checkout still strands one — how to move it.
|
|
1033
|
+
throw new MissingConfigError(missingConfigMessage(locateConfig(), strandedCheckoutConfig({ root: sandboxRoot() })));
|
|
1034
|
+
}
|
|
1035
|
+
const cfg = parseConfig(readFileSync(p, "utf8"));
|
|
1036
|
+
validateSlackConfig(cfg);
|
|
1037
|
+
if (!path)
|
|
1038
|
+
cached = cfg;
|
|
1039
|
+
return cfg;
|
|
1040
|
+
}
|
|
1041
|
+
//# sourceMappingURL=config.js.map
|