Integrate pb-mirror into os-sdlc: .pbm.yml, gitignore, after_commit tickle #510
Labels
No labels
P0
P1
P2
P3
bug
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#510
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
ADR-0150 decides a read-only PocketBase mirror of .sdlc/pipeline.db via the standalone pb-mirror gem (~/dev/ruby-gems/pb-mirror, binary pbm). The gem is built separately; this ticket is the os-sdlc side of the integration. Design settled in the 2026-08-25 grilling session.
Slice
A pipeline gate settlement on a repo with pbm installed appears as fresh rows in the PocketBase admin UI within ~2s, via a fire-and-forget after_commit tickle.
Tasks
[ ] Add committed .pbm.yml at repo root: db_path .sdlc/pipeline.db, table list with watermark columns (default updated_at), port, PocketBase version pin.
[ ] Gitignore .pbm/ (pb_data, credentials, pidfile, lockfile).
[ ] Add a Sequel after_commit tickle in the runner that spawns pbm sync fire-and-forget (never blocks a write path; pbm handles lockfile-skip and self-healing up/full-sync).
[ ] Verify worktree behavior: tickles from worktree sessions resolve through the ADR-0143 symlink to the owning pipeline.db; one mirror instance total.
[ ] History row in the os-sdlc implementation-status leaf.
Acceptance criteria
[ ] A pipeline run with pbm installed shows fresh rows in the PocketBase admin UI within ~2s of gate settlement, with no runner slowdown or new runner test failures.
[ ] With pbm absent or PocketBase down and unbootable, the runner behaves exactly as today (tickle failure is silent-to-the-pipeline, logged only).
Non-goals
• The pb-mirror gem itself (own repo).
• Any monitoring front-end pages.
Notes for implementer
.pbm.yml already exists at repo root and is now staged for commit; the stray .gitignore entry ignoring it was removed on 2026-08-27 during triage — task 1's remaining work is verifying content and committing. The .pbm/ gitignore entry already exists. The runner integration point is plugins/os-sdlc/lib/os_sdlc/runner/db.rb per ADR-0150. Real gem commands:
pbm init <db>writes config,pbm installdownloads the pinned PocketBase binary.Origin
• Trigger: 2026-08-25 grilling session on swapping sqlite for PocketBase in os-sdlc.
• Improvised this session: none
• Chain: no live view of pipeline data ← pipeline.db only readable via sqlite CLI ← DESIGN (ADR-0089 SQLite+Sequel persistence; resolved additively by ADR-0150)
• Root candidate: this ticket (with the pb-mirror gem as its dependency)
Refined to ticket tier: added Slice, renamed Out of scope to Non-goals, added Notes for implementer. Gitignore contradiction resolved (.pbm.yml unignored and staged, .pbm/ stays ignored). Redundancy check found the after_commit tickle unimplemented. No undecided choices, so no decision children.
Work started via os-sdlc pipeline. Branch: ticket-510.
os-sdlc pipeline run failed at node code-probe (implementation_id 2, reason verdict:fail). Gate details: code-probe found no after_commit/pbm/sync/tickle code under plugins/os-sdlc/lib (all four PHANTOM), so it returned verdict fail because the ticket's core behavior is unimplemented. Evidence it did collect: write-path entry points Db.connect/Db.file_db at plugins/os-sdlc/lib/os_sdlc/runner/db.rb:15,36; .pbm.yml exists at repo root (port 8090, version pin) but with an absolute db_path; .gitignore already has .pbm/; worktree pipeline.db symlink matches ADR-0143. Branch ticket-510 kept. No resume path — recovery starts with a new implementation-open.
os-sdlc run 3 (implementation_id 3) terminated: bound_exhausted:test-writer/fail at dispatch 22. Cause is the known unexpected-pass routing gap, not missing work: behavior-verifier required a failure-path test, that test (test_a_failing_tickler_stays_silent_and_commit_succeeds in plugins/os-sdlc/tests/runner/db_pbm_tickle_test.rb) exists and pins the correction exactly, but it is green on arrival because MirrorTickle's rescue already shipped in the programmer round — the test-writer node demands red, has no unexpected-pass verdict, and looped until the bound tripped. Work state: after_commit tickle implemented (db.rb + mirror_tickle.rb), 3 behavior tests, suite green, lint green, contract-auditor pass with zero corrections. Awaiting human decision on manual acceptance (precedent: #491 override).
Resolution
Done: os-sdlc integration of pb-mirror complete: MirrorTickle module spawns pbm sync fire-and-forget via an after_commit hook installed at Db.connect (CommitHook wraps Database#transaction); failures swallowed and logged to stderr; committed .pbm.yml now has relative db_path .sdlc/pipeline.db, port 8090, PocketBase 0.40.1 pin; .pbm/ already gitignored; worktree tickles resolve through the ADR-0143 symlink (relative db_path + symlinked .sdlc/pipeline.db); history row added to docs/implementation-status/os-sdlc.md
Evidence: Merged to main:
a18e16a(tickle + 3 behavior tests: commit fires once, rollback never fires, failing tickler stays silent with commit intact),125cfcf(history row),a486944(relative db_path). Suite 1226 runs 0 failures; lint clean; contract-auditor pass with zero corrections. Pipeline run itself ended bound_exhausted:test-writer/fail (unexpected-pass gap) and was accepted by explicit user override, precedent #491.Follow-ups: #522 already filed this session (code-probe greenfield misroute, skeptic VERDICT: CREATE). Unexpected-pass verdict gap in the test-writer gate: investigated this session (local per-edge bound exhaustion routes via error: to terminal by ADR-0133 design; ADR-0152 cap-as-escalation covers only the global dispatch cap); previously left unticketed by explicit user choice after #475; findings surfaced to the user, ticketing decision is the user's. No other follow-ups.