| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
commits.md was 12,800 tokens, larger than the next four rules combined, and it loaded in every session in every project whether or not anything was being published. Most of it is procedure that only applies when a commit or PR is in play.
I split it by blast radius rather than by size. What stays always-loaded is what must hold whether or not I'm publishing, and where a violation is permanent and reaches other people: author identity, the no-AI-attribution ban, the generated-document byline rule, and the public-artifact content-scope rules. That core is 1,027 words, about 2,342 tokens.
What moved into the publish skill is everything about how a message gets written, reviewed, approved, and published. The pre-flight reconcile, the code-review gate, the draft and voice and approval gate, conventional-commit format, Voice and Focus, PR description structure, the three review shapes, merge strategy, and the pre-commit checklist.
The failure modes are why the line falls there. If the skill doesn't load I don't know the publish flow and have to be told, which is visible and recoverable. I don't silently commit with AI attribution, because that guard never moved. Only the recoverable half is on the skill-triggering bet.
I verified the split by using it. The skill registered mid-session and I invoked it to publish this commit, and it loaded with the flow intact.
Content is conserved: 5,561 words in, 5,898 across both files, the difference being the frontmatter and the pointer I added to the core. I repointed five cross-references in voice, review-code, inbox.org, and no-approvals.org that named sections which moved.
One thing I left alone. The skill is a single 4,871-word file, and both posts argue a long skill should split internally rather than sit as one blob. It loads on demand now, which is the win worth taking today. Splitting it further is its own change.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
I had the goal backwards in the lead. Craig's framing is output quality first, with token reduction real but second, and where they conflict quality wins. Anthropic's 80% was a finding rather than a target, and aiming at it directly optimizes the thing we don't care about. P4 falls to that and is dropped: lowering effort buys tokens by spending quality. P5 rises for the same reason, since positive framing over prohibition is what actually targets guardrails working against output.
My token figures were low by about 45%. I converted word counts at a guessed ratio when /context reports real per-file numbers, so I used an estimate because it was easier to compute from inside the repo. The live ratio is 2.28 tokens per word. commits.md is 12,800 tokens rather than the 7,000 I estimated, and claude-rules was near 57,800 per session before today.
I also conflated two loading paths. Memory files come in through the harness at session start. protocols.org and the workflows are read by startup and land in Messages, so they never appear under Memory files at all. They shrink by editing the workflow, not by scoping a rule, and treating them as one surface made protocols.org look like it competed with commits.md for the same fix.
Path-scoping is confirmed working at user level, and the de-duplication holds. That splits the remaining work: anything scopable to a file type or directory ships with no trial, because a glob match is deterministic. Only the semantic rules need the skills route and the stop conditions, and commits.md is the one that matters there at 12,800 tokens of publish machinery that only applies when a commit is in play.
I recorded one caution the confirmation doesn't cover. Path-scoping fires when a matching file is read, so creating a new org file from scratch never triggers todo-format.md. Edits are safe because Edit requires a prior read.
I also wrote up the day's two guard failures, both mine. wrap-org-table reflowed a table into a worse shape and lint-org certified it clean, and the teardown hook consumed a stale sentinel and killed a live work session. The plan leans on mechanical detectors because they have no stake, which is still right, but a detector can be confidently wrong and a green check from a guard that never looked is indistinguishable from one that did.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
wrap-it-up drops /tmp/ai-wrap-teardown-<project> to ask the Stop hook to kill the tmux session once the wrap certifies clean. When certification fails the Stop hook blocks and leaves the sentinel armed, which I did on purpose so a wrap blocked by a dirty tree can retry on a later stop without re-running the workflow.
I never bounded that retry to the session. An uncertified sentinel sat armed indefinitely and fired in whatever session next reached a clean tree. work's 11:37 wrap today left one armed. The 13:20 session ran startup, committed the task filing and the template sync, went clean, and the next stop consumed the two-hour-old sentinel and killed the terminal mid-work. Every stop before those commits had been blocked by the same sentinel failing certification, so the session spent its whole life either blocked or dead. archsetup's had been armed since Saturday on a live attached terminal, and home's was armed and waiting.
session-start-disarm.sh clears the project's sentinels at SessionStart. A new session means the wrap that armed one is gone, so its pending teardown is meaningless. Within-session retry is untouched, since the hook only runs at session start, and a test pins that. If teardown is still wanted, wrap-it-up re-arms it.
I disarmed the three live ones by hand before writing this, backed up under /tmp/disarmed-sentinels.
Four tests cover the disarm, one pins the retry behavior I did not want to lose. The scoping test matters most: a concurrent session in another project keeps its own sentinel.
|
| |
|
|
|
|
|
|
|
|
| |
I wrote three working documents while reviewing the Claude 5 context-engineering post, the Opus 5 prompting guide, and the Fable field guide against what this repo ships downstream.
In proposals.org I measured the always-loaded surface at 32,123 words and ranked six changes, plus two places where a post contradicts something we arrived at deliberately. I also reread the rules as your prompts rather than as agent context, which is where the sharper finding is: 41 execution and hygiene workflows against 6 discovery and design ones, on a system whose bottleneck has moved.
In rollout.org I phased the work and named the seven decisions that gate it. My lead finding is that the harness system prompt already carries most of what the Opus 5 guide recommends adding, so the posts' value here is subtractive. Applying them additively would make the duplication worse.
In metrics.org I split the posts into separable claims and marked which are testable here and which are judgment calls, rather than inventing a metric for the ones an eval harness would be needed to settle. I also stated the pilot's stop conditions in advance, including a zero-tolerance threshold on the load-bearing rules, so I can't renegotiate that threshold later under pressure to make a phase succeed.
|
| |
|
|
|
|
|
|
|
|
| |
Generic rules install once at ~/.claude/rules/ and load in every session on the machine. The language bundles copied all twenty into each project as well, so work and .emacs.d loaded them twice. Project rules outrank user-level ones, which makes it worse than waste. A stale project copy overrides the fresh global rule until the next startup heals it, and that is what happened to work's interaction.md this morning for the hours between the commit and its next session.
I stopped install-lang copying them. sync-language-bundle now sweeps the copies earlier installs left, but only where the global rule exists to take over. A machine that hasn't run make install keeps the only copy it has. I swept 20 files each from work and .emacs.d, leaving their language rules and work's publishing overlay untouched.
I updated three existing tests that encoded the old contract. The generic-rule drift test is the interesting one: I made a drifted copy get swept rather than repaired, which is the stronger fix, because that copy outranked the global rule for as long as it existed.
I also gitignored the live session anchor. This repo tracks .ai/, so the anchor read as untracked for a whole session. git-worktree-gate reported rulesets sync-blocked, and every other project skipped its rulesets pull until wrap. The anchor is ephemeral and gets archived under a different name, so nothing needs it tracked.
|
| |
|
|
|
|
|
|
|
|
| |
Three rules already declared a narrow scope. todo-format and org-tables name org files, emacs names elisp. But they declared it in an "Applies to:" line, which is prose. Claude Code scopes a rule by a paths field in YAML frontmatter. None of them had one, so all three loaded into every session in every project regardless of what their own first line said. That's 5,896 words of a 25,386-word rules surface, resident whether or not the session ever opened an org or elisp file.
They now carry the frontmatter. The prose line stays, because it's what a human reads. The frontmatter is what the loader reads. Keeping both means they can disagree, so lint.sh now warns when a rule names a concrete extension in prose without matching frontmatter. That check flags exactly these three and nothing else.
The heading check needed teaching too. It read line 1 and expected a Markdown heading, which frontmatter displaces. It now skips a leading frontmatter block and the blank line after it. A file with no heading and no frontmatter still warns.
I haven't confirmed that paths frontmatter applies to user-level rules rather than project-level ones only. The docs describe it as a property of rules files without drawing that distinction. If it turns out to be project-only the frontmatter is inert and the rules load as before, so the downside is nothing. I'll check with /context next session.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
I added a Collaborative Peer Reasoning section to the interaction rules. It governs how an interpretation forms before any rule about presenting choices: infer first and clarify only at material forks, test a conclusion against its strongest alternative, let a correction update the downstream model instead of just the wording. The file's framing line widened to match.
Two probes were failing silently. The startup KB nudge looked up the best-practices node by grepping file content for its slug. A roam node's slug lives in its filename, so the lookup always returned empty. The nudge pointed at nothing in every project and every session, for as long as it shipped. It matches the filename now, through find rather than a glob so zsh doesn't abort on no match.
The browser rule told agents to open URLs with a form ending in &>/dev/null &. That discards the "Opening in existing browser session." line confirming the tab opened. Warm and cold start now split: foreground and read the confirmation when Chrome is already up, detach only when it isn't. The confirmation is on stdout, verified rather than assumed.
I filed two tasks from handoffs. The sentry triage split needs a work-vs-personal classification mechanism before its wording can move, because the current rule excludes by category and category can't express that split. The publish-lock design is approved but carries three open gaps. The load-bearing one is a lock held across an unbounded human approval pause.
I also swept the old processed handoffs out of inbox/. History keeps them.
|
| |
|
|
| |
Centralize repository-state checks, bind teardown to a certified clean HEAD, and allow inbox-only refreshes. Guard installed symlinks from cross-project writes and add regression coverage.
|
| |
|
|
| |
Clarify that speedrunnable means the solo autonomy tag; quick remains only an effort hint.
|
| |
|
|
|
|
| |
Archives the fixed lint-org bug into Resolved and records seven review
stamps from the day's cycle. The lint sweep's deferred judgments ride
along in the follow-ups file.
|
| |
|
|
|
|
|
|
| |
org-lint's invalid-block checker flags both delimiters of a paired example or src block whose body holds a heading-shaped line. Its parser reads the `** ` as a structural break and loses the open block. Every org file that documents org syntax inside a block collects two false findings.
The checker is org-lint's own, not one lint-org implements, so I filtered its output instead of patching a local checker. `lo--matched-block-regions` pairs blocks by scanning lines under org's real rule (once open, only the block's own `#+end_TYPE` closes it). A finding inside a matched region gets dropped, delimiters included, since that's where org-lint reports. I scanned lines rather than asking org because org's parser is what's confused.
An unterminated block never lands in a matched region, so it still reports. Three tests cover the false positives: a heading in an example block, a literal `#+end_example` inside a src block, and uppercase delimiters. Two more guard the real finding, including a file with one paired and one unterminated block that proves the suppression is per-block.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|