Why: Settings plaintext loses to secret_keys, so replacing the env key did not change the key a conversation actually sent.
Evidence: python3 -m unittest tests.test_svc.SvcDbRecoveryTests.test_seed_replaces_old_system_secret tests.test_svc.SvcDbRecoveryTests.test_seed_warns_when_old_secret_stays_active tests.test_svc.SvcDbRecoveryTests.test_seed_puts_without_credentials_when_auth_off (SELF).
Impact: Embedded databases now compare the active system secret fingerprint after seeding, and the backend gitlink carries the adoption fix.
Refs: fix/model-key-secret-overlay
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=692735e91d6a9ab07ddd3686feb60a56b270728a.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: The dev service is an rdm build, so startup skipped model seeding and kept the old MiniMax chat model. Later starts need the saved env file applied even without an admin key command.
Evidence: seed and rdm launcher tests passed. The live dev database now uses the four-model chat route and keeps the original MiniMax endpoint as reserve.
Impact: Restart of a service with envfile set rewrites system model settings. HTTP seeding is unchanged for builds that can mint an admin key. MiniMax is stored separately because fallbacks cannot switch gateways.
Refs: .task/feature-four-model-vision.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: Chat, lightweight, fallback and vision settings need a seed path, and the backend now sends current-turn images only to models declared capable of seeing them.
Evidence: The backend change is cfde38d. The seed test covers fallback and vision settings. A local image conversation on each builtin profile returned the pictured content from the expected model, and removing the chat model from the capable list switched that turn to the vision model.
Impact: New runs can use the four builtin profiles and image input. Secrets stay in the ignored env file. The live 8788 process is unchanged.
Refs: .task/feature-four-model-vision.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: deploy needs to choose registered plugins and ship them inside one agent-system, then refuse the release when they are not active.
Evidence: python3 -m unittest tests.test_svc_plugins tests.test_svc_user_help tests.test_svc tests.test_svc_u2 (SELF, 63 passed, 1 skipped). Real compose build and make test-lifecycle are NOT_RUN.
Impact: --with is mutually exclusive with --from rdm and --from release. Existing non-interactive deploys stay without plugins unless plugins= is already recorded. Changing the plugin id set on a live service requires --allow-source-switch.
Refs: .task/feature-svc-plugin-compose.md modules/documents/docs/proposals/2026-10-14-svc-plugin-compose-deploy.md
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: card_merge only recognized "Merge ... from <branch> into main"
merge commits, so a PR landed as a squash (real case: #457) left its
task card in .task/ forever; task-close reported nothing to close and
precheck showed no debt. Closing required a manual backfill (PR #541).
Evidence: card_merge now returns sha|subject|pr and falls back to a
Gitea API lookup by head ref or label (deleted branches keep the
original name only in label), gated by merge_commit_sha ancestry in
origin/main; precheck [cards] reuses card_merge so both surfaces agree.
Live probe against production Gitea returns 226a4af15791|Reset
per-service runtime state in svc.sh env_config|457 for
feature/svc-pidcheck-leak; stub-server tests cover squash landing,
decoy skip and the not-on-main refusal; full governance suite follows
in-card evidence.
Impact: scripts/task.sh close and precheck detect squash-merged cards
when GITEA_TOKEN is set (merge-commit path unchanged without token);
tests/test_task.py adds two regressions; no protocol change for
existing merge-commit closures beyond the appended pr field.
Refs: card-merge-misses-squash-merges (memory); PR #541 manual closure.
Why: F2 token extraction predates the two-section (HOME/IMC) layout of
~/.secrets/gitea so it concatenated both tokens and always failed; F6
registered a grep BRE alternation that facts-verify unescapes into a
literal pipe, failing re-verification and misaligning precheck's naive
pipe split into a spurious F6 date-format expiry warning, while both
underlying facts still hold.
Evidence: make facts-verify now 6/6 PASS with last_verified refreshed
to 2026-10-14; new regression test for escaped pipes in facts rows;
full governance suite 342 tests OK (18 skipped); precheck [facts] line
reports all facts fresh on the fixed parser.
Impact: policy/facts.md F2 (HOME-section awk extraction) and F6
(negated pipe-free grep); scripts/task.sh precheck neutralizes escaped
pipes the same way facts-verify does; tests/test_task.py covers it.
Refs: precheck WARN 过期事实 F6(日期格式); AGENTS.md 证据与验证门禁.
Why: pipefail treated a recent merged-card match as a failed git log after grep exited early, hiding completed cards from precheck and task-close.
Evidence: A disposable long-history regression failed before the fix and passed after it; make test-governance passed 341 cases. Git history confirms PR #489/#488/#486 merge SHAs.
Impact: Detect merged cards reliably and archive only the three authorized trial cards; four unrelated eligible cards remain untouched.
Refs: Dev merge queue #518; Dev #489, #488, #486
Why: Finish Dev #488 with delivered Frontend and RDM objects, explicit audit grants in private browser fixtures, and owned process cleanup.
Evidence: Tool-imported SELF precheck, final sync, make test, and real-browser runs retain failures and passes; latest isolated runtime completed seven browser cases. Final exact-head GATE and independent parent Review follow.
Impact: Preserves other main components and existing CI jobs while the one final candidate is fixed for formal checks.
Refs: Dev PR #488; Frontend PR #73; RDM PR #301; queue Issue #518
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=f00165e8d71e4dc8ba0ceb7dc50c1a8a3deb6d60.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: A LOCAL_READY receipt must permit normal target advancement without accepting a rewind or divergent target history after its observation.
Evidence: Two disposable real Git regressions reproduced erroneous successful recovery before the guard; all 18 task recovery tests pass afterward. Raw SELF receipts are in the task card.
Impact: Reject abnormal target ancestry before receipt import; preserve normal local recovery and strict delivery defaults. Correct stale implementation-stage documentation without activating the queue.
Refs: Documents implementation plan ba4044d U2; independent review R1 and R2; .task/feature-merge-queue-policy-draft.md
Why: agents need consistent entrypoints and recording defaults to avoid retrying synchronization and CI outside the final delivery window.
Evidence: SELF generated-task-card red-green regression and governance suite recorded through make evidence; pending shared record created as Issue #518.
Impact: rules, task template and capability matrix stay explicit about pending activation, default strict startup, manual coordination and unchanged CI triggers.
Refs: U4; policy/merge-queue.md; .task/feature-merge-queue-policy-draft.md
Why: an existing authorized task should not merge a moving target merely to resume local work, while new task startup and delivery remain strict.
Evidence: SELF red-green recovery and environment regressions; task, recovery, evidence and local-mode write-guard suites passed through make evidence.
Impact: add explicit LOCAL_READY and task-resume, validate worktree/card/baseline and receipt purpose, preserve schema 1 and prevent local receipts from starting or releasing tasks.
Refs: U2; policy/merge-queue.md; .task/feature-merge-queue-policy-draft.md
Why: repeated task-sync calls changed HEAD and invalidated CI even when main had not advanced.
Evidence: SELF red-green regression and 58 task lifecycle tests recorded through make evidence in the task card.
Impact: sync still fetches and validates components, creates records only for an actual merge, and reports the complete final source SHA.
Refs: U1; policy/merge-queue.md; .task/feature-merge-queue-policy-draft.md
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=3fb8210f6495a78e70a67af3661bdfe9c00fb9de.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: A static dev deploy deleted the worktree before copying dist, so a mixed batch could not update the workbench. Missing manifests and a second instance on the same Postgres database must fail closed the same way on real artifacts.
Evidence: SELF unittest of the mixed batch, the three-entry manifest-loss case, and the PG cross-instance case exited 0. The PG case used a temporary cluster.
Impact: static dev deploys copy dist before recycling the worktree. Login and rdm.ping stay NOT_RUN.
Refs: tests/integration/lifecycle/test_lifecycle_real.py
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=5aebedebeb963b5c01f39fd9122ec60dbe6d34d3.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: U7 acceptance bootstrapped u7-admin into the shared dev runtime's
singleton rdm_admins ledger, locking the operator out of RDM admin pages
(rdm.role.list 400); recovery required forensics. KTD4 keeps base isAdmin
to audit-view only, so an operator-side trusted channel is needed.
Evidence: python3 -m unittest tests.test_svc_rdm_admin -v (25 OK, SELF);
live smoke on runtime/dev: show/status/typo-guard outputs verified.
Impact: new svc.sh <env> rdm-admin [show|transfer --to x] command, help
topic, status ledger line with stale-owner warning; no behavior change
for existing commands.
Refs: task card .task/feature-rdm-admin-lockout-recovery.md R1/R2
Why: The live deploy journal never called fault injection, and test-lifecycle failed closed on login so CI could not require the real combination cases.
Evidence: SELF python3 -m unittest tests.test_svc_u2.U2ReleaseTests -q exit 0 (35 ok, 1 skipped) on 3602a87; receipt sha256 9b5785577751e8e9e7947cf9700fb8854b1c80142f34273ae25f3097ee4c9aa8.
Impact: test-pg builds the Dev binary and runs make test-lifecycle. Login and full-track deploy without SVC_RDM_ORIGIN stay NOT_RUN. No live data move and no account CLI.
Refs: recovery plan D2/D3; Dev #485
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=cd61bbb112eea6a210a64e84f2cef00b0d64bfc1.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: Main D1 now shares the same explicit fixture initialization contract.
Evidence: Both real SQLite and temporary PostgreSQL initialization paths
were independently replayed; capabilities JSON assertions are preserved.
Impact: Resolve duplicate PG setup through the tested helper; preserve
all main lifecycle changes and the rollback directory protection.
Refs: Dev #483/#485; D1 existing-store identity contract
Why: one isolated run reached a listening server and still failed the single login attempt, while the same data accepted the password a moment later.
Evidence: replaying the login against that data directory returned HTTP 200.
Impact: the seed retries login for a few seconds before it stops. The password and the set-password step are unchanged.
Refs: scripts/e2e.sh
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: the audit seed does not provide the project-settings entry, so the U7 live-entry specs fail before the script reaches its plain-base phase.
Evidence: the isolated run passed all five rdm-audit specs, including the overview export, and failed four U7 specs on a missing 项目设置 tool.
Impact: this script's first browser phase is limited to e2e/rdm-audit.playwright.ts. The U7 specs stay in the frontend suite for their own seed.
Refs: scripts/e2e.sh
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: a freshly created account still has must_change_password set, so the seed command returns 403 before Playwright can open the audit workspace.
Evidence: a replay of the isolated seed received "forbidden: password setup required" on rdm.project.create.
Impact: the seed completes the existing set-password call and logs in again. Browser login still starts from the initial password.
Refs: scripts/e2e.sh
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: env -i dropped RDM_DISABLE_EXEC_TOOLS, so the real RDM binary exited immediately on runners without bwrap, and the capability probe now prints the JSON document.
Evidence: SELF bash -n scripts/svc.sh; python3 -m py_compile tests/test_svc_realcombo.py. GATE run 2656 job 3831 failed on the previous head before this fix.
Impact: serve and the lifecycle child forward that one switch; identity capabilities is checked as protocol 1 JSON.
Refs: #485
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: main gained the real-combination CI gate after the previous sync, and this branch still has to carry that gate with the isolated identity calls.
Evidence: SELF python3 -m unittest recovery/identity/u2/deploy/pin/isolation — 100 tests OK (2 skipped); bash -n scripts/svc.sh.
Impact: identity ensure/verify still pass DSN only through the environment; stop waits for the port and can keep the desired state. CI keeps the lifecycle pin step and the svc-realcombo job.
Refs: #485
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: env -i dropped SVC_STUB_*, so recovery tests saw an empty serve record even though the bound DSN was still passed.
Evidence: SELF python3 -m unittest tests.test_svc.SvcDbRecoveryTests tests.test_svc_lifecycle_isolation — 34 tests OK.
Impact: only SVC_STUB_* is added at launch; serve.env still omits them, and caller AGENT_SYSTEM_* stays out of the process.
Refs: #485
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=99048dda1f48bccb3d5d798050d7beeea2907177.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: main already has one release transaction, so this branch keeps that path and only isolates update and recover in a clean child.
Evidence: SELF bash -n scripts/svc.sh; python3 -m unittest identity/recover/deploy/u2/lifecycle pin 92 tests OK (2 skipped), then 66 tests OK after dropping the obsolete journal hook.
Impact: deploy uses releases/ and deploy.journal; the lifecycle child reconciles that journal before deploy or recover. Backend pin is 0f192a4.
Refs: #485
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: on slow runners the orphaned http child of a stopped stub lingers
a few hundred milliseconds past the parent's exit (ppid-watch suicide),
and the immediately following start - notably the U2 rollback restart -
classified the unparented listener as a foreign occupant and refused to
start (CI run 3774).
Evidence: test_svc_u2/identity/svc suites 82 OK locally with the wait
in both stop paths.
Impact: adds <=3s bounded wait in do_stop/do_stop_quiet after SIGTERM
cleanup; no behavior change when the port is already free.
Why: Second-resolution release IDs let staging delete a previous release
when a same-source deployment ran within the same clock tick.
Evidence: Fixed-clock rollback regression fails before and passes after;
250 governance checks pass. Independent review replays collision and
copy-failure protection; receipts are in the primary task card.
Impact: Add invocation identity and exclusive directory creation; keep
old artifacts intact. Also retain the latest compatible frontend pointer.
Refs: User-approved I2; Dev #483; Frontend #71/#72
Why: an update that stops the old process and overwrites the binary cannot
get the previous version back, and a migration the old binary cannot read
must be refused before that stop. CI also had no fixed RDM SHA to build from.
Evidence: python3 -m unittest tests.test_svc_identity tests.test_svc_recover tests.test_svc_deploy_txn tests.test_lifecycle_pin passed. make test-lifecycle exits 2 when AGENT_PG_TEST_DSN is unset.
Impact: installs land in releases/<rid> and current switches with mv -T.
Deploy keeps the desired state and rolls back a non-terminal journal.
Schema compatFloor above the installed target is refused unless
--migrate-schema --confirm is paired with a backup. test-lifecycle fails
closed without PostgreSQL and an RDM checkout. Login stays NOT_RUN.
Refs: recovery plan r3.1 D2 and D3; Backend feature/d1-identity-open
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: stub suites proved the script logic but not real artifact
behavior (the 2026-10-12 incidents passed all stub tests); the report's
U3 requires real-combination gates, and realcombo dry-runs exposed two
real gaps: fresh deploys closed identity governance one lifecycle late,
and pg-bound identity calls put the DSN on the command line.
Evidence: make test exit 0; local realcombo dry-run 16 OK (rows in the
task card); CI adds svc-realcombo (SQLite, both real binaries, full RDM
track) and a real-PG identity step on test-pg with env-delivered DSN.
Impact: tests/test_svc_realcombo.py (SVC_TEST_REAL gate, explicit
NOT_RUN otherwise); ci.yaml new job + test-pg step (RDM clone via
trusted-base URL-scoped token header, allowlist addition reviewed in
this PR); svc.sh delivers identity DSN via AGENT_SYSTEM_DSN and runs
manifest adoption in the same deploy that first registers svc.env;
modules/backend pinned to main (env fallback, backend #182).
Refs: .task/feature-svc-u3-realcombo.md; user goal directive 2026-10-12
(U3); backend #182; RDM #285.
Why: probing identity by running the subcommand still launched old RDM
builds, and ensure on a missing database created an empty one. A batch
update also inherited the caller's AGENT_SYSTEM_* variables.
Evidence: python3 -m unittest tests.test_svc_identity tests.test_svc_recover passed (41 tests, 1 skipped). tests.test_svc_lifecycle_isolation caller-env and restart cases passed.
Impact: capability probes use version --json only. Established instances
refuse a missing identity row until adopt --confirm. update and recover
run each service in a clean environment. serve reads a 0600 serve.env
and does not inherit the caller environment. Backend and documents pins
move to the D1 identity and recovery-plan commits.
Refs: recovery plan r3.1 D1; Backend feature/d1-identity-open; RDM feature/d1-version-json
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=3b9cf82cd6fb53f973f26e2039275f7858b0c654.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: deploy overwrote live artifacts after stopping the old service, so
a failed start or workbench check left instances in a mixed
registration-vs-artifact state with no recovery path (2026-10-12
rdm1/rdmcand); the report's U2 requires restorable updates.
Evidence: make test-governance 250 OK; five svc suites 105 OK (rows in
the task card); new tests cover layout/pidcheck stability, rollback on
start failure with desired-state restore, build failure keeping the old
service running, interrupted-switch journal resolution, and schema-
advance blocking rollback without touching the database.
Impact: agent deploys stage immutable releases/<id>/ and switch the
current symlink atomically; deploy.journal persists the switch and is
resolved at start/restart/deploy/update/recover entries; legacy layouts
are adopted on first deploy and remain readable; release/rdm tracks
verify sha256 before staging.
Refs: .task/feature-svc-u2-release-recovery.md; user goal directive
2026-10-12; Dev #474 (U1 gate); Documents unified-deploy plan r2.
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=6a494d3977e6557e7bebe0e5bb1c4a12091296e0.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: batch update leaked AGENT_SYSTEM_INSTANCE_ID/DBREF from one service
to the next, and RDM artifacts without the identity CLI were stopped and
overwritten before their startup identity refusal surfaced, leaving
rdm1/rdmcand in a mixed registration-vs-artifact state (2026-10-12).
Evidence: make test-governance 217 OK; tests.test_svc_identity and
tests.test_svc_precheck green; rows recorded in the task card.
Impact: env_config resets identity env per service; capability probe is
timeout-guarded and rejects serve-shaped output; identity ensure moves
to adoption/init (bare start is verify-only); deploy builds and gates
candidates before stopping the old service (refuses identityless
candidates, completes missing identity rows via the candidate); update
runs svc_manifest_migrate like every other lifecycle entry.
Refs: .task/feature-svc-identity-u1.md; user root-cause report 2026-10-12.
Why: make the agent responsible for merging reviewed PRs without another human merge step.
Evidence: SELF governance and generated-card checks are captured in .task/feature-agent-pr-merge.md; CI remains required on the final PR HEAD.
Impact: update project delivery policy, agent entry points, task metadata and closure guidance; preserve platform protection and scoped authorization.
Refs: .task/feature-agent-pr-merge.md; user instruction on 2026-10-12
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=b4b042630a352eca2a399a7a64931c74978bca7f.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
Why: make the six instance-bound user commands discoverable (T5-1) and pin Documents r2/r3.
Evidence: python3 -m unittest tests.test_svc_user_help; existing test_svc_user_binding still green.
Impact: scripts/svc.sh help accounts|user; docs/svc.md topic list; documents gitlink to plan branch tip.
Refs: Documents #87; feature/svc-account-durability-plan
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=c6fefa3435dc5d9524fc35483f1d34fa1a6e0d59.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync
# Conflicts:
# tests/test_svc.py
Why: Batch update --all left SVC_PIDCHECK from the prior service in
memory, so pid_alive/reclaim_own_port misclassified the next service's
process as dead/foreign, deleted svc.pid, and failed start on a still-
occupied port (genui/rdm1/rdmcand after successful dev).
Evidence: make test-governance (SELF; receipt /tmp/svc-pidcheck-gov.json);
new test_batch_update_stops_second_service_despite_prior_pidcheck +
SVC_PIDCHECK ratchet in test_svc_precheck.
Impact: env_config clears SVC_PIDCHECK/EXEC/VERSION/SOURCE per service;
batch update correctly stops and restarts each agent. After merge:
restore genui/rdm1/rdmcand and move rdmcand to its own data dir.
Refs: .task/feature-svc-pidcheck-leak.md; complements #456 reclaim_own_port
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: genui update cleared svc.pid without killing the process, then
overwrote the binary and failed start with a false "non-ours" port error.
Evidence: make test-governance (receipt /tmp/svc-reclaim-governance.json)
Impact: reclaim_own_port walks ss listener ancestry; stop/check_port/install
wire it; orphans matching pidcheck are stopped, foreign occupants still refused
Refs: fix/svc-reclaim-own-port
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: RDM agent deploy left workbench htdocs unserved (prompt-only), so
environments like dev silently offered API-only 404 pages after a source
switch; static first-start also misclassified http.server as dead when
pidcheck was unset.
Evidence: CMD="make test-governance" make evidence (200 ok, 1 skipped; SELF).
Impact: rdm deploy auto-starts <name>web and asserts UI 200; cross-kind
redeploy needs --allow-source-switch; list/info flag missing workbench.
Refs: .task/feature-svc-rdm-ui-gate.md; docs/svc.md §5.4
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: include the current integration baseline before verification.
Evidence: fetched origin/main=b008bd94ad0fe6f520a8500f40ed6297251762b7.
Impact: integrate upstream changes without rewriting task history.
Refs: task-sync