| Commit message (Collapse) | Author | Age | Files | Lines |
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Every bundle built its scan input as `git diff --cached ... | grep ... || true`. The `|| true` has to stay, since grep exits 1 when it matches nothing and that is the ordinary case. But with no pipefail it also swallowed a failure of git itself, so an empty result made the scan search nothing, find nothing, and report clean with a real credential staged. A gate that passes without having looked.
.emacs.d found it in elisp. It was in all five: bash, elisp, go, python and typescript, eleven sites once each bundle's staged-file list is counted. Two of those bundles are ones I wrote yesterday by copying bash, so I propagated it while closing an unrelated gap in the same file. Each site now reads the diff on its own and aborts if git fails, leaving the greps their `|| true`.
Verified per bundle on three axes: refuses when the diff cannot be read, still blocks a real staged secret, still passes a clean commit.
The cross-bundle test suite had its own version of the same disease. Its VARIANTS list read "elisp bash go" while python and typescript also shipped hooks, so every "in every variant" assertion had quietly skipped two bundles since the day they were added. VARIANTS is now discovered from the tree. Two fail-closed assertions join it, and .emacs.d's elisp suite is adopted here beside the canonical hook, because a test living in the consuming project cannot fail when the canonical regresses.
Also removes the validate-el auto-test cap, Craig's call. Above 20 matching test files the runner skipped everything and exited 0 with no output. The premise was speed and it did not hold: a whole family runs in about a second. The cap was also hiding a real cross-test pollution bug that only surfaces when a family runs in one process.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An overnight hygiene run over this repo, reviewed adversarially afterward. Every problem below was reproduced before it was fixed, and every fix was re-checked by a skeptic who was told to refute it.
cj-remove-block could silently destroy content. Its range check validated only the first and last lines, so a span from one cj block's opener to a later block's closer passed and the removal deleted everything between — prose, headings, whole tasks, with a zero exit. That is the failure the check exists to prevent, and drift is its normal case, since the calling skill edits the file while processing. It now refuses a range holding more than one block, backs up first, and writes atomically while preserving the file's mode and following symlinks to the real target.
todo-cleanup rewrote todo.org with no backup, alone among the three tools that mutate these files. It now copies to the temp dir like lint-org does. Both backup helpers suffix rather than overwrite, because a second-resolution stamp collapsed two back-to-back invocations into one backup holding already-mutated content — and running todo-cleanup twice in a row is the shipped path.
audit.bats failed about one run in eight, in teardown rather than in its assertions, so a passing test reported as a false red. git commit spawns a detached maintenance process that is still writing packs when the commit returns, racing the cleanup. The fixture disables it.
route_recommend downgraded a correct strong match to weak when two projects shared a basename. lint.sh now sweeps the scripts that get symlinked onto PATH, which were the only shell in the repo with no gate over them.
Two test defects found in review and fixed here: a suite that deleted real backups from the shared temp dir, and one that depended on that directory's contents. Isolation now lives in an autouse fixture rather than in each test's memory.
Known and filed, not closed: the range check still cannot prove the range is the block that was scanned, so drift by exactly one whole block deletes the wrong annotation. That needs a content assertion and a CLI contract change.
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
Two additions from Craig, both landing on the throwaway branch that already makes a bad night a deleted branch.
Pass 11 now finds refactoring opportunities alongside bugs, filing each as a graded task. Still find-never-fix: a fresh finding files a task and stops, because a just-found bug can be a misread (one was filed and retracted two fires apart on 2026-07-23). The task is the checkpoint.
New pass 12 implements the backlog's solo, decision-free tasks on the branch, off by default behind :SENTRY_MAY_IMPLEMENT:. It reuses work-the-backlog's unattended-loop contract: only the ready bucket runs, anything needing a decision defers to a VERIFY, and nothing pushes. The morning review is the gate. Its /review-code runs the premise check first (reproduce the bug before judging the diff), because a filed claim never gets a review, and that skeptical review is what makes fixing on a branch safe. A finding that fails its premise check isn't implemented.
The marker is separate from :COMMIT_AUTONOMY: on purpose: hygiene is a two-minute merge, implemented code is a review session, so the owner opts in per project.
|
| |
|
|
|
|
| |
Craig's idea, via archsetup: drop a question into the roam inbox, have the agent retrieve it during a pass but hold rather than auto-answer, then answer it live at the next conversation and close on his acknowledgement. The inverse of a VERIFY — the agent owes the answer, not the other way round.
Parked as a spec candidate rather than a direct build: the value is clear, but marking a question item, tracking the answer-owed state, and the new-keyword-vs-VERIFY-variant call are decisions to make with Craig. The proposal is staged under working/.
|
| |
|
|
| |
Three inbox-send and lint-org bugs fixed and one already satisfied, closed with their commit SHAs. Metrics for the run appended to the backlog log.
|
| |
|
|
|
|
|
|
| |
The five todo-format-family checkers encode todo.org completion conventions, but they ran on every org file, so they misfired across docs/specs/. That was 100 findings over nine specs in this repo, and the same noise in every project carrying specs. A spec's Decisions section legitimately uses a level-2 DONE with no CLOSED cookie. Its review-history uses level-2 dated headings. Neither is a completion defect there.
A path guard now skips the family on any file under a docs/specs/ segment, the canonical spec home per the docs-lifecycle rule. Link, table, and structural checks still run on specs, so a broken link in one still flags. todo.org and every non-spec org file keep the full checker set.
Folds in task-missing-last-reviewed alongside the four named checkers, since it's the same family and misfires the same way on a spec's phase tasks. Correcting an earlier note in the task: these are lint-org.el's own checkers, not org-lint's, so the fix is a local guard rather than filtering upstream output.
|
| |
|
|
|
|
| |
main caught ValueError and FileNotFoundError around the send, so an unreadable source raised a PermissionError as a raw traceback instead of the clean "inbox-send: <message>" every other failure produces. Widening the catch to OSError covers the unreadable source, the missing source, and any atomic-write failure alike.
discover_projects appended without deduping, so a roots config naming both a parent directory and one of its children listed the same project at two indices. It now dedupes on the resolved path, first-seen order preserved.
|
| |
|
|
|
|
|
|
| |
inbox-send wrote straight to the destination path, and write_text truncates on open, so any mid-write failure left a zero-byte .org in another project's inbox. inbox-status counted that phantom as a pending handoff and blocked a turn in the receiving project over a file with no content and no sender.
Both send paths now write to a temp sibling and os.replace it into place, so the inbox only ever sees a complete file. A caught failure removes the temp and re-raises, leaving no debris. encoding is pinned to utf-8 on the write and on the roots-config read, which closes the locale-dependent failure that first surfaced this.
inbox-status also skips the .inbox-send-* temp, so the brief window before the rename can't read as pending either. The atomicity is only complete once the consumer ignores the in-flight file.
|
| |
|
|
|
|
| |
Home hit a cross-account hazard: a triage fire reached the personal inbox through a work-bound Gmail MCP and pulled 201 DeepSat messages, which would have run every hygiene action against the wrong mailbox. The fix adds one guard to the plugin's Scan phase — verify a sample result's recipient before classifying, fall back to the local mu mirror on mismatch rather than another MCP.
Parked for approval since the plugin is a synced asset. Graded [#A] on severity alone: acting on the wrong person's mailbox is a privacy exposure regardless of how rarely it happens. Diff and companion note staged under working/.
|
| |
|
|
|
|
| |
Craig proposed a new pattern from the work session: a sentence that makes the reader translate more than one specialized term is too dense and gets rewritten. He supplied the rule and a worked before/after and left number, placement, and mode to me.
Prepared as #48 in general mode, since it's a universal clarity rule rather than a Craig-voice trait. The one structural call is in the VERIFY: general mode was a clean "patterns #1-31," and a general pattern at #48 breaks that, so the diff updates every enumeration to "#1-31 and #48." Both files and the diffs are staged under working/, ready to apply on his word.
|
| |
|
|
|
|
|
|
| |
Adds pattern #47: in a reply, lead with what matters most to the recipient, not the easiest answer or the order they wrote it. Correspondence-scoped, so it fires on email, Signal, and letters and nowhere else. It's the one pattern that doesn't carry into personal mode, since a commit or PR review isn't a reply to someone's news.
Recalibrates #43 in the same edit. "Shifts angle" now means shifts topic: break between topics, consolidate within one, up to a five-or-six-sentence ceiling. The never-merge line was being read at sentence granularity, which fragmented single topics across paragraphs. #43 and #47 are one rule seen from both sides, the break between topics and the order of them, not a rule in tension with its neighbor.
Both land in SKILL.md and the profile per the pairing rule, with the worked before/after in the profile. From a home session drafting a Signal reply; the design is Craig's.
|
| |
|
|
|
|
|
|
| |
Craig's roam capture reached me a second time, relayed from another project, and the sender asked what already existed before treating it as new. Three of its four asks had already shipped, one of them earlier today from the same capture.
The remaining ask is an automatic sweep of a closed task's working/ files into temp/. I'm recommending against it. temp/ is cleared at the next wrap, so the sweep would destroy the artifacts that working-files.md says to rename and file into assets/. Filing is also the moment you decide what each artifact is worth keeping as, and automating it skips that.
The real gap is smaller: orphan detection only runs during a sentry fire, so a project that never runs sentry never hears about it. The parked diff adds report-only detection to wrap-up.
|
| |
|
|
|
|
|
|
|
|
| |
The python and typescript bundles carried rules and a coverage script but no pre-commit hook, so any project installing one got no credential scan on commit. Both now ship all four components the README documents: the shared secret scan, a validate-on-edit hook, settings wiring, and a seed CLAUDE.md. Verified against a real repo: a commit carrying an AWS key is refused.
install-lang now warns when a bundle is missing a documented component. That's the half that keeps this from recurring. Whoever adds the sixth bundle will forget something too, and today the installer prints success either way.
Two things fell out of the build. node --check is unusable on TypeScript: it ignores --experimental-strip-types, so it rejects valid TS and accepts broken TS. The hook uses tsc filtered to syntactic diagnostics instead. And completing the bundles means every pair now collides on settings.json and pre-commit, so no two compose without FORCE=1. The earlier "bundles already compose" reading rested on these two being incomplete. Filed for a real decision; clock-panel is the project that wants it.
Also stamps :LAST_REVIEWED: at task creation, with a lint checker to catch misses. Writing a task is reviewing it, so leaving the stamp off pushed every fresh task to the top of the next review batch to be re-derived by someone with less context than its author had. Tonight's sweep sent the staleness count from 13 to 22 while the list got more accurate.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Four proposals from other projects, reviewed and applied together.
wrap-it-up gains a Clear temp/ step in Step 3. temp/ is gitignored everywhere, so nothing there survives deletion. The step confirms before removing anything that reads as in-progress rather than throwaway, and skips where temp/ isn't gitignored. This closes the last open clause of the working/temp work from 2026-07-20.
interaction.md drops the fenced-code-block carve-out. Chat output carries no markup at all now, fences included. Fences don't invert the way inline spans do, but the carve-out kept pulling them back in.
sentry.org folds in four notes from its first two live runs elsewhere. Two are traps for anyone reviewing a night by git log: archive-done touches .gitignore on its first run, and a mirror-only project's quiet fires leave no commits at all. The others make property sweeps sanctioned quiet-fire work and split the task audit into a mechanical hourly subset plus a nightly judgment half.
The notes.org template now lints clean, down from four flags in every project on every sweep. Two of those were mechanical, so lint-org --fix anywhere would have rewritten the template and drifted it from canonical.
|
| |
|
|
|
|
|
|
|
|
| |
Overnight hygiene sweep of this repo. Everything here is a finding or a staged proposal. No rule, workflow, script, or bundle file was modified.
The one that matters: the python and typescript language bundles ship no pre-commit hook, so a project installing either gets no credential scan on commit. Both bundles predate the hook rollout that swept go and bash, and install-lang skips missing components without a word, so it went unnoticed for two months. Live on two projects, one of them work. Filed [#A].
Seven more findings landed. The largest is a non-atomic write in the cross-project inbox tool, which can strand an empty handoff in another project's inbox and block a turn there. The rest are lint noise and two gaps in the Signal channel. An eighth was filed and then retracted the same night, once a retest showed I had compared two different files and read the difference as a bug.
Four proposals from other projects are staged under working/ with verified diffs, each behind a VERIFY task, waiting on a decision.
|
| |
|
|
|
|
|
|
|
|
| |
Sentry no longer checks email or messengers. Pass 3 loads only the calendar and PR/ticketing triage plugins. The mail and messenger ones stay out: cmail, Gmail, Telegram, Signal, chat DMs. A manual triage intake still scans everything. The probe follows, so a project whose only declared sources are mail or messengers now skips the pass instead of running it empty.
New pass 11 hunts bugs. It runs linters and static analysis, checks config sanity, and reads one rotating code area per fire so coverage builds over a night. Verified findings get filed as graded bug tasks. It never fixes unattended.
I dropped the suite run the order called for. Running the suite every fire is the per-pass anti-pattern this same file forbids, and the entry baseline already has the result.
The KB personal-project roots now cover ~/.dotfiles, which was classifying Unknown and blocking writes from there.
|
| |
|
|
| |
Moved 5 completed level-2 tasks into Resolved. Logged one review-health followup: a top-level task has gone unreviewed past 30 days.
|
| |
|
|
|
|
|
|
| |
Auto mode is the away-from-desk mode. A sweep worth seeing should reach Craig's phone, not just print into a session he isn't watching. I folded a Phone delivery subsection into canonical triage-intake.org: a full-three-section sweep now pushes to the phone over Signal via agent-text. A pointer from End-of-sweep output and a Living Document note tie it in.
Signal-only, by Craig's ruling: a quiet sweep's "nothing" heartbeat never reaches the phone. Silent-until-signal governs the phone channel too, so it only fires on real signal. The in-session heartbeat stays as proof the loop ran.
Only the send half ships. Reply polling (the retired ntfy design's phone-recv) waits on the reply-correlation follow-up: a Signal reply fans out to every linked device and neither knows which page it answers. That spec owns the recv wiring. I re-pointed the transport off dead ntfy onto agent-text (the renamed pager). The mirror is synced and the DONE task records the deferral.
|
| | |
|
| |
|
|
|
|
| |
Craig's directive from the 2026-07-20 archsetup session: no sentence in a publish artifact carries more than two commas, enforced in the /voice personal pass. The third comma almost always marks stacked clauses or an inline list doing a paragraph's work. It's a mechanical count the walk can enforce where "don't stack clauses" gets skipped.
Scoped to publish artifacts, so the personal-only set goes four to five. Added to the attestation high-recurrence set at birth: a comma count is cheap to receipt, and new discipline fails silently without one. The profile section carries the before/after from the Hyprland issue draft that prompted the rule.
|
| |
|
|
|
|
| |
"page me" and "text me" now name distinct channels: page is the desktop notification, text is the Signal phone push, and "text and page me" fires both. Before, "page me" defaulted to desktop and the phone was an unnamed "on my phone" variant, so you couldn't name the phone without naming the machine.
I renamed the Signal tool agent-page to agent-text to match, with a deprecated agent-page shim delegating to it so callers and other machines don't break before their next install. The dispatch and tests are otherwise unchanged. I rewrote protocols.org "Reaching Craig", page-me.org, and work-the-backlog's away-run logic around the three phrasings, and updated the runbook.
|
| |
|
|
|
|
|
|
| |
The pager worked but was undocumented and drifting stale: signal-cli warned the account had gone 47 days without a receive, and no runbook existed to hand a future session or a non-Claude runtime.
I added the runbook under docs/design/ and a roam-sync-shaped receive timer that drains the queue every 15 minutes, keeping the account warm and surfacing reply messages. I also generalized agent-page: it now sends directly from any machine holding the pager account and relays to velox only when it doesn't. ratio is linked as a device of the account, so a page lands even when velox is down.
The receive script no-ops cleanly where the account isn't registered, since the units stow onto every machine via the shared common package.
|
| |
|
|
| |
Polyglot: case-by-case, no new machinery. The bundle files that auto-install already compose. The only real collision is the hand-pasted coverage-makefile.txt, and clock-panel (the one polyglot project) proves it's benign. Keep the install-lang guard and document the coverage-target namespacing as a manual step (filed as a follow-up). Subprojects: don't promote. N=1 (only home), and a 282-line always-on rule for one project fails the thin-always-on principle. Keep it home-local. Revisit as a thin pointer if a second case appears.
|
| |
|
|
| |
scouting tasks due
|
| |
|
|
| |
Merged the two no-session /schedule tasks (the sentry variant and the unattended inbox check) into one "Unattended /schedule cron contract". They were the same design problem stated for two consumers. Added a foundational "Cross-host agent coordination" task capturing the shared prerequisite behind the roam-conflict task and the two blocked sentry passes: agent-lock is host-local, so nothing coordinates ratio and velox. Cross-linked both dependents to it.
|
| | |
|
| | |
|
| |
|
|
|
|
| |
The general triage plugins (personal Gmail, cmail, calendar, Telegram, GitHub PRs) are template-synced into every project, so the old "plugins present" probe self-activated triage everywhere. The sentry live trial caught it reaching personal inboxes from a project that isn't a triage target. Now a general plugin activates only when the project names its basename in a :TRIAGE_SOURCES: line in notes.org Workflow State. A project-specific plugin stays active by presence. The gate lives in triage-intake Phase 0, so it fixes the interactive over-pull too, and sentry's pass-3 probe reads the same signal.
Presence is capability, the declaration is activation. A project that declares nothing and owns no project plugin pulls nothing. Migration handoffs went to home and work. rulesets correctly declares nothing.
|
| |
|
|
|
|
| |
Auto triage-intake and auto inbox-zero now collapse an empty check to a single "<workflow> at HH:MM: nothing" line, matching the sentry quiet-fire heartbeat from Phase 1. Detection stays in-session, so the MCP-auth sources are scanned in full and only the output collapses. Inbox already had an acknowledge-only-on-empty rule, now unified to the standard format; triage's three-section sweep output gains the empty-sweep collapse.
Completes the silent-until-signal spec (Phases 2-5): the spec is the shared-policy home the three workflows reference, and a manual-testing entry covers the live-loop verification. Spec flipped to IMPLEMENTED.
|
| |
|
|
|
|
| |
A suspend now ends by detaching the tmux client viewing the aiv-<project> session, so the parked session drops out of the alt-space rotation instead of cluttering it. Detach is not teardown: the session and agent process stay alive in the background and only the view disconnects, so it runs inline as the last action (the handoff text is preserved in the pane and shown on re-attach) rather than deferring to a Stop hook the way the session-killing teardown must. Degrades gracefully when not in tmux.
Originated in archsetup as a local stopgap and reconciled to canonical here.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
| |
An in-session monitor loop (sentry, auto triage-intake, auto inbox-zero) fires the model every interval and narrates a full turn even when nothing changed, so a session fills with quiet-fire noise. The spec settles the fix as a policy, not a watcher: detect first, and on an empty check collapse to one labelled heartbeat line, spending a full turn only on a real item. Keeping detection in-session dissolves the MCP-auth split (triage's sources need the session's auth, which a detached watcher can't reach), so it applies uniformly across all three loops. DRAFT, decisions resolved live. Links a [#B] build task.
|
| |
|
|
|
|
| |
research task
Two .emacs.d handoffs. The silent-until-signal monitor pattern (Craig-approved) files as a [#B] spec candidate — it's a cross-workflow shared-asset change across triage-intake, inbox, and sentry, and the sentry live trial just demonstrated the noise problem it solves. The device-location MCP question files as a [#D] research task.
|
| |
|
|
| |
live trial
|
| |
|
|
| |
archsetup routed a Craig-authored suspend.org change (detach the tmux client on every suspend, so a parked session leaves the alt-space rotation). It's a synced shared asset, so it parks for approval rather than landing unattended: reviewed as clean and low-risk, filed as a [#C] task with the exact diff preserved in the processed handoff, replied to archsetup. Applies to canonical on Craig's go.
|
| |
|
|
| |
The autonomous-batch spec's three source artifacts (the Phase E proposal, its diff, the sender note) moved from working/inbox-zero-phase-e/ into docs/design/ under dated names, with the spec's inbound links repointed. The spec is IMPLEMENTED, so the working dir was a filing candidate. Also removed the spent working/sentry-2026-07-19-working-files-ruling/ staging dir, whose proposal shipped in the working/-tracked-from-creation change. working/ is now empty and gone.
|
| |
|
|
| |
Three pointed at artifacts that were folded in or processed away (a spec-review file merged into wrapup-routing-spec, a removed pearl inbox note, a home-side subprojects log with no rulesets file) — delinked to plain text so the reference survives without a dead link. The fourth repoints the autonomous-batch spec at inbox.org, since inbox-zero.org was renamed in the consolidation. Surfaced by the sentry link-integrity pass.
|
| |
|
|
| |
The sentry live trial surfaced that triage-intake self-activates in every project. The general personal-account plugins are template-synced everywhere, so its probe reads present-everywhere as active-everywhere. The spec captures the fix: general plugins gate on a per-project :TRIAGE_SOURCES: declaration, project-specific plugins stay active by presence, and the activation layer lives in triage-intake Phase 0 so it fixes interactive runs too. DRAFT, pending review. Links a [#B] build task.
|
| |
|
|
|
|
|
|
|
|
| |
working/ is the tracked home of in-progress work, version-controlled from creation rather than staged locally until it graduates. Filing on completion reorganizes durable artifacts into permanent homes. It doesn't mark when they became durable. Ephemeral, disposable artifacts go in a gitignored temp/ (or /tmp), never working/.
install-ai.sh emits a temp/ ignore in both track and gitignore modes. Ephemerality is independent of whether a project tracks its .ai/ tooling, so temp/ rides neither the track .gitkeep step nor the gitignore-only tooling block. working/ is never ignored, on purpose. sweep-gitignore-tooling.sh backfills temp/ as a separate mode-independent pass, not an IGNORE_SET member: folding it into that set would skip every track-mode project, the set that most needs it.
While implementing I confirmed the canonical machinery never ignored working/ (the tooling set is only .ai/ .claude/ CLAUDE.md AGENTS.md), so a project that ignored working/ did so as a local deviation.
Documents the convention in working-files.md and mirrors it in protocols.org. 7 new bats cover temp/ in both modes, never working/, and idempotency.
|
| |
|
|
|
|
| |
trial
.emacs.d routed three sentry-workflow design ideas from its own hand-run trial (codebase-gated bug/enhancement logging, a system-health pass, a sibling-machine freshness pass). Filed as a [#C] backlog task rather than applied — they're design input for the sentry Living Document refinements and two of them hinge on an unresolved cross-driver coordination question. Replied to the sender.
|
| |
|
|
|
|
| |
Home's colloquialisms + "the list" before-close-queue handoff was already wired canonically before it arrived (protocols.org Colloquialisms section + wrap-it-up Before-Close Queue drain step); replied to confirm, filed.
The .emacs.d working/ tracked-from-creation ruling is a shared-asset + convention change carrying a temp/-placement design decision, so it parks rather than applying unattended: staged proposal under working/, filed a [#B] VERIFY, replied to .emacs.d with the two findings (canonical never ignored working/; temp/ needs a both-modes ignore call).
|
| |
|
|
| |
Move the three finished tasks into Resolved: the bin/ai characterization-and-refactor hardening, the inbox-boundary Stop hook, and the before-close-queue convention.
|
| |
|
|
| |
Both built, tested, and pushed this session: the task-boundary inbox Stop hook (soft-nudge) and the 'the list' before-close queue plus colloquialisms convention.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
convention
Home proposed two linked cross-project norms and Craig approved rolling them out. Both now ship in the template so every project inherits them.
A new "Colloquialisms and Expansions" section in protocols.org maps Craig's shorthand to a defined action the agent applies without asking. Two seed entries: "put X on the list" appends to a session-scoped Before-Close Queue, and "tell <project> <message>" drops the message in that project's inbox via inbox-send. The set is extensible.
The queue lives under a "* Before-Close Queue" heading in the session anchor, so it resets when the anchor is archived at wrap. Anything that must outlive the session stays a todo.org task. wrap-it-up Step 1 gets a sub-step that works the queue oldest-first before the Summary, so any resulting edits ride the wrap commit, with unfinished items surfaced in the valediction rather than dropped.
I settled three design calls. The reference lives in protocols.org rather than a per-project notes.org (home's local reference), since a synced section is what makes it a shared norm. The queue lives in the session anchor, as home did. The wrap step sits at the front of Step 1 rather than a new half-step, which keeps the "Steps 1 through 5" framing intact. A documentation-integrity bats guards the wiring and the before-the-Summary ordering against a future edit or sync dropping it.
|
| |
|
|
|
|
|
|
| |
The "check inbox/ at every task boundary" rule was prose-only in protocols.org, so it held only as well as the agent remembered it and a handoff could pass a turn unseen. inbox-boundary-check.sh is a Stop hook that backs the rule: when inbox-status -q reports pending items it blocks the yield once and injects the count, so the agent processes them before returning.
It soft-nudges rather than hard-blocks. On the harness re-entry (stop_hook_active: true) the hook steps aside and lets the turn end, so a mid-task pause to ask a question, or an item the agent genuinely can't process, never wedges the session. A hard block would instead push inbox processing ahead of that clarifying question.
The hook self-skips where it doesn't apply: no inbox/ dir, no inbox-status, or a clean inbox each exit 0 silently, so one global hook covers every project with no config. It prefers the project-local .ai/scripts/inbox-status and falls back to one on PATH. It's wired into the Stop array ahead of ai-wrap-teardown in both the tracked settings.json (which the live ~/.claude/settings.json symlinks to) and the documented snippet. bats covers pending, clean, the re-entry step-aside, no-inbox, and the absent-status degrade.
|
| |
|
|
| |
Netted the 17 uncovered functions (launcher tests 9 to 42), extracted four pure decision cores with Normal/Boundary/Error sets, and dispositioned the footgun audit plus refactor pass. shellcheck clean, shfmt consistent, suite green before and after.
|