aboutsummaryrefslogtreecommitdiff
path: root/.ai/workflows
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-20 12:30:51 -0500
committerCraig Jennings <c@cjennings.net>2026-07-20 12:30:51 -0500
commit0767af804b980c23fdd759f65c0f50b499fb1bbe (patch)
tree1e521bbe6b9db8046c7137c09aa9588b0c1ccf67 /.ai/workflows
parent986d6caeeaba6e4ab2f1e6f5e760ce841c922259 (diff)
downloadrulesets-0767af804b980c23fdd759f65c0f50b499fb1bbe.tar.gz
rulesets-0767af804b980c23fdd759f65c0f50b499fb1bbe.zip
feat(sentry): a quiet fire collapses to a one-line heartbeat
A sentry fire whose passes all probe-skip or no-op now writes a single "sentry at HH:MM: nothing" line instead of a full per-pass digest block. A fire that runs or queues anything writes the full digest as before. This is Phase 1 of the silent-until-signal policy. The live trial's fires 3-8 were walls of no-op digests, the noise this removes. The "no silent skip" discipline is reconciled, not broken: inside a working fire every pass still writes its ran/skipped line, and a quiet fire's heartbeat is the explicit "nothing to do" record rather than a hidden skip.
Diffstat (limited to '.ai/workflows')
-rw-r--r--.ai/workflows/sentry.org10
1 files changed, 5 insertions, 5 deletions
diff --git a/.ai/workflows/sentry.org b/.ai/workflows/sentry.org
index 56f0c96..bfeeffc 100644
--- a/.ai/workflows/sentry.org
+++ b/.ai/workflows/sentry.org
@@ -89,7 +89,7 @@ Each fire, after acquiring the single-runner lock and verifying branch state (be
2. *Work* — run the pass under the unattended contract. Quick, solo, already-agreed mechanical actions execute. Anything destructive or requiring judgment does *not* execute — it appends to the morning-approval queue (what, why, the exact command or edit that fires on approval). A pass runs fully or not at all; there is no reduced-form pass.
-3. *Session-context entry* — append the pass's digest line to the =session-context.org= Session Log (path resolved via =.ai/scripts/session-context-path=). This precedes the commit so a crash between them still leaves the trail.
+3. *Session-context entry* — a pass that does or queues work appends its digest line to the =session-context.org= Session Log (path resolved via =.ai/scripts/session-context-path=) before its commit, so a crash between them still leaves the trail. Per-pass lines for an all-quiet fire (every pass probe-skipped or no-op) are not written one by one — the fire collapses to a single heartbeat at fire-end (below), so an idle fire doesn't spray one skip line per pass.
4. *Commit* — if the pass wrote to disk, commit it: =chore(sentry): <pass> — <what changed>=. One commit per writing pass. A probe-skip or a no-op pass writes nothing and commits nothing.
@@ -111,7 +111,7 @@ With no one at the terminal, any unsafe state makes the affected scope skip with
- *A pass's own precondition unmet* (its probe fails, or a dependency is dirty) → skip that pass only.
- *Red suite at fire-end* (see below) → the commits stay on the branch, flagged in the digest for morning review; the fire doesn't roll back.
-Skips are never silent and never partial. A pass line in the digest means the pass fully ran; a skip line names why it didn't.
+Skips are never silent and never partial. Inside a *working* fire, a pass line means the pass fully ran and a skip line names why it didn't. An *all-quiet* fire is not a silent skip either: its single =sentry at HH:MM: nothing= heartbeat is the explicit record that every pass found nothing, standing in for a wall of identical skip lines. The anti-silence rule targets a pass that hides work it should have surfaced; a quiet fire has surfaced that there was none.
** Multi-day stall notification
@@ -153,13 +153,13 @@ After the passes:
1. *Conditional suite run.* If any pass this fire modified files *outside* the org/spine set (a code-touching pass, rare but possible via fixtures), run the full suite once. A green run confirms the fire's commits are safe; a red run flags the digest for morning review — the commits stay on the branch (nothing is pushed, so the morning gate catches it). No per-pass suite runs: the entry run is the green baseline, and hourly per-commit runs would turn a seconds-long fire into minutes all night. Fires that only touched org/spine files skip this.
-2. *Digest commit.* Commit any accumulated spine writes in one sweep — =chore(sentry): digest — <date> <time> fire= — so even a read-only fire (all passes probe-skipped or no-op) leaves a clean tree. This is what lets the next fire's branch-state check see a clean, spine-excluded tree.
+2. *Heartbeat or digest, then commit.* Decide quiet vs working. A *quiet* fire — every pass probe-skipped or no-op, nothing added to the approval queue — writes a single heartbeat line to the Session Log, =sentry at HH:MM: nothing= (HH:MM local, from =date=), and no per-pass digest block. A *working* fire — any pass ran, wrote, or queued — writes its full per-pass digest block. Then commit any accumulated spine writes in one sweep: =chore(sentry): digest — <date> <time> fire= for a working fire, =chore(sentry): heartbeat — <date> <time>= for a quiet one, so even a quiet fire leaves a clean tree for the next branch-state check (where the spine is untracked, the mirror-only case, there is nothing to commit and the heartbeat line stays in the working-tree anchor). This is the silent-until-signal policy (see =docs/specs/2026-07-20-silent-until-signal-monitors-spec.org=): an all-quiet night collapses from a wall of no-op digests to a list of one-line heartbeats, while a fire that actually did or queued something still writes the full record.
3. *Release the single-runner lock.*
* The digest and the approval queue
-*Digest.* Each fire appends its lines to the =session-context.org= Session Log (the spine the fire already writes), so it survives a crash, rides the session archive, and is on screen in the running session. One block per fire: the timestamp, then one line per pass (ran + what, or skipped + why), plus any lock reclaim notes.
+*Digest.* A *working* fire appends its block to the =session-context.org= Session Log (the spine the fire already writes), so it survives a crash, rides the session archive, and is on screen in the running session. One block per working fire: the timestamp, then one line per pass (ran + what, or skipped + why), plus any lock reclaim notes. A *quiet* fire (nothing done or queued) writes no block — just the one heartbeat line =sentry at HH:MM: nothing= (the silent-until-signal policy). The per-pass block is a working-fire artifact; it still carries one line per pass so a real skip inside a working fire is never hidden.
*Approval queue.* Destructive and judgment actions accumulate under one heading in the same file — =* Sentry approval queue (<date>)= — newest last. Each item carries three things: *what* (the action), *why* (what triggered it), and the *exact command or edit* that fires on approval. The morning review is Craig reading this heading top to bottom and running or discarding each item.
@@ -201,7 +201,7 @@ Stopping sentry is the only way to reclaim the working tree mid-night. The entry
4. *Running a =git= write against =~/org/roam=* — roam-sync is the only committer. Sentry edits the tree under the roam-write lock and triggers the sync; it never commits or pushes roam.
5. *A per-pass suite run* — the suite runs at entry (baseline) and conditionally at fire-end (only when a pass touched non-org files). Hourly per-commit runs all night is the anti-pattern the suite policy exists to prevent.
6. *Executing a judgment or destructive action unattended* — those queue for the morning with their exact command. The pass did its detection; Craig makes the call.
-7. *A silent skip* — every skip writes a digest line naming why. A missing pass with no line reads as "ran clean" when it didn't.
+7. *A silent skip* — inside a working fire, every skip writes a digest line naming why; a missing pass with no line reads as "ran clean" when it didn't. The one exception is not a violation: an all-quiet fire collapses to a single =sentry at HH:MM: nothing= heartbeat instead of one skip line per pass — the heartbeat is the explicit "nothing to do" record, per the silent-until-signal policy.
8. *Degrading a pass to a reduced form* — a pass runs fully or skips. No half-passes.
9. *Letting an unmerged branch stall silently* — after two consecutive unmerged-branch skips, the persistent desktop notify fires. Don't suppress it.
10. *Merging sentry's branch automatically* — the morning teardown is Craig's. Sentry creates and commits; it never merges or deletes its own branch.