Why: branches merged into main had left their task cards open; backfill status and archive to prevent bookkeeping debt.
Evidence: feature-cross-session-reading.md(PR#67) — merges verified via git log --merges against origin/main.
Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change.
Refs: task.sh close (card-autoclose-r1)
Why: cmd_start derived the worktree location from $PWD, so running task.sh start from a repository subdirectory (or inside a task worktree) placed the new worktree at the wrong spot — e.g. scripts-wt-<slug> nested inside the repo.
Evidence: bash -n clean; functional smoke of the patched script from both the main checkout scripts/ subdir and the repo root created ../Agent-System-Dev-wt-<slug> as a sibling of the main checkout (paths asserted; pre-fix subdir run would nest inside the repo); git rev-parse --git-common-dir resolves to the main checkout from both locations (relative ../.git vs absolute).
Impact: scripts/task.sh cmd_start only; from the main checkout root the derived path is identical to before; new worktrees now always land as siblings of the main checkout regardless of invocation directory.
Refs: .task/feature-task-start-rootfix.md
Why: make contracts regenerates modules/ui/src/contracts.ts from Core
as authority; the mirror commit (UI PR #15) must be pinned or the
combined tree stays dirty after make test.
Evidence: UI PR #15 merged on ui main; make test re-run on this tree
below.
Impact: gitlink-only change.
Refs: Core PR #6; UI PR #15; Dev task feature/cross-session-reading.
Why: branches merged into main had left their task cards open; backfill status and archive to prevent bookkeeping debt.
Evidence: feature-svc-auto-update.md(PR#65) — merges verified via git log --merges against origin/main.
Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change.
Refs: task.sh close (card-autoclose-r1)
Why: integrate the approved cross-session reading feature (proposal +
core contract + backend gate/tools/UI) into the Dev composition.
Evidence: subrepo PRs all merged on their mains — Documents #21
(bf0988b), Core #6 (fd44179), Backend #18 (cb7f79d), Frontend #16
(9c87953); combined make test to follow on this exact tree before the
Dev PR is requested.
Impact: gitlink-only change plus task card; no Dev-repo code touched.
Refs: modules/documents/docs/proposals/2026-09-30-cross-session-reading.md;
task card .task/feature-cross-session-reading.md.
Why:
After the repository moves forward, updating a running service meant
manually figuring out the new commit, rebuilding and redeploying by hand;
the user asked for the tool to detect and update automatically.
Evidence:
- "update [name...] [--check] [--all] [--no-fetch]": fetches origin,
compares each service's registered source against the latest (Dev repo
origin/main for local@/dev@ sources, newest Releases version for
release@), prints a per-service table (current / latest / state), and
without --check refreshes outdated running services by reusing the full
deploy pipeline (stop → build/verify → start → health check; persisted
exec= config and tags survive; update events appended to history).
- local@ services: auto git pull --ff-only origin main + make sync before
rebuilding, guarded three ways (current branch == main, clean worktree,
ff-only) — dirty trees or non-main branches are skipped with a warning,
never touching uncommitted work.
- dev@ sources go straight to the remote main commit via an isolated
worktree; release@ sources deploy the newest Releases version with
sha256 verification; postgres and static --dir services are reported as
not applicable; sources that diverged from or lead the remote are never
force-updated.
- Verified end to end with five test services: dev@73b2802 → dev@ffda6d3
(real isolated build, HTTP 200, tag/port preserved, worktree recycled),
non-main-branch skip, stopped-service warning vs --all, release
sha256-verified update, --check read-only (svc.env checksums unchanged),
unregistered name exits 2.
- Fixed en route: a latent bug from the v2 refactor — materialize_dev_commit
leaked submodule/make stdout into the captured worktree path, breaking
every real dev@sha deploy since (cp: File name too long); build output
now goes to stderr. Also fixed an unbound-variable crash in the update
loop (local statement self-reference under set -u).
Impact:
New read-mostly operational command; no behavior change to existing
commands except dev@sha deploys now actually working end to end.
Makefile gains svc-update; --help and docs/svc.md document the command.
Refs: .task/feature-svc-auto-update.md(任务卡=PR 描述)
Why: branches merged into main had left their task cards open; backfill status and archive to prevent bookkeeping debt.
Evidence: feature-svc-docs-help.md(PR#63) — merges verified via git log --merges against origin/main.
Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change.
Refs: task.sh close (card-autoclose-r1)
Why:
svc.sh grew into a three-kind service manager with database operations,
but its only documentation was a flat --help wall of text; the user asked
for a complete usage document and a better help experience.
Evidence:
- docs/svc.md: 14-section manual (prerequisites, quick start, concepts
and directory layout, per-command reference for service/global/db
commands, deploy sources, database operations handbook, configuration
layering, registry fields and event types, safety boundaries, exit
codes, troubleshooting table, recipe index) — every claim cross-checked
against the implementation from the previous two rounds.
- Help layering: no-args and -h print a one-screen overview; --help
renders the header comment reorganized into 7 labeled sections; the new
"help [topic]" command deep-dives eight topics (model, deploy,
lifecycle, db, dbops, config, examples, safety); usage errors now show
the short overview plus a pointer to --help / help / docs/svc.md.
All topics verified to render; unknown topic exits 2.
- No runtime behavior changed: end-to-end db lifecycle regression
(create → start → backup → status → stop → rm --purge) passes after the
refactor.
- Makefile help and README's documentation section point to docs/svc.md.
Impact:
Documentation-only plus display-layer changes; command semantics,
exit codes and file formats are untouched. Maintenance note: behavior
changes must now update both --help and docs/svc.md.
Refs: .task/feature-svc-docs-help.md(任务卡=PR 描述)
Why: branches merged into main had left their task cards open; backfill status and archive to prevent bookkeeping debt.
Evidence: feature-ui-capability-platform.md(PR#61) — merges verified via git log --merges against origin/main.
Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change.
Refs: task.sh close (card-autoclose-r1)
Why: R-platform spans core/ui/frontend/documents; also honors the
agreed housekeeping item — .env.dev must be gitignored (it holds live
API keys).
Evidence: make test full suite green on this head (exit 0); headless
walk on the real binary: avatar columns, settings shell with badges,
admin-row avatars, zero console errors.
Impact: capability layer only, no behavior changes. Merge order:
core -> ui -> frontend -> documents -> this PR.
Refs: proposal 2026-09-30-ui-redesign-and-auth.md (capability platform)
Why: branches merged into main had left their task cards open; backfill status and archive to prevent bookkeeping debt.
Evidence: feature-svc-db-ops.md(PR#59) — merges verified via git log --merges against origin/main.
Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change.
Refs: task.sh close (card-autoclose-r1)
Why:
The service manager could create and run postgres instances but had no
way to retarget a port explicitly, back data up, clone an instance to
another port, or move a database between instances — the user asked for
exactly these operations.
Evidence:
- "set <name> [--port N] [--host H] [--apply] [--tag T...]": explicit
registration change; running postgres requires --apply (stop → rewrite
registration → start); port availability checked against both
registrations and live listeners. Verified: 8890→8895 with data intact
and DSN updated, old port freed; refusal without --apply.
- "db backup <name> [--db X] [--out F]": pg_dump -Fc into
runtime/<name>/backups/ (0600) with pg_restore --list self-check;
"db backups" lists them.
- "db restore <name> --file F [--db X] [--force]": restores into a new db
or refuses on a non-empty target unless --force (drop with FORCE +
recreate + restore), reporting table counts afterwards. Verified all
three paths.
- "db clone <src> <dst> [--port P] [--password PW] [--tag] [--online]":
default physical clone (brief source stop, cp -a of pgdata minus
postmaster files, new registration, source restarted on its own port);
--online copies via dump/restore without stopping the source (verified
source pid unchanged). Clone lands on the requested or derived port.
- "db copy <src> <dst> [--db X] [--force]": single-database logical move
between two running instances with the same non-empty-target guard.
"db ls <name>" lists databases.
- Fixed during verification: clone/copy leaked the CLI --port into the
source restart path (source briefly came up on the clone's port); the
address overrides are now cleared inside those commands.
Impact:
All operations stay inside runtime/<name>/, append to history.jsonl, and
reuse the existing safety constraints (own-process stop, port conflicts
reported not seized, secrets in 0600 files). Overwriting a non-empty
database requires an explicit --force everywhere. Makefile help line
mentions the new db subcommands.
Refs: .task/feature-svc-db-ops.md(任务卡=PR 描述)
Why: feature/svc-services-registry merged via PR #57 (merge 33fe7fb);
its card must be marked done and archived per the no-pending-cards rule.
Evidence: git log --merges origin/main shows 33fe7fb merging the branch;
card backfilled with PR link and moved to .task/archive/.
Impact: .task bookkeeping only (main checkout holds an unrelated untracked
.video_agent/ dir which is left untouched).
Refs: task.sh close
Why:
svc.sh only managed agent-system environments; databases, standalone
frontend serving, per-service tags and reusable start configs were out of
scope, and the user asked for a unified service lifecycle on this host.
Evidence:
- Service model v2: kind=agent|static|postgres registered in
runtime/<name>/svc.env (dotenv, mode 600); legacy entries without kind=
are adopted as agent.
- postgres: "db create <name> --port/--user/--password/--db/--auth-mode/
--tag" runs initdb (scram-sha-256, pwfile 0600), start/stop/restart use
pg_ctl (-m fast, never SIGKILL on postmaster) with pg_isready checks and
first-start database creation; "db dsn <name> [--reveal]" prints a
composable DSN (password masked by default). Verified end to end against
a real postgresql@18 instance: data survives restart, wrong passwords
rejected, stop/restart clean.
- static: "deploy --kind static --from dev[@sha]|local" builds frontend
dist into htdocs/ in an isolated worktree, or "--dir PATH" serves an
existing directory; verified serving HTTP 200, restart, stop, dry-run
plan, and explicit rejection of release sources.
- agent: unchanged three deploy sources plus --tag; bare start/restart now
reuses the persisted exec= from svc.env (verified: same custom port and
args across restart); old binaries lacking --dsn/--auth get those flags
auto-omitted with a warning.
- "list|status [--tag]" shows NAME/KIND/STATE/PID/ADDR/SOURCE/TAGS for all
registered services; "<name> status" gives per-kind detail; "rm <name>
[--purge]" unregisters (and optionally deletes) only runtime/<name>/.
- Fixed during verification: psql arg mangling (-c -c), tags lost because
record_state read svc.env inside its own redirect block, postgres
--version field parsing, unbound vars for unregistered names.
Impact:
Same invariants as before: writes stay under runtime/<name>/ and
runtime/.worktrees/ (only --from local also writes main-checkout build
outputs, all gitignored), stops only own pidfile+cmdline-verified
processes, port conflicts reported not seized. Prompt output moved to
stderr so stdout (tables, DSNs) stays pipeable. Makefile gains svc-list.
Refs: .task/feature-svc-services-registry.md(任务卡=PR 描述)
Why: feature/svc-deploy-source-registry merged via PR #55 (merge 8523415);
its card must be marked done and archived per the no-pending-cards rule.
Evidence: git log --merges origin/main shows 8523415 merging the branch;
card backfilled with PR link and moved to .task/archive/.
Impact: .task bookkeeping only.
Refs: task.sh close