@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,803 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# qcr-update — the thin updater that `provision` installs on the VM once
|
|
3
|
+
# (/usr/local/sbin/qcr-update, root 0755). Every deploy afterwards is
|
|
4
|
+
#
|
|
5
|
+
# tar -C <config home> -cf - config.toml profiles \
|
|
6
|
+
# | ssh vm sudo qcr-update <version>@<daemon index digest> \
|
|
7
|
+
# --memory-digest <memory index digest> [--cutover-ack <version>]
|
|
8
|
+
#
|
|
9
|
+
# and that is the ONLY thing a deploy runs on the VM (scripts/deploy.sh
|
|
10
|
+
# release). Nothing is rsynced, built or installed: the images were built once
|
|
11
|
+
# by CI and are pulled by digest.
|
|
12
|
+
#
|
|
13
|
+
# The config home arrives as a tar on stdin: config.toml and profiles/ only.
|
|
14
|
+
# The updater REFUSES a tar with a secrets/ entry (secrets stay with
|
|
15
|
+
# provision), with an absolute or `..` path, with a link, or with any other
|
|
16
|
+
# top-level name.
|
|
17
|
+
#
|
|
18
|
+
# Order of a run (a refusal before "stop" changes nothing on the VM):
|
|
19
|
+
# lock flock, one updater at a time
|
|
20
|
+
# drain refuse unless status.json says draining=true, running_rounds=0
|
|
21
|
+
# layout on the legacy layout, refuse without --cutover-ack <version>
|
|
22
|
+
# pull pull both images BY DIGEST, check the digests and the labels
|
|
23
|
+
# runspec refuse an image whose qcr.runspec label is newer than
|
|
24
|
+
# update.conf's: "re-run provision"
|
|
25
|
+
# stage-config unpack the tar into config-home.next
|
|
26
|
+
# config-check the NEW image's `qcr config check --json` on it
|
|
27
|
+
# --- from here a failure is RESCUED ---
|
|
28
|
+
# stop stop the daemon container
|
|
29
|
+
# snapshot state.db(+wal/shm) and a tar of state/pi-sessions into
|
|
30
|
+
# <backups>/<version>-<ts>/ (root, 0600; pihome never)
|
|
31
|
+
# preflight the new image's `daemon --preflight` on a scratch copy of
|
|
32
|
+
# the snapshot, --network none. Required: an image without
|
|
33
|
+
# the qcr.preflight label was refused at "pull"
|
|
34
|
+
# seed legacy layout only: seed the sidecar store once (copy plus
|
|
35
|
+
# checksum verify; the daemon's old store is left untouched)
|
|
36
|
+
# swap config-home -> .prev, .next -> config-home
|
|
37
|
+
# sidecar-start / sidecar-ready start the memory sidecar, wait for /ready
|
|
38
|
+
# (a long timeout: a re-embed is a boot)
|
|
39
|
+
# recreate recreate the daemon container on the new image. At the
|
|
40
|
+
# cutover this is the point of no return: the first boot
|
|
41
|
+
# migrates forward.
|
|
42
|
+
#
|
|
43
|
+
# RESCUE (any failure from "stop" up to the recreate): restore the previous
|
|
44
|
+
# config, remove the newly started sidecar (and put the old one back), start
|
|
45
|
+
# the OLD daemon container, wait for its first reconcile in status.json (a
|
|
46
|
+
# healthy legacy boot lifts the drain, and the first reconcile is the
|
|
47
|
+
# observable that it ran), re-send `drain on` through the operator channel,
|
|
48
|
+
# confirm draining=true, and exit non-zero naming the step. Between the
|
|
49
|
+
# auto-lift and the re-sent drain the dispatch pump may already have started
|
|
50
|
+
# held pending_wakes rounds: the bot is left drained but rounds may be
|
|
51
|
+
# running, and a retry waits for running_rounds 0. A failure AFTER the
|
|
52
|
+
# recreate keeps the drain on (a failed first reconcile never lifts it) and is
|
|
53
|
+
# fixed forward.
|
|
54
|
+
#
|
|
55
|
+
# qcr-update status [--json] the layout, the image digests and labels, the
|
|
56
|
+
# run-spec version and fingerprint, the drain
|
|
57
|
+
# state and the last run
|
|
58
|
+
#
|
|
59
|
+
# The run spec is /etc/qcr/update.conf (KEY=VALUE, root-owned, rendered by
|
|
60
|
+
# `deploy.sh provision` from group_vars). Its RUNSPEC_FINGERPRINT is the
|
|
61
|
+
# sha256 of every other KEY=VALUE line, in order; this script recomputes it.
|
|
62
|
+
#
|
|
63
|
+
# Test seam: run as a non-root user, QCR_UPDATE_CONF, QCR_UPDATE_DOCKER,
|
|
64
|
+
# QCR_UPDATE_POLL_S, QCR_UPDATE_NAP_S, QCR_RESCUE_WAIT_S, QCR_DRAIN_RECEIPT_WAIT_S, QCR_MEMORY_READY_TIMEOUT_S and
|
|
65
|
+
# QCR_UPDATE_FAIL_AT=<step> are honoured. As root none of
|
|
66
|
+
# them is: root reads /etc/qcr/update.conf and runs `docker`. (sudo also resets
|
|
67
|
+
# the environment.) tests/qcr-update.test.ts drives it with a fake docker.
|
|
68
|
+
|
|
69
|
+
set -Eeuo pipefail
|
|
70
|
+
umask 077
|
|
71
|
+
|
|
72
|
+
SELF="qcr-update"
|
|
73
|
+
|
|
74
|
+
# ---- the seam ----------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
TEST_MODE=0
|
|
77
|
+
if [[ "$(id -u)" -eq 0 ]]; then
|
|
78
|
+
CONF=/etc/qcr/update.conf
|
|
79
|
+
DOCKER=docker
|
|
80
|
+
POLL_S=5
|
|
81
|
+
FAIL_AT=""
|
|
82
|
+
RESCUE_WAIT_S=300
|
|
83
|
+
DRAIN_WAIT_S=120
|
|
84
|
+
READY_WAIT_S=""
|
|
85
|
+
NAP_S=5
|
|
86
|
+
elif [[ -n "${QCR_UPDATE_CONF:-}" ]]; then
|
|
87
|
+
TEST_MODE=1
|
|
88
|
+
CONF="$QCR_UPDATE_CONF"
|
|
89
|
+
DOCKER="${QCR_UPDATE_DOCKER:-docker}"
|
|
90
|
+
POLL_S="${QCR_UPDATE_POLL_S:-5}"
|
|
91
|
+
FAIL_AT="${QCR_UPDATE_FAIL_AT:-}"
|
|
92
|
+
RESCUE_WAIT_S="${QCR_RESCUE_WAIT_S:-300}"
|
|
93
|
+
DRAIN_WAIT_S="${QCR_DRAIN_RECEIPT_WAIT_S:-120}"
|
|
94
|
+
READY_WAIT_S="${QCR_MEMORY_READY_TIMEOUT_S:-}"
|
|
95
|
+
NAP_S="${QCR_UPDATE_NAP_S:-$POLL_S}"
|
|
96
|
+
else
|
|
97
|
+
echo "$SELF: must run as root (sudo qcr-update ...)" >&2
|
|
98
|
+
exit 2
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
LOG_FILE=""
|
|
102
|
+
log() {
|
|
103
|
+
local line="$SELF: $*"
|
|
104
|
+
echo "$line" >&2
|
|
105
|
+
[[ -z "$LOG_FILE" ]] || echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) $line" >>"$LOG_FILE" 2>/dev/null || true
|
|
106
|
+
}
|
|
107
|
+
die() {
|
|
108
|
+
log "$*"
|
|
109
|
+
exit 1
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# ---- the run spec -------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
declare -A C=()
|
|
115
|
+
REQUIRED_KEYS=(
|
|
116
|
+
RUNSPEC_VERSION RUNSPEC_FINGERPRINT SANDBOX_ROOT APP_ROOT
|
|
117
|
+
DAEMON_CONTAINER MEMORY_CONTAINER DAEMON_IMAGE_REPO MEMORY_IMAGE_REPO
|
|
118
|
+
MEMORY_NETWORK WEBHOOK_PORT CONTAINER_UID TOOL_UID TOOL_GID TZ
|
|
119
|
+
DAEMON_CPUS DAEMON_MEMORY MEMORY_CPUS MEMORY_MEMORY
|
|
120
|
+
MEMORY_STATE_DIR OPENVIKING_HOME OPENVIKING_PORT BASE_CLONE_DIR LEGACY_SANDBOX_ROOT
|
|
121
|
+
BACKUP_DIR UPDATE_STATE_DIR
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
fingerprint_of() {
|
|
125
|
+
grep -E '^[A-Z][A-Z0-9_]*=' "$1" | grep -v '^RUNSPEC_FINGERPRINT=' | sha256sum | cut -d' ' -f1
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
load_conf() {
|
|
129
|
+
[[ -f "$CONF" ]] || die "no run spec at $CONF — run \`deploy.sh provision\` first"
|
|
130
|
+
if [[ $TEST_MODE -eq 0 ]]; then
|
|
131
|
+
local owner mode
|
|
132
|
+
owner="$(stat -c '%u' "$CONF")"
|
|
133
|
+
mode="$(stat -c '%a' "$CONF")"
|
|
134
|
+
[[ "$owner" == 0 ]] || die "$CONF is not owned by root"
|
|
135
|
+
[[ "${mode: -1}" != [2367] && "${mode: -2:1}" != [2367] ]] || die "$CONF is writable by group or others (mode $mode)"
|
|
136
|
+
fi
|
|
137
|
+
local line key val
|
|
138
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
139
|
+
[[ -z "$line" || "$line" == \#* ]] && continue
|
|
140
|
+
[[ "$line" =~ ^([A-Z][A-Z0-9_]*)=([A-Za-z0-9_./:@+,-]*)$ ]] || die "$CONF has a line this updater will not read: ${line:0:60}"
|
|
141
|
+
key="${BASH_REMATCH[1]}"
|
|
142
|
+
val="${BASH_REMATCH[2]}"
|
|
143
|
+
C["$key"]="$val"
|
|
144
|
+
done <"$CONF"
|
|
145
|
+
for key in "${REQUIRED_KEYS[@]}"; do
|
|
146
|
+
[[ -n "${C[$key]:-}" ]] || die "$CONF lacks $key — re-run provision"
|
|
147
|
+
done
|
|
148
|
+
[[ "$(fingerprint_of "$CONF")" == "${C[RUNSPEC_FINGERPRINT]}" ]] ||
|
|
149
|
+
die "$CONF does not match its RUNSPEC_FINGERPRINT (edited by hand?) — re-run provision"
|
|
150
|
+
[[ "${C[RUNSPEC_VERSION]}" =~ ^[0-9]+$ ]] || die "$CONF RUNSPEC_VERSION is not a number"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# ---- docker helpers ------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
d() { "$DOCKER" "$@"; }
|
|
156
|
+
|
|
157
|
+
# Every lookup by name is `container inspect`: a bare `docker inspect` resolves any
|
|
158
|
+
# object, and the memory network shares the sidecar's name (the 1.0.2 cutover
|
|
159
|
+
# took the network for an old sidecar and failed renaming it).
|
|
160
|
+
|
|
161
|
+
# A container's label, or "" (a missing container or label is "").
|
|
162
|
+
container_label() {
|
|
163
|
+
d container inspect -f "{{index .Config.Labels \"$2\"}}" "$1" 2>/dev/null | sed 's/^<no value>$//' || true
|
|
164
|
+
}
|
|
165
|
+
image_label() {
|
|
166
|
+
d image inspect -f "{{index .Config.Labels \"$2\"}}" "$1" 2>/dev/null | sed 's/^<no value>$//' || true
|
|
167
|
+
}
|
|
168
|
+
container_exists() { d container inspect -f '{{.Id}}' "$1" >/dev/null 2>&1; }
|
|
169
|
+
container_running() { [[ "$(d container inspect -f '{{.State.Running}}' "$1" 2>/dev/null || true)" == true ]]; }
|
|
170
|
+
|
|
171
|
+
# release | legacy | none — of the daemon container.
|
|
172
|
+
detect_layout() {
|
|
173
|
+
if ! container_exists "${C[DAEMON_CONTAINER]}"; then echo none; return; fi
|
|
174
|
+
if [[ "$(container_label "${C[DAEMON_CONTAINER]}" qcr.layout)" == release ]]; then echo release; else echo legacy; fi
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# ---- the drain ------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
STATUS_JSON() { echo "${C[SANDBOX_ROOT]}/state/status.json"; }
|
|
180
|
+
|
|
181
|
+
# First `"key": value` of status.json, or "".
|
|
182
|
+
status_value() {
|
|
183
|
+
local f; f="$(STATUS_JSON)"
|
|
184
|
+
[[ -f "$f" ]] || return 0
|
|
185
|
+
grep -m1 -o "\"$1\"[[:space:]]*:[[:space:]]*\"\?[^,}\" ]*" "$f" 2>/dev/null | sed -E 's/^[^:]*:[[:space:]]*"?//' || true
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
# ---- status ---------------------------------------------------------------------
|
|
189
|
+
|
|
190
|
+
json_str() { printf '"%s"' "$(printf '%s' "$1" | tr -d '\000-\037"\\')"; }
|
|
191
|
+
json_bool_or_null() { case "$1" in true|false) printf '%s' "$1" ;; *) printf null ;; esac; }
|
|
192
|
+
json_num_or_null() { if [[ "$1" =~ ^[0-9]+$ ]]; then printf '%s' "$1"; else printf null; fi; }
|
|
193
|
+
|
|
194
|
+
image_block() {
|
|
195
|
+
local container="$1" img id
|
|
196
|
+
if ! container_exists "$container"; then printf null; return; fi
|
|
197
|
+
img="$(d container inspect -f '{{.Config.Image}}' "$container" 2>/dev/null || true)"
|
|
198
|
+
printf '{"container":%s,"running":%s,"image":%s,"layout":%s,"build_sha":%s,"runspec":%s,"preflight":%s,"pi":%s}' \
|
|
199
|
+
"$(json_str "$container")" "$(container_running "$container" && echo true || echo false)" \
|
|
200
|
+
"$(json_str "$img")" "$(json_str "$(container_label "$container" qcr.layout)")" \
|
|
201
|
+
"$(json_str "$(container_label "$container" qcr.build-sha)")" \
|
|
202
|
+
"$(json_str "$(container_label "$container" qcr.runspec)")" \
|
|
203
|
+
"$(json_str "$(container_label "$container" qcr.preflight)")" \
|
|
204
|
+
"$(json_str "$(container_label "$container" qcr.pi)")"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
cmd_status() {
|
|
208
|
+
local json="$1"
|
|
209
|
+
load_conf
|
|
210
|
+
local layout draining rounds last="null" fpfile
|
|
211
|
+
layout="$(detect_layout)"
|
|
212
|
+
draining="$(status_value draining)"
|
|
213
|
+
rounds="$(status_value running_rounds)"
|
|
214
|
+
fpfile="${C[UPDATE_STATE_DIR]}/last-run.json"
|
|
215
|
+
[[ -s "$fpfile" ]] && last="$(cat "$fpfile")"
|
|
216
|
+
if [[ "$json" -eq 1 ]]; then
|
|
217
|
+
printf '{"layout":%s,"daemon":%s,"memory":%s,"runspec":{"version":%s,"fingerprint":%s},"drain":{"draining":%s,"running_rounds":%s},"last_run":%s}\n' \
|
|
218
|
+
"$(json_str "$layout")" "$(image_block "${C[DAEMON_CONTAINER]}")" "$(image_block "${C[MEMORY_CONTAINER]}")" \
|
|
219
|
+
"$(json_str "${C[RUNSPEC_VERSION]}")" "$(json_str "${C[RUNSPEC_FINGERPRINT]}")" \
|
|
220
|
+
"$(json_bool_or_null "$draining")" "$(json_num_or_null "$rounds")" "$last"
|
|
221
|
+
else
|
|
222
|
+
echo "layout $layout"
|
|
223
|
+
echo "runspec v${C[RUNSPEC_VERSION]} ${C[RUNSPEC_FINGERPRINT]}"
|
|
224
|
+
echo "drain draining=${draining:-unknown} running_rounds=${rounds:-unknown}"
|
|
225
|
+
echo "daemon $(image_block "${C[DAEMON_CONTAINER]}")"
|
|
226
|
+
echo "memory $(image_block "${C[MEMORY_CONTAINER]}")"
|
|
227
|
+
echo "last run $last"
|
|
228
|
+
fi
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
# ---- arguments --------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
VERSION=""
|
|
234
|
+
DAEMON_DIGEST=""
|
|
235
|
+
MEMORY_DIGEST=""
|
|
236
|
+
ACK=""
|
|
237
|
+
|
|
238
|
+
usage() {
|
|
239
|
+
echo "usage: $SELF <version>@<sha256:daemon-index-digest> --memory-digest <sha256:...> [--cutover-ack <version>] < config.tar" >&2
|
|
240
|
+
echo " $SELF status [--json]" >&2
|
|
241
|
+
exit 2
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
VERSION_RE='^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$'
|
|
245
|
+
DIGEST_RE='^sha256:[0-9a-f]{64}$'
|
|
246
|
+
|
|
247
|
+
if [[ "${1:-}" == status ]]; then
|
|
248
|
+
shift
|
|
249
|
+
json=0
|
|
250
|
+
[[ "${1:-}" == --json ]] && { json=1; shift; }
|
|
251
|
+
[[ $# -eq 0 ]] || usage
|
|
252
|
+
cmd_status "$json"
|
|
253
|
+
exit 0
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
[[ $# -ge 1 ]] || usage
|
|
257
|
+
if [[ "$1" =~ ^([^@]+)@(.+)$ ]]; then
|
|
258
|
+
VERSION="${BASH_REMATCH[1]}"
|
|
259
|
+
DAEMON_DIGEST="${BASH_REMATCH[2]}"
|
|
260
|
+
else
|
|
261
|
+
usage
|
|
262
|
+
fi
|
|
263
|
+
shift
|
|
264
|
+
while [[ $# -gt 0 ]]; do
|
|
265
|
+
case "$1" in
|
|
266
|
+
--memory-digest) [[ $# -ge 2 ]] || usage; MEMORY_DIGEST="$2"; shift ;;
|
|
267
|
+
--cutover-ack) [[ $# -ge 2 ]] || usage; ACK="$2"; shift ;;
|
|
268
|
+
*) usage ;;
|
|
269
|
+
esac
|
|
270
|
+
shift
|
|
271
|
+
done
|
|
272
|
+
[[ "$VERSION" =~ $VERSION_RE ]] || die "'$VERSION' is not a version (X.Y.Z); there is no latest tag"
|
|
273
|
+
[[ "$DAEMON_DIGEST" =~ $DIGEST_RE ]] || die "the daemon digest must be sha256:<64 hex> (got '$DAEMON_DIGEST')"
|
|
274
|
+
[[ "$MEMORY_DIGEST" =~ $DIGEST_RE ]] || die "--memory-digest sha256:<64 hex> is required (got '${MEMORY_DIGEST:-nothing}')"
|
|
275
|
+
|
|
276
|
+
load_conf
|
|
277
|
+
|
|
278
|
+
# ---- state of this run -----------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
TS="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
281
|
+
mkdir -p "${C[UPDATE_STATE_DIR]}"
|
|
282
|
+
LOG_FILE="${C[UPDATE_STATE_DIR]}/update.log"
|
|
283
|
+
STEP="start"
|
|
284
|
+
PHASE=init # init -> rescuable (the stop) -> committed (the recreate)
|
|
285
|
+
WORK="$(mktemp -d "${TMPDIR:-/tmp}/qcr-update.XXXXXX")"
|
|
286
|
+
ROOT="${C[SANDBOX_ROOT]}"
|
|
287
|
+
CFG="$ROOT/config-home"
|
|
288
|
+
UID_GID="${C[CONTAINER_UID]}:${C[CONTAINER_UID]}"
|
|
289
|
+
DAEMON="${C[DAEMON_CONTAINER]}"
|
|
290
|
+
MEM="${C[MEMORY_CONTAINER]}"
|
|
291
|
+
DAEMON_REF="${C[DAEMON_IMAGE_REPO]}@$DAEMON_DIGEST"
|
|
292
|
+
MEMORY_REF="${C[MEMORY_IMAGE_REPO]}@$MEMORY_DIGEST"
|
|
293
|
+
# 0: untouched; 1: config-home moved to .prev; 2: .next is config-home
|
|
294
|
+
SWAP_STATE=0
|
|
295
|
+
LOCKED=0
|
|
296
|
+
OLD_DAEMON_RENAMED=0
|
|
297
|
+
OLD_MEM_RENAMED=0
|
|
298
|
+
OLD_MEM_STOPPED=0
|
|
299
|
+
NEW_MEM_STARTED=0
|
|
300
|
+
SEEDED=0
|
|
301
|
+
RESCUE_OK=1
|
|
302
|
+
SWAP_MARKER="${C[UPDATE_STATE_DIR]}/swap-pending"
|
|
303
|
+
# the SQLite files the snapshot and the preflight scratch copy both carry
|
|
304
|
+
STATE_DB_FILES=(state.db state.db-wal state.db-shm)
|
|
305
|
+
NEW_DAEMON_STARTED=0
|
|
306
|
+
DAEMON_STOPPED=0
|
|
307
|
+
LAYOUT=none
|
|
308
|
+
CONFIG_PATH_IN_CONTAINER="/opt/quickreview/config-home/config.toml"
|
|
309
|
+
|
|
310
|
+
step() {
|
|
311
|
+
STEP="$1"
|
|
312
|
+
log "step: $1"
|
|
313
|
+
[[ -z "$FAIL_AT" || "$FAIL_AT" != "$1" ]] || die "injected failure at step '$1' (test seam)"
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
record_last_run() {
|
|
317
|
+
local result="$1" detail="$2"
|
|
318
|
+
printf '{"version":%s,"at":%s,"result":%s,"step":%s,"detail":%s}\n' \
|
|
319
|
+
"$(json_str "$VERSION")" "$(json_str "$TS")" "$(json_str "$result")" "$(json_str "$STEP")" "$(json_str "$detail")" \
|
|
320
|
+
>"${C[UPDATE_STATE_DIR]}/last-run.json" 2>/dev/null || true
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
# ---- the operator channel (drain) -----------------------------------------------------
|
|
324
|
+
|
|
325
|
+
OPERATOR_DIR="$ROOT/sandbox/commands/operator"
|
|
326
|
+
RESULTS_DIR="$ROOT/sandbox/commands/results"
|
|
327
|
+
|
|
328
|
+
# The operator channel's directory, made and sealed by root here, while no
|
|
329
|
+
# container runs: commands/operator, root-owned 0755. The bot holds no
|
|
330
|
+
# capability that lets root inside it create or take over a directory in the
|
|
331
|
+
# daemon's commands/, so the operator's `docker exec -u 0` writes only
|
|
332
|
+
# into this one, which root owns. A symlink in its place is refused, never
|
|
333
|
+
# followed.
|
|
334
|
+
ensure_operator_channel() {
|
|
335
|
+
local parent="$ROOT/sandbox/commands"
|
|
336
|
+
[[ -d "$parent" && ! -L "$parent" ]] || return 0
|
|
337
|
+
[[ ! -L "$OPERATOR_DIR" ]] || die "$OPERATOR_DIR is a symlink — refusing to seal the operator channel through it"
|
|
338
|
+
[[ -e "$OPERATOR_DIR" ]] || mkdir "$OPERATOR_DIR"
|
|
339
|
+
[[ -d "$OPERATOR_DIR" ]] || die "$OPERATOR_DIR is not a directory — cannot seal the operator channel"
|
|
340
|
+
if [[ $TEST_MODE -eq 0 ]]; then
|
|
341
|
+
chown -h 0:0 "$OPERATOR_DIR" && chmod 0755 "$OPERATOR_DIR"
|
|
342
|
+
fi
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
# Write one `drain on` command as root into the sealed operator directory and
|
|
346
|
+
# wait for the daemon's receipt. 0 only when the receipt says draining=true.
|
|
347
|
+
send_drain_on() {
|
|
348
|
+
local name base waited=0 wait_s="${1:-120}" result
|
|
349
|
+
[[ -d "$ROOT/sandbox/commands" ]] || { log "no commands dir at $ROOT/sandbox/commands — cannot send drain on"; return 1; }
|
|
350
|
+
mkdir -p "$OPERATOR_DIR"
|
|
351
|
+
if [[ $TEST_MODE -eq 0 ]]; then
|
|
352
|
+
chown 0:0 "$OPERATOR_DIR" && chmod 0755 "$OPERATOR_DIR"
|
|
353
|
+
fi
|
|
354
|
+
base="$(date -u +%Y-%m-%dT%H-%M-%S-%3NZ)-qcr-update-drain"
|
|
355
|
+
name="$base.json"
|
|
356
|
+
printf '{"command":"drain","on":true}\n' >"$OPERATOR_DIR/.$name.tmp"
|
|
357
|
+
chmod 0644 "$OPERATOR_DIR/.$name.tmp"
|
|
358
|
+
mv "$OPERATOR_DIR/.$name.tmp" "$OPERATOR_DIR/$name"
|
|
359
|
+
result="$RESULTS_DIR/$base.result.json"
|
|
360
|
+
while (( waited <= wait_s )); do
|
|
361
|
+
if [[ -f "$result" ]] && grep -Eq '"ok"[[:space:]]*:[[:space:]]*true' "$result" &&
|
|
362
|
+
grep -Eq '"draining"[[:space:]]*:[[:space:]]*true' "$result"; then
|
|
363
|
+
return 0
|
|
364
|
+
fi
|
|
365
|
+
if [[ -f "$result" ]] && grep -Eq '"ok"[[:space:]]*:[[:space:]]*false' "$result"; then
|
|
366
|
+
log "the daemon refused drain on: $(head -c 300 "$result" | tr -d '\n')"
|
|
367
|
+
return 1
|
|
368
|
+
fi
|
|
369
|
+
sleep "$NAP_S"
|
|
370
|
+
waited=$((waited + POLL_S))
|
|
371
|
+
done
|
|
372
|
+
log "no receipt for drain on within ${wait_s}s"
|
|
373
|
+
return 1
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
# The old container's first reconcile, as status.json shows it: a heartbeat
|
|
377
|
+
# written by this boot (after the container's StartedAt) with the drain lifted,
|
|
378
|
+
# which is what a healthy first reconcile does. The daemon writes `draining`
|
|
379
|
+
# only while draining and omits the key once lifted, so lifted = absent (or false). A boot whose first reconcile
|
|
380
|
+
# fails leaves the drain standing, so the wait also ends at the timeout.
|
|
381
|
+
wait_first_reconcile() {
|
|
382
|
+
local container="$1" wait_s="${2:-300}" waited=0 started written draining
|
|
383
|
+
started="$(d container inspect -f '{{.State.StartedAt}}' "$container" 2>/dev/null | cut -c1-19 || true)"
|
|
384
|
+
while (( waited <= wait_s )); do
|
|
385
|
+
written="$(status_value written_at | cut -c1-19)"
|
|
386
|
+
draining="$(status_value draining)"
|
|
387
|
+
if [[ -n "$started" && -n "$written" && ! "$written" < "$started" && "$draining" != true ]]; then
|
|
388
|
+
log "the old daemon's first reconcile has run (heartbeat $written, drain lifted)"
|
|
389
|
+
return 0
|
|
390
|
+
fi
|
|
391
|
+
sleep "$NAP_S"
|
|
392
|
+
waited=$((waited + POLL_S))
|
|
393
|
+
done
|
|
394
|
+
log "no first reconcile from the old daemon within ${wait_s}s (the drain may be standing already)"
|
|
395
|
+
return 0
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
# ---- rescue ---------------------------------------------------------------------------
|
|
399
|
+
|
|
400
|
+
rescue() {
|
|
401
|
+
set +e
|
|
402
|
+
trap - ERR
|
|
403
|
+
log "RESCUE after failure at step '$STEP': restoring the previous config and the old containers"
|
|
404
|
+
local ok=1
|
|
405
|
+
[[ $SWAP_STATE -ge 1 ]] || rm -f "$SWAP_MARKER"
|
|
406
|
+
if [[ $SWAP_STATE -ge 1 ]]; then
|
|
407
|
+
# the new config is set aside as .failed, the previous one is current again
|
|
408
|
+
rm -rf "$CFG.failed"
|
|
409
|
+
if [[ -e "$CFG" ]]; then mv "$CFG" "$CFG.failed" || ok=0; fi
|
|
410
|
+
if mv "$CFG.prev" "$CFG"; then rm -f "$SWAP_MARKER"; else log "RESCUE: could not restore $CFG.prev"; ok=0; fi
|
|
411
|
+
fi
|
|
412
|
+
if [[ $NEW_MEM_STARTED -eq 1 || $OLD_MEM_RENAMED -eq 1 ]]; then
|
|
413
|
+
d rm -f "$MEM" >/dev/null 2>&1
|
|
414
|
+
if [[ $OLD_MEM_RENAMED -eq 1 ]]; then
|
|
415
|
+
d rename "$MEM-prev" "$MEM" >/dev/null 2>&1 || { log "RESCUE: could not put the old sidecar back"; ok=0; }
|
|
416
|
+
fi
|
|
417
|
+
fi
|
|
418
|
+
if [[ $OLD_MEM_STOPPED -eq 1 ]]; then
|
|
419
|
+
d start "$MEM" >/dev/null 2>&1 || { log "RESCUE: the old sidecar did not start"; ok=0; }
|
|
420
|
+
fi
|
|
421
|
+
if [[ $SEEDED -eq 1 ]]; then
|
|
422
|
+
# The legacy daemon owns its store again, so the copy this run seeded goes stale from
|
|
423
|
+
# here on: it is set aside (never deleted) and the next run seeds afresh.
|
|
424
|
+
local aside="${C[MEMORY_STATE_DIR]}.rescued-$TS"
|
|
425
|
+
if mv "${C[MEMORY_STATE_DIR]}" "$aside"; then
|
|
426
|
+
log "RESCUE: the sidecar store this run seeded is set aside at $aside; the next run seeds afresh"
|
|
427
|
+
else
|
|
428
|
+
log "RESCUE: could not set aside ${C[MEMORY_STATE_DIR]}: move it away before the next run, or it boots a stale store"
|
|
429
|
+
ok=0
|
|
430
|
+
fi
|
|
431
|
+
fi
|
|
432
|
+
if [[ $NEW_DAEMON_STARTED -eq 1 || $OLD_DAEMON_RENAMED -eq 1 ]]; then
|
|
433
|
+
d rm -f "$DAEMON" >/dev/null 2>&1
|
|
434
|
+
if [[ $OLD_DAEMON_RENAMED -eq 1 ]]; then
|
|
435
|
+
d rename "$DAEMON-prev" "$DAEMON" >/dev/null 2>&1 || { log "RESCUE: could not put the old daemon container back"; ok=0; }
|
|
436
|
+
fi
|
|
437
|
+
fi
|
|
438
|
+
if [[ $DAEMON_STOPPED -eq 1 && "$LAYOUT" != none ]]; then
|
|
439
|
+
d start "$DAEMON" >/dev/null 2>&1 || { log "RESCUE: the old daemon container did not start"; ok=0; }
|
|
440
|
+
wait_first_reconcile "$DAEMON" "$RESCUE_WAIT_S"
|
|
441
|
+
if send_drain_on "$DRAIN_WAIT_S"; then
|
|
442
|
+
log "RESCUE: drain on confirmed. Rounds may be running (held wakes started after the auto-lift): retry once running_rounds is 0"
|
|
443
|
+
else
|
|
444
|
+
log "RESCUE: COULD NOT CONFIRM drain on — drain by hand (qcr drain on) before anything else"
|
|
445
|
+
ok=0
|
|
446
|
+
fi
|
|
447
|
+
fi
|
|
448
|
+
RESCUE_OK=$ok
|
|
449
|
+
[[ $ok -eq 1 ]] && log "RESCUE complete: the previous version is running again" || log "RESCUE INCOMPLETE — look at the VM"
|
|
450
|
+
return 0
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
# Only the run that holds the lock may touch the staging directory.
|
|
454
|
+
cleanup() {
|
|
455
|
+
rm -rf "$WORK"
|
|
456
|
+
[[ $LOCKED -ne 1 ]] || rm -rf "$CFG.next"
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
on_exit() {
|
|
460
|
+
local rc=$?
|
|
461
|
+
trap - EXIT
|
|
462
|
+
if [[ $rc -ne 0 ]]; then
|
|
463
|
+
if [[ "$PHASE" == rescuable ]]; then
|
|
464
|
+
rescue
|
|
465
|
+
if [[ $RESCUE_OK -eq 1 ]]; then
|
|
466
|
+
record_last_run "rescued" "failed at $STEP; previous version restored"
|
|
467
|
+
else
|
|
468
|
+
record_last_run "rescue-incomplete" "failed at $STEP; the rescue did not complete, look at the VM"
|
|
469
|
+
fi
|
|
470
|
+
elif [[ "$PHASE" == committed ]]; then
|
|
471
|
+
log "FAILED at step '$STEP' AFTER the recreate: the drain stays on (a failed first reconcile never lifts it); fix forward"
|
|
472
|
+
record_last_run "failed-forward" "failed at $STEP after the recreate"
|
|
473
|
+
else
|
|
474
|
+
log "FAILED at step '$STEP' — nothing was changed on the VM"
|
|
475
|
+
record_last_run "refused" "failed at $STEP before the stop"
|
|
476
|
+
fi
|
|
477
|
+
cleanup
|
|
478
|
+
log "exit $rc: step '$STEP'"
|
|
479
|
+
exit "$rc"
|
|
480
|
+
fi
|
|
481
|
+
cleanup
|
|
482
|
+
}
|
|
483
|
+
trap on_exit EXIT
|
|
484
|
+
trap 'exit 1' ERR
|
|
485
|
+
|
|
486
|
+
# ---- 1. the lock ------------------------------------------------------------------------
|
|
487
|
+
|
|
488
|
+
step lock
|
|
489
|
+
exec 9>"${C[UPDATE_STATE_DIR]}/update.lock"
|
|
490
|
+
flock -n 9 || die "another qcr-update is running (lock ${C[UPDATE_STATE_DIR]}/update.lock)"
|
|
491
|
+
LOCKED=1
|
|
492
|
+
[[ ! -e "$SWAP_MARKER" ]] ||
|
|
493
|
+
die "a previous qcr-update was interrupted between the config swap and the recreate ($SWAP_MARKER): $CFG.prev holds the config the running daemon was started on. Put it back by hand (mv $CFG $CFG.failed; mv $CFG.prev $CFG), remove the marker, then retry"
|
|
494
|
+
|
|
495
|
+
# The config tar, spooled first so a refusal below needs no stdin.
|
|
496
|
+
step read-config
|
|
497
|
+
cat >"$WORK/config.tar"
|
|
498
|
+
[[ -s "$WORK/config.tar" ]] || die "no config tar on stdin (config.toml and profiles/)"
|
|
499
|
+
|
|
500
|
+
# ---- 2. the drain --------------------------------------------------------------------------
|
|
501
|
+
|
|
502
|
+
step drain
|
|
503
|
+
# A first install has nothing to drain: no daemon container, no heartbeat, no
|
|
504
|
+
# state database. Anything less than all three is an existing install (a lost
|
|
505
|
+
# container over live state), and keeps the drain requirement.
|
|
506
|
+
FRESH=0
|
|
507
|
+
if [[ "$(detect_layout)" == none && ! -e "$(STATUS_JSON)" && ! -e "${C[SANDBOX_ROOT]}/state/state.db" ]]; then
|
|
508
|
+
FRESH=1
|
|
509
|
+
log "fresh install: no daemon container, heartbeat or state database; nothing to drain or snapshot"
|
|
510
|
+
fi
|
|
511
|
+
draining="$(status_value draining)"
|
|
512
|
+
rounds="$(status_value running_rounds)"
|
|
513
|
+
[[ $FRESH -eq 1 ]] || [[ "$draining" == true ]] || die "refusing: the bot is not drained (draining=${draining:-unreadable}). Run \`qcr drain on\`, wait for running_rounds 0, retry"
|
|
514
|
+
[[ $FRESH -eq 1 ]] || [[ "$rounds" =~ ^[0-9]+$ ]] || die "refusing: running_rounds is unreadable in status.json"
|
|
515
|
+
[[ $FRESH -eq 1 ]] || [[ "$rounds" -eq 0 ]] || die "refusing: $rounds round(s) still running. Wait for running_rounds 0, retry"
|
|
516
|
+
|
|
517
|
+
# ---- 3. the layout ------------------------------------------------------------------------------
|
|
518
|
+
|
|
519
|
+
step layout
|
|
520
|
+
LAYOUT="$(detect_layout)"
|
|
521
|
+
log "layout: $LAYOUT"
|
|
522
|
+
# No container of this name, yet a running container writes this state: the run
|
|
523
|
+
# spec names the wrong daemon, and a second daemon would share its state.db.
|
|
524
|
+
if [[ "$LAYOUT" == none && $FRESH -eq 0 ]]; then
|
|
525
|
+
for id in $(d ps -q); do
|
|
526
|
+
if d container inspect -f '{{range .Mounts}}{{.Source}} {{end}}' "$id" 2>/dev/null | tr ' ' '\n' | grep -qx "${C[SANDBOX_ROOT]}/state"; then
|
|
527
|
+
die "refusing: no container ${C[DAEMON_CONTAINER]}, but the running container $(d container inspect -f '{{.Name}}' "$id" | tr -d /) mounts ${C[SANDBOX_ROOT]}/state. The run spec names the wrong daemon: set image_name (and memory_container_name) to the containers this host runs, then provision again"
|
|
528
|
+
fi
|
|
529
|
+
done
|
|
530
|
+
fi
|
|
531
|
+
if [[ "$LAYOUT" == legacy && "$ACK" != "$VERSION" ]]; then
|
|
532
|
+
die "refusing: the VM still runs the legacy layout, so this deploy is the cutover (the first boot migrates forward). Re-run with --cutover-ack $VERSION"
|
|
533
|
+
fi
|
|
534
|
+
|
|
535
|
+
# ---- 4. pull both images by digest, check them ----------------------------------------------------------
|
|
536
|
+
|
|
537
|
+
step pull
|
|
538
|
+
d pull "$DAEMON_REF" >/dev/null || die "could not pull $DAEMON_REF (is the VM logged in to ghcr.io? scripts/vm-ghcr-login.sh)"
|
|
539
|
+
d pull "$MEMORY_REF" >/dev/null || die "could not pull $MEMORY_REF"
|
|
540
|
+
|
|
541
|
+
step check-images
|
|
542
|
+
check_digest() {
|
|
543
|
+
local ref="$1" digest="$2" digests
|
|
544
|
+
digests="$(d image inspect -f '{{range .RepoDigests}}{{.}} {{end}}' "$ref" 2>/dev/null || true)"
|
|
545
|
+
[[ "$digests" == *"@$digest"* ]] || die "the pulled image $ref does not carry the digest $digest (RepoDigests: ${digests:-none})"
|
|
546
|
+
}
|
|
547
|
+
check_digest "$DAEMON_REF" "$DAEMON_DIGEST"
|
|
548
|
+
check_digest "$MEMORY_REF" "$MEMORY_DIGEST"
|
|
549
|
+
[[ "$(image_label "$DAEMON_REF" qcr.layout)" == release ]] || die "$DAEMON_REF is not a release-layout image (no qcr.layout=release label)"
|
|
550
|
+
sha_label="$(image_label "$DAEMON_REF" qcr.build-sha)"
|
|
551
|
+
[[ -n "$sha_label" && "$sha_label" != unstamped ]] || die "$DAEMON_REF carries no CI build stamp (qcr.build-sha)"
|
|
552
|
+
[[ "$(image_label "$DAEMON_REF" qcr.preflight)" == true ]] ||
|
|
553
|
+
die "$DAEMON_REF has no qcr.preflight label: the required \`daemon --preflight\` step cannot run, so the image is refused"
|
|
554
|
+
|
|
555
|
+
step runspec
|
|
556
|
+
image_runspec="$(image_label "$DAEMON_REF" qcr.runspec)"
|
|
557
|
+
[[ "$image_runspec" =~ ^[0-9]+$ ]] || die "$DAEMON_REF has no numeric qcr.runspec label"
|
|
558
|
+
if [[ "$image_runspec" -gt "${C[RUNSPEC_VERSION]}" ]]; then
|
|
559
|
+
die "refusing: the image needs run spec v$image_runspec but $CONF is v${C[RUNSPEC_VERSION]} — re-run provision"
|
|
560
|
+
fi
|
|
561
|
+
# The gate group of the image's setid helper (docker/Dockerfile): the
|
|
562
|
+
# bot is given it, and the helper is what runs the model's tools as TOOL_UID. An
|
|
563
|
+
# image from before the helper (run spec v1) has no label and needs no group.
|
|
564
|
+
SETID_GID="$(image_label "$DAEMON_REF" qcr.setid-gid)"
|
|
565
|
+
if [[ "$image_runspec" -ge 2 || -n "$SETID_GID" ]]; then
|
|
566
|
+
[[ "$SETID_GID" =~ ^[1-9][0-9]*$ ]] || die "$DAEMON_REF needs run spec v$image_runspec but has no numeric qcr.setid-gid label"
|
|
567
|
+
[[ "$SETID_GID" != "${C[CONTAINER_UID]}" ]] || die "$DAEMON_REF's setid gate group $SETID_GID is the container uid's own group"
|
|
568
|
+
fi
|
|
569
|
+
[[ "${C[TOOL_UID]}" =~ ^[1-9][0-9]*$ && "${C[TOOL_UID]}" != "${C[CONTAINER_UID]}" ]] ||
|
|
570
|
+
die "$CONF TOOL_UID (${C[TOOL_UID]}) must be a non-zero uid other than CONTAINER_UID — re-run provision"
|
|
571
|
+
[[ "${C[TOOL_GID]}" =~ ^[1-9][0-9]*$ && "${C[TOOL_GID]}" != "${C[CONTAINER_UID]}" ]] ||
|
|
572
|
+
die "$CONF TOOL_GID (${C[TOOL_GID]}) must be a non-zero gid other than the container's — re-run provision"
|
|
573
|
+
# The helper switches to the identity compiled into the image and nothing else
|
|
574
|
+
# (docker/setid/qcr-setid.c): the run spec must name that same identity.
|
|
575
|
+
if [[ -n "$SETID_GID" ]]; then
|
|
576
|
+
for k in uid gid; do
|
|
577
|
+
want="$(image_label "$DAEMON_REF" "qcr.tool-$k")"
|
|
578
|
+
have="${C[TOOL_${k^^}]}"
|
|
579
|
+
[[ "$want" == "$have" ]] ||
|
|
580
|
+
die "$DAEMON_REF runs the model's tools as tool $k ${want:-?}, but $CONF says TOOL_${k^^}=$have — re-run provision"
|
|
581
|
+
done
|
|
582
|
+
fi
|
|
583
|
+
|
|
584
|
+
# ---- 5. stage the config and check it with the NEW image ---------------------------------------------------
|
|
585
|
+
|
|
586
|
+
step stage-config
|
|
587
|
+
# Names only: no secrets/, no absolute or `..` paths, no links, nothing but
|
|
588
|
+
# config.toml and profiles/.
|
|
589
|
+
bad=""
|
|
590
|
+
while IFS= read -r entry; do
|
|
591
|
+
e="${entry#./}"
|
|
592
|
+
e="${e%/}"
|
|
593
|
+
[[ -z "$e" || "$e" == . ]] && continue
|
|
594
|
+
top="${e%%/*}"
|
|
595
|
+
if [[ "$e" == /* || "$e" == *..* ]]; then bad="$entry (absolute or parent path)"; break; fi
|
|
596
|
+
if [[ "$top" == secrets ]]; then bad="$entry (secrets/ never rides the config tar — secrets stay with provision)"; break; fi
|
|
597
|
+
if [[ "$top" != config.toml && "$top" != profiles ]]; then bad="$entry (only config.toml and profiles/ are accepted)"; break; fi
|
|
598
|
+
if [[ "$top" == config.toml && "$e" != config.toml ]]; then bad="$entry"; break; fi
|
|
599
|
+
done < <(tar -tf "$WORK/config.tar")
|
|
600
|
+
[[ -z "$bad" ]] || die "refusing the config tar: $bad"
|
|
601
|
+
if tar -tvf "$WORK/config.tar" | grep -Eq '^[lh]'; then
|
|
602
|
+
die "refusing the config tar: it holds a link (the controller ships profiles dereferenced)"
|
|
603
|
+
fi
|
|
604
|
+
rm -rf "$CFG.next"
|
|
605
|
+
mkdir -p "$CFG.next"
|
|
606
|
+
tar -xf "$WORK/config.tar" --no-same-owner --no-same-permissions -C "$CFG.next"
|
|
607
|
+
[[ -f "$CFG.next/config.toml" ]] || die "the config tar holds no config.toml"
|
|
608
|
+
chmod -R u+rwX,go+rX,go-w "$CFG.next"
|
|
609
|
+
if [[ $TEST_MODE -eq 0 ]]; then chown -R "$UID_GID" "$CFG.next"; fi
|
|
610
|
+
|
|
611
|
+
step config-check
|
|
612
|
+
check_out="$WORK/config-check.json"
|
|
613
|
+
if ! d run --rm --network none --user "$UID_GID" -v "$CFG.next:/cfg:ro" "$DAEMON_REF" config check --json --config-home /cfg >"$check_out" 2>"$WORK/config-check.err"; then
|
|
614
|
+
log "$(head -c 2000 "$check_out" | tr '\n' ' ')"
|
|
615
|
+
log "$(head -c 500 "$WORK/config-check.err" | tr '\n' ' ')"
|
|
616
|
+
die "refusing: the new image's \`qcr config check\` fails on this config home. Nothing was changed"
|
|
617
|
+
fi
|
|
618
|
+
|
|
619
|
+
# The network is a precondition that changes nothing running.
|
|
620
|
+
if ! d network inspect "${C[MEMORY_NETWORK]}" >/dev/null 2>&1; then
|
|
621
|
+
d network create "${C[MEMORY_NETWORK]}" >/dev/null
|
|
622
|
+
fi
|
|
623
|
+
|
|
624
|
+
# ---- 6. from here a failure is rescued ----------------------------------------------------------------------------
|
|
625
|
+
|
|
626
|
+
BACKUP="${C[BACKUP_DIR]}/$VERSION-$TS"
|
|
627
|
+
STATE="$ROOT/state"
|
|
628
|
+
|
|
629
|
+
PHASE=rescuable
|
|
630
|
+
# Marked before the stop, so a stop that fails half way is rescued like any
|
|
631
|
+
# other step: the old container is started (a no-op if it runs) and re-drained.
|
|
632
|
+
[[ "$LAYOUT" == none ]] || DAEMON_STOPPED=1
|
|
633
|
+
step stop
|
|
634
|
+
if [[ "$LAYOUT" != none ]]; then
|
|
635
|
+
d stop -t 90 "$DAEMON" >/dev/null
|
|
636
|
+
fi
|
|
637
|
+
|
|
638
|
+
step snapshot
|
|
639
|
+
mkdir -p "$BACKUP"
|
|
640
|
+
chmod 0700 "${C[BACKUP_DIR]}" "$BACKUP"
|
|
641
|
+
[[ $FRESH -eq 1 || -f "$STATE/state.db" ]] || die "no $STATE/state.db to snapshot"
|
|
642
|
+
for f in "${STATE_DB_FILES[@]}"; do
|
|
643
|
+
[[ -f "$STATE/$f" ]] && cp -p "$STATE/$f" "$BACKUP/$f"
|
|
644
|
+
done
|
|
645
|
+
if [[ -d "$STATE/pi-sessions" ]]; then
|
|
646
|
+
tar -C "$STATE" -czf "$BACKUP/pi-sessions.tar.gz" pi-sessions
|
|
647
|
+
fi
|
|
648
|
+
chmod 0600 "$BACKUP"/* 2>/dev/null || true
|
|
649
|
+
log "snapshot in $BACKUP"
|
|
650
|
+
|
|
651
|
+
step preflight
|
|
652
|
+
# The scratch copy: the snapshot's db files and the sessions, owned by the
|
|
653
|
+
# container uid, mounted as the app's state dir. --network none: the preflight
|
|
654
|
+
# reads, it reaches nothing. `daemon --preflight` is the image's own check
|
|
655
|
+
#: migrate the scratch db forward, resume the live JSONLs offline.
|
|
656
|
+
SCRATCH="$WORK/preflight-state"
|
|
657
|
+
mkdir -p "$SCRATCH"
|
|
658
|
+
for f in "${STATE_DB_FILES[@]}"; do
|
|
659
|
+
[[ -f "$BACKUP/$f" ]] && cp -p "$BACKUP/$f" "$SCRATCH/$f"
|
|
660
|
+
done
|
|
661
|
+
[[ -f "$BACKUP/pi-sessions.tar.gz" ]] && tar -xzf "$BACKUP/pi-sessions.tar.gz" -C "$SCRATCH"
|
|
662
|
+
if [[ $TEST_MODE -eq 0 ]]; then chown -R "$UID_GID" "$SCRATCH"; fi
|
|
663
|
+
chmod -R go+rX "$SCRATCH"
|
|
664
|
+
d run --rm --network none --user "$UID_GID" \
|
|
665
|
+
-e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER" \
|
|
666
|
+
-v "$SCRATCH:${C[APP_ROOT]}/state" -v "$CFG.next:/opt/quickreview/config-home:ro" \
|
|
667
|
+
-v "$ROOT/pihome:/home/qcr/.pi:ro" \
|
|
668
|
+
"$DAEMON_REF" daemon --preflight >"$WORK/preflight.out" 2>&1 ||
|
|
669
|
+
{ tail -n 20 "$WORK/preflight.out" >&2 || true; die "the new image's \`daemon --preflight\` failed on a scratch copy of the snapshot"; }
|
|
670
|
+
rm -rf "$SCRATCH"
|
|
671
|
+
|
|
672
|
+
step seed
|
|
673
|
+
if [[ "$LAYOUT" == legacy ]]; then
|
|
674
|
+
marker="${C[MEMORY_STATE_DIR]}/.seeded-from-daemon"
|
|
675
|
+
if [[ ! -e "$marker" ]]; then
|
|
676
|
+
mkdir -p "${C[MEMORY_STATE_DIR]}" "${C[OPENVIKING_HOME]}"
|
|
677
|
+
chmod 0700 "${C[MEMORY_STATE_DIR]}"
|
|
678
|
+
if [[ $TEST_MODE -eq 0 ]]; then chown "$UID_GID" "${C[MEMORY_STATE_DIR]}"; fi
|
|
679
|
+
# a copy that fails part way is already a stale partial store: marked before the
|
|
680
|
+
# copy, so the rescue sets it aside and the retry seeds from an empty directory
|
|
681
|
+
SEEDED=1
|
|
682
|
+
# additive: no --delete, nothing on either side is removed
|
|
683
|
+
rsync -a "${C[OPENVIKING_HOME]}/" "${C[MEMORY_STATE_DIR]}/"
|
|
684
|
+
diff_out="$(rsync -a --checksum --dry-run --itemize-changes "${C[OPENVIKING_HOME]}/" "${C[MEMORY_STATE_DIR]}/")"
|
|
685
|
+
[[ -z "$diff_out" ]] || die "the sidecar store copy does not verify by checksum: ${diff_out:0:200}"
|
|
686
|
+
printf 'seeded from %s on %s\n' "${C[OPENVIKING_HOME]}" "$TS" >"$marker"
|
|
687
|
+
chmod 0600 "$marker"
|
|
688
|
+
if [[ $TEST_MODE -eq 0 ]]; then chown "$UID_GID" "$marker"; fi
|
|
689
|
+
log "sidecar store seeded from ${C[OPENVIKING_HOME]} (copy verified; the old store is untouched)"
|
|
690
|
+
else
|
|
691
|
+
log "sidecar store already seeded"
|
|
692
|
+
fi
|
|
693
|
+
fi
|
|
694
|
+
|
|
695
|
+
step swap
|
|
696
|
+
rm -rf "$CFG.prev"
|
|
697
|
+
printf '%s\n' "$TS" >"$SWAP_MARKER"
|
|
698
|
+
if [[ -d "$CFG" ]]; then mv "$CFG" "$CFG.prev"; else mkdir -p "$CFG.prev"; fi
|
|
699
|
+
SWAP_STATE=1
|
|
700
|
+
mv "$CFG.next" "$CFG"
|
|
701
|
+
SWAP_STATE=2
|
|
702
|
+
|
|
703
|
+
step sidecar-start
|
|
704
|
+
mem_args=(
|
|
705
|
+
run -d --name "$MEM" --restart unless-stopped --init
|
|
706
|
+
--user "$UID_GID"
|
|
707
|
+
--cpus "${C[MEMORY_CPUS]}" --memory "${C[MEMORY_MEMORY]}" --memory-swap "${C[MEMORY_MEMORY]}"
|
|
708
|
+
--network "${C[MEMORY_NETWORK]}"
|
|
709
|
+
# no published port: OpenViking answers on the container network only
|
|
710
|
+
-v "${C[MEMORY_STATE_DIR]}:${C[OPENVIKING_HOME]}"
|
|
711
|
+
-v "$ROOT/secrets:/opt/quickreview/secrets:ro"
|
|
712
|
+
-v "$ROOT/config-home:/opt/quickreview/config-home:ro"
|
|
713
|
+
-e "TZ=${C[TZ]}" -e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER"
|
|
714
|
+
)
|
|
715
|
+
for key in "${!C[@]}"; do
|
|
716
|
+
[[ "$key" == SIDECAR_ENV_* ]] && mem_args+=(-e "${key#SIDECAR_ENV_}=${C[$key]}")
|
|
717
|
+
done
|
|
718
|
+
mem_args+=("$MEMORY_REF")
|
|
719
|
+
if container_exists "$MEM"; then
|
|
720
|
+
# one writer on the store: the old sidecar stops before the new one starts
|
|
721
|
+
if container_running "$MEM"; then OLD_MEM_STOPPED=1; d stop -t 90 "$MEM" >/dev/null; fi
|
|
722
|
+
d rm -f "$MEM-prev" >/dev/null 2>&1 || true
|
|
723
|
+
d rename "$MEM" "$MEM-prev"
|
|
724
|
+
OLD_MEM_RENAMED=1
|
|
725
|
+
fi
|
|
726
|
+
NEW_MEM_STARTED=1
|
|
727
|
+
d "${mem_args[@]}" >/dev/null
|
|
728
|
+
|
|
729
|
+
step sidecar-ready
|
|
730
|
+
ready_wait="${READY_WAIT_S:-${C[MEMORY_READY_TIMEOUT_S]:-1800}}"
|
|
731
|
+
waited=0
|
|
732
|
+
until d exec "$MEM" curl -fsS "http://127.0.0.1:${C[OPENVIKING_PORT]}/ready" >/dev/null 2>&1; do
|
|
733
|
+
(( waited < ready_wait )) || die "the memory sidecar was not ready within ${ready_wait}s (a re-embed is a boot; read: docker logs --tail 100 $MEM)"
|
|
734
|
+
sleep "$NAP_S"
|
|
735
|
+
waited=$((waited + POLL_S))
|
|
736
|
+
done
|
|
737
|
+
log "memory sidecar ready after ${waited}s"
|
|
738
|
+
|
|
739
|
+
step recreate
|
|
740
|
+
daemon_args=(
|
|
741
|
+
run -d --name "$DAEMON" --restart unless-stopped --init
|
|
742
|
+
--cpus "${C[DAEMON_CPUS]}" --memory "${C[DAEMON_MEMORY]}" --memory-swap "${C[DAEMON_MEMORY]}"
|
|
743
|
+
--user "$UID_GID"
|
|
744
|
+
# the model's tools run as TOOL_UID:TOOL_GID (QCR_TOOLS_AS), which cannot
|
|
745
|
+
# read secrets/ or pi's login; the bot reaches it through the image's setid
|
|
746
|
+
# helper, which switches to that one identity only, given by the --group-add
|
|
747
|
+
# below. The bot stays this uid, so a `docker exec` lands as it. No
|
|
748
|
+
# capability beyond SETUID/SETGID, the helper's file capabilities: the
|
|
749
|
+
# operator channel's `docker exec -u 0` writes into commands/operator, which
|
|
750
|
+
# is root's own (ensure_operator_channel), and needs none.
|
|
751
|
+
# no-new-privileges stays off: it would void the helper's file capabilities;
|
|
752
|
+
# the model's tools carry no_new_privs of their own.
|
|
753
|
+
--cap-drop ALL --cap-add SETUID --cap-add SETGID
|
|
754
|
+
-e "QCR_TOOLS_AS=${C[TOOL_UID]}"
|
|
755
|
+
-p "127.0.0.1:${C[WEBHOOK_PORT]}:${C[WEBHOOK_PORT]}"
|
|
756
|
+
--network "${C[MEMORY_NETWORK]}"
|
|
757
|
+
-v "$ROOT/state:${C[APP_ROOT]}/state"
|
|
758
|
+
-v "$ROOT/secrets:/opt/quickreview/secrets:ro"
|
|
759
|
+
-v "$ROOT/config-home:/opt/quickreview/config-home:ro"
|
|
760
|
+
-v "$ROOT/pihome:/home/qcr/.pi"
|
|
761
|
+
-v "$ROOT/sandbox/wt:${C[APP_ROOT]}/wt"
|
|
762
|
+
-v "$ROOT/sandbox/archive:${C[APP_ROOT]}/archive"
|
|
763
|
+
-v "$ROOT/sandbox/commands:${C[APP_ROOT]}/commands"
|
|
764
|
+
-v "$ROOT/sandbox/digest:${C[APP_ROOT]}/digest"
|
|
765
|
+
-v "$ROOT/sandbox/inject:${C[APP_ROOT]}/inject"
|
|
766
|
+
-v "$ROOT/sandbox/verdict:${C[APP_ROOT]}/verdict"
|
|
767
|
+
# the sessions' own HOME (<root>/pihome: their ovcli.conf, recall hints, retired
|
|
768
|
+
# list and pinned git config), the directory the legacy container kept beside them
|
|
769
|
+
-v "$ROOT/sandbox/pihome:${C[APP_ROOT]}/pihome"
|
|
770
|
+
-v "$ROOT/sandbox/${C[BASE_CLONE_DIR]}:${C[APP_ROOT]}/${C[BASE_CLONE_DIR]}"
|
|
771
|
+
# path continuity for what the legacy container recorded
|
|
772
|
+
-v "$ROOT/sandbox/wt:${C[LEGACY_SANDBOX_ROOT]}/wt"
|
|
773
|
+
-v "$ROOT/sandbox/${C[BASE_CLONE_DIR]}:${C[LEGACY_SANDBOX_ROOT]}/${C[BASE_CLONE_DIR]}"
|
|
774
|
+
-e "TZ=${C[TZ]}" -e "QC_REVIEW_PORT=${C[WEBHOOK_PORT]}" -e QC_BIND_HOST=0.0.0.0
|
|
775
|
+
-e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER"
|
|
776
|
+
)
|
|
777
|
+
if [[ -n "$SETID_GID" ]]; then
|
|
778
|
+
# the helper's gate group, and the tool gid the shared directories belong to
|
|
779
|
+
daemon_args+=(--group-add "$SETID_GID" --group-add "${C[TOOL_GID]}")
|
|
780
|
+
fi
|
|
781
|
+
if [[ -n "${C[DAEMON_ENV_FILE]:-}" && -f "${C[DAEMON_ENV_FILE]}" ]]; then
|
|
782
|
+
daemon_args+=(--env-file "${C[DAEMON_ENV_FILE]}")
|
|
783
|
+
fi
|
|
784
|
+
daemon_args+=("$DAEMON_REF" daemon)
|
|
785
|
+
if container_exists "$DAEMON"; then
|
|
786
|
+
d rm -f "$DAEMON-prev" >/dev/null 2>&1 || true
|
|
787
|
+
d rename "$DAEMON" "$DAEMON-prev"
|
|
788
|
+
OLD_DAEMON_RENAMED=1
|
|
789
|
+
fi
|
|
790
|
+
ensure_operator_channel
|
|
791
|
+
NEW_DAEMON_STARTED=1
|
|
792
|
+
d "${daemon_args[@]}" >/dev/null
|
|
793
|
+
|
|
794
|
+
# ---- the point of no return ---------------------------------------------------------------------------------------------
|
|
795
|
+
PHASE=committed
|
|
796
|
+
rm -f "$SWAP_MARKER"
|
|
797
|
+
step post-recreate
|
|
798
|
+
d tag "$DAEMON_REF" "${C[DAEMON_IMAGE_REPO]}:$VERSION" >/dev/null 2>&1 || true
|
|
799
|
+
d tag "$MEMORY_REF" "${C[MEMORY_IMAGE_REPO]}:$VERSION" >/dev/null 2>&1 || true
|
|
800
|
+
container_running "$DAEMON" || die "the new daemon container is not running right after the recreate (docker logs --tail 100 $DAEMON)"
|
|
801
|
+
STEP="done"
|
|
802
|
+
record_last_run "ok" "updated to $VERSION ($sha_label); the drain stays on until the first healthy reconcile lifts it"
|
|
803
|
+
log "updated to $VERSION (build $sha_label). The drain stays on: the new boot's first healthy reconcile lifts it (cutover: the owner triggers and checks one worker round first)"
|