| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
Phase 3 of the sentry supervisor: reconcile the existing roam writers and wrap-up so sentry's locks actually guard something, and its shutdown has one enforced entry point.
The roam-write lock only helps if every roam writer takes it, so both writers now do. knowledge-base.md's write recipe and inbox.org core §5 acquire the roam-write lock around their edit and trigger roam-sync instead of committing themselves. That closes a gap the one-git-owner rule already implied but the KB recipe still violated: the recipe told agents to run git add -A && commit && push against a tree that's chronically dirty from live captures, which could sweep an in-flight capture into a stray commit. roam-sync stays the roam repo's only committer. Agents edit-plus-trigger under the lock, and roam-sync.sh's header now states that contract instead of the old "agents commit inline" note.
Both writers degrade as the spec settled: an absent agent-lock proceeds unlocked (today's behavior), and only a present helper reporting the lock busy after its bounded wait defers or surfaces.
wrap-it-up.org gains a Step 0 that refuses while sentry is live. It checks the single-runner lock and points at "stop sentry" rather than archiving the anchor and tearing down the buffer under a still-firing loop. Both files derive the lock name the same way (sentry-<repo-basename>), so the guard and the engine agree. triage-intake.org notes that it also runs as sentry's triage pass under the no-approvals contract, with its trigger phrases unchanged.
|
| |
|
|
|
|
| |
Both helpers treated any pipe-led line as a table row, so ASCII art in an example block got mangled into a bordered table (a work file took a 1949-line reformat on 2026-07-09). The scanners now track the open block's type and skip its content. Only the matching end marker closes a block, so a literal end_src quoted inside an example block can't re-expose it.
The deeper cause was wrap-org-table's load-time dispatch: it fired when lint-org merely required the library, running the reformatter over files lint-org was only asked to report on. It now dispatches only when named as the entry script. lint-org's CLI is also report-only by default now. Writes require --fix, and the wrap-up workflow and lint command pass it.
|
| |
|
|
|
|
|
|
|
|
| |
Every org document an agent writes carried `#+AUTHOR: Craig Jennings & Claude`. No template stamps that line. Agents copy it from a neighboring file, so one stray header propagates through everything generated afterward.
My own repos tolerate the co-author line. Employers whose policy is that work product carries employee names alone do not. An `#+AUTHOR:` line survives conversion into docx, a wiki page, or a PDF that reaches a customer.
I rewrote the header to `Craig Jennings` across the workflows, templates, specs, and design docs. The rule now lives in commits.md, so the next generated document starts correct rather than inheriting the mistake.
Archived session logs keep their original headers as a record of what happened. The two Codex-authored design docs keep their byline, because Codex wrote them and relabeling would be a false attribution rather than the removal of one.
|
| |
|
|
|
|
|
|
|
|
| |
This closes the build half of the wrap-up routing spec: Phases 2 and 4 here, with the engine and discovery already shipped.
inbox.org's "File as TODO" disposition now runs route_recommend on each keeper and stamps :ROUTE_CANDIDATE: <destination> on strong and weak matches, so the wrap-up router has a candidate set without ever scanning the standing backlog. wrap-it-up.org Step 3 gains the optional router after the inbox sanity check, with the gate-vs-optional split named in the prose: surface the batch with destinations and confidence labels, then go or skip. An empty set stays silent.
The go path is mechanical rather than prose-driven: the new route-batch helper lists candidates read-only, and on go extracts each subtree (children ride along, markers stripped, headings promoted), delivers it via inbox-send for provenance, and removes the local copy only after a successful send, rewriting todo.org per send so a crash never strands an already-sent task locally. Overlapping candidate spans (a tagged child inside a tagged parent) are a loud conflict, left in place with a non-zero exit, because routing either span would silently take the other along.
A 13-test bats suite covers list/backlog exclusion, empty-set silence, delivery with provenance and children, promotion, drawer pruning, the no-todo.org destination, failed-send recovery with the marker intact, the nested-candidate conflict, and duplicate-marker dedupe. cross-project.md notes the router as a sanctioned cross-project write path.
|
| |
|
|
|
|
|
|
| |
Rewrites every level-3+ DONE/CANCELLED/FAILED heading into a dated event-log entry from its CLOSED cookie, enforcing the todo-format depth rule that interactive closes and --archive-done (level-2 only) leave unapplied. A new lint-org checker (subtask-done-not-dated) flags stragglers, and the clean-todo, wrap-up, open-tasks, and task-review workflows now run the converter before archiving.
Removing the CLOSED cookie keeps a DEADLINE or SCHEDULED cookie that shares its planning line, rather than dropping the whole line.
From the .emacs.d handoff (2026-07-01 convert-subtasks bundle).
|
| |
|
|
|
|
| |
The wrap-up valediction now always ends with "session wrapped." on its own line — a consistent, unmistakable end-of-session marker, since it's the last user-facing output before Step 6's silent teardown. Craig's request via the roam inbox.
Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
|
| |
|
|
|
|
|
|
|
|
| |
The roam repo's working tree is dirty most of the time (Craig captures into it constantly, and roam-sync only commits every 15 minutes), so roam mode's pull --ff-only failed on nearly every run and blocked triage. The auto inbox zero loop hit it every cycle.
Roam mode now never pulls. The scan reads the working-tree file directly, since that's already the latest local state, and the rare write removes the claimed items in place and then triggers roam-sync to commit and push. roam-sync already commits-first-then-rebases, so it handles the dirty tree, and the ownership partition (only this project touches its own prefixed lines) means its rebase can't conflict on the edit.
Trade-off: the roam-repo commit carries roam-sync's generic auto-sync message instead of a descriptive one. The provenance for routed tasks lives in the project's todo.org and session log anyway.
Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
|
| |
|
|
|
|
|
|
|
|
|
|
| |
A bare "wrap it up" now tears the session down after the valediction: it kills the ai-term buffer and the aiv-<project> tmux session (which takes claude with it) and restores geometry. "wrap it up with summary" or "and summarize" keeps the buffer. "wrap it up and shutdown" gates on this being the only live ai-term session, then powers the machine off through an abort-able Emacs countdown.
Teardown can't run inline because it kills the session claude runs in, so the valediction would never flush. Step 6 instead drops a basename-keyed sentinel after commit+push is verified, and a new Stop hook (ai-wrap-teardown.sh) does the teardown when the response ends, by which point the valediction has rendered. The hook is a no-op on every normal stop because the sentinel only exists after a teardown wrap.
The runtime lives in .emacs.d/modules/ai-term.el (cj/ai-term-quit, cj/ai-term-live-count, cj/ai-term-shutdown-countdown), and the rulesets side calls it via emacsclient. I routed that companion to .emacs.d, so the feature is end-to-end once it lands. The hook has 8 bats tests. The live teardown and shutdown paths are a manual checklist in todo.org.
Built from the proposal. I went with both summary qualifiers, the Emacs-timer countdown, and the live-count gate.
Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
|
| |
|
|
|
|
|
|
|
|
|
|
| |
I merged process-inbox, monitor-inbox, and inbox-zero into one inbox.org engine. A shared core (value gate, skeptical review, disposition ladder, reply discipline, capture-guard, priority-scheme check) holds the logic that used to be duplicated and cross-referenced across the three files. Each mode (process, monitor, roam) references the core by name instead of restating it.
Every trigger phrase still works, now routing to a mode, so there's nothing to relearn. I added the interactive auto inbox zero mode: ask for an interval, run roam mode on /loop, acknowledge-only on an empty cycle, surface a find to a queue gated on a yes. The fully-unattended /schedule pass stays vNext, tracked separately.
I repointed every live caller (INDEX, protocols, startup Phase C, wrap-up Step 3, triage-intake, broadcast) at inbox.org and its modes, then deleted the three old files. triage-intake and no-approvals stay separate by design. The value gate, dispositions, capture-guard, and reply discipline all behave as before.
Built from the Ready spec. Workflow-integrity and sync-check pass on both the canonical and mirror trees, the stale-reference grep is clean, and the full suite is green.
Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
|
| |
|
|
| |
Recent session receipts read "promoted 0 / consulted no" across the board: the wrap-up KB-promotion check existed but fired too late, and nothing surfaced existing lessons to read. This adds the spec's four light prompts plus the read-side step it was missing. Startup gets two Phase C nudges (gated on the roam clone): a consult line listing project-relevant node titles, and a contribute line pointing at the best-practices node. Triage-intake and inbox-zero get a conditional end-of-flow capture reminder that fires only on real signal. Wrap-up gets an early reflection prompt at the top of Step 1 that feeds the existing receipt, so learnings are captured while fresh instead of reconstructed after the Summary. Ratifies the spec's five decisions and adds D6 (the read-side surfacing).
|
| |
|
|
|
|
| |
A helper agent's session-context file is .ai/session-context.d/<id>.org. A bare, reused id like "codex" makes the next run resolve to the previous run's leftover anchor, which it then mistakes for a crash to recover or clobbers. That bit on 2026-06-13: a codex run left codex.org for the next session to clean up.
The fix is a convention, not a resolver change. The spawner appends an epoch on the tail (host.project.runtime.<epoch>) so each run gets a fresh anchor. The epoch can't be minted inside session-context-path, since that resolver runs many times per session and must return the same path each call. I documented it in protocols.org, the wrap-up recommended-shape note, and the resolver header.
|
| |
|
|
|
|
|
|
| |
The global roam inbox (~/org/roam/inbox.org) is one shared capture file every project can see, and nothing routed its items to the project that owns them. inbox-zero claims the items prefixed for the current project, files them into that project's todo.org per the process-inbox discipline, and removes them from the shared inbox. Foreign-prefixed and unowned items stay. Every scan reports the total item count plus how many appear related to this project.
This v1 is single-destination: it routes by explicit <project>: prefix only. The domain-aware mode that would guess every item's owner and empty the whole inbox in one run is deferred until the multi-project need is concrete.
Wired into both session ends so each project touches the inbox twice a session: startup surfaces a read-only count and offer, wrap-up Step 3 sweeps the claimed set before the cleanup scripts so imported tasks ride the wrap commit. INDEX carries the trigger phrases.
|
| |
|
|
| |
Phase 3 of the agent KB spec. Step 1 of wrap-it-up gains a promotion check against knowledge-base.md's inclusion criteria, and every Summary now ends with a "KB: promoted N / consulted yes-no" line — the single grep-able input to the spec's 30-day success-metrics checkpoint. The validation checklist enforces the line.
|
| |
|
|
|
|
|
|
| |
Phase A's startup rsync copies template updates from rulesets into each project's .ai/, but nothing committed that churn, so it accumulated across sessions and eventually blocked Phase A.0's auto-fast-forward (git won't ff a dirty tree). Two projects hit it the same day.
I added a Step 4.0 to wrap-it-up.org that commits the churn as its own chore commit before the session-work commit, guarded so it only auto-commits synced .ai paths matching rulesets canonical byte-for-byte and surfaces anything that doesn't. startup.org Phase C now surfaces leftover churn at session start as the crashed-session safety net. Both skip the rulesets repo, where .ai/ is a committed mirror.
I also moved four misplaced PROPERTIES drawers in todo.org (DONE tasks) from after the resolution prose to immediately under the CLOSED line, so org parses them as real drawers.
|
| |
|
|
|
|
| |
A single .ai/session-context.org races when two agents share a project: each agent's writes clobber the other's session log. I added .ai/scripts/session-context-path, which resolves the active path from AI_AGENT_ID: unset gives the legacy .ai/session-context.org singleton (so every existing one-agent session is unchanged), set gives .ai/session-context.d/<id>.org with the id sanitized to filename-safe characters. This is Codex's Phase 1 slice from the runtime-neutral spec: the race fix on its own, no broader refactor.
startup.org's existence check and wrap-it-up.org's rename now resolve through the helper, each with a singleton fallback so older checkouts that haven't synced the script still work. Wrap folds the agent id into the archive name so two agents wrapping in the same minute don't collide. protocols.org documents the rule. Verified with 5 bats cases and a two-agent simulation showing distinct paths per id.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The inbox sanity check I added in 8424e8f counted lint-followups.org
as unprocessed, which surfaced as a false alarm during this session's
wrap-up. lint-org writes its judgment items into inbox/lint-followups.org
earlier in the same wrap-up workflow by design. The file is a
pipeline artifact for the next morning's daily-prep, not a handoff
that needs the value gate.
The find filter now excludes .gitkeep, lint-followups.org, and
PROCESSED-* prefixes. The Validation Checklist line names the same
expected-artifacts list explicitly.
Smoke test: post-fix count is 0 in the rulesets project (where
lint-org just wrote 5 judgment items into inbox/lint-followups.org).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Wrap-up never knew about the inbox. After process-inbox.org landed
today as the formal workflow for handoff intake, wrap-it-up.org
needs to surface inbox/ when it's non-empty so the wrap doesn't
silently defer handoffs to next session.
This commit adds a new Inbox sanity check sub-step under Step 3
(project hygiene). The check runs find inbox -maxdepth 1 -type f
filtered to skip .gitkeep and PROCESSED-* prefixes. A non-zero
count surfaces with the file list and a recommendation to run
process-inbox.org or explicitly defer each item. A zero count or no
inbox/ directory makes the check a silent no-op.
It also adds one line to the Validation Checklist: inbox is empty
(excluding .gitkeep and PROCESSED-* prefixes), OR each remaining
item has an explicit deferral logged in the valediction.
This is the only integration gap surfaced today. The other gaps
considered (LAST_INBOX_PROCESS marker stamp, sync-check, make
status) didn't justify wrap-up changes. The marker is
process-inbox's own responsibility. sync-check is project-specific
to rulesets. make status doesn't generalize across projects.
|
| |
|
|
|
|
| |
Step 3.5's Linear ticket-state sweep uses gh to find the merged PR for a Dev-Review ticket, which assumes a GitHub-family host. That holds today because DeepSat, the only Linear-using project, lives on GHE where gh talks to the API.
I added a note flagging the assumption rather than rewriting the step to be provider-agnostic. A future Linear project on GitLab, Gitea, or Bitbucket would need a different PR lookup, but none exists yet, so documenting the boundary beats building for a host we don't have.
|
| |
|
|
|
|
|
|
| |
The date-coverage scan flagged every open [#A]/[#B] task with no DEADLINE or SCHEDULED, on the assumption that high-priority work needs a date. That assumption is wrong (research and watch-list tasks are legitimately dateless), so the scan generated dismiss-or-paper-over cleanup at every wrap-up.
The replacement watches the daily task-review habit instead. It calls task-review-staleness.sh todo.org 30 and, when the count is non-zero, writes one summary line to the follow-ups file: N top-level tasks unreviewed for >30 days. There's no per-task dump, because the per-task walk is the review habit's job. Staleness, not datelessness, is the signal worth surfacing.
The change lands in both the canonical workflow and the project mirror.
|
| |
|
|
|
|
|
|
|
|
| |
Project .ai/ mirror catches up to two canonical updates already in claude-templates/:
- lint-org cj-comment block suppression (3fb4c80). The =#+begin_src cj: ...= annotation pattern triggered three lint categories (suspicious-language, empty-header-argument, wrong-header-argument) as false positives at todo.org:16 and todo.org:1291. lint-org.el now recognizes the opener and skips all three on those lines.
- LINT_ORG_FOLLOWUPS default flipped to =./inbox/lint-followups.org= (684891d). The previous hardcoded default routed every project's wrap-up findings into the work project's inbox.
Phase A startup rsync brought both into the project mirror this morning; bundled into one chore commit since neither delta is project-specific work.
|
| |
|
|
|
|
| |
The Step 4 "Push to all remotes" parenthetical singled out "github.com + cjennings.net mirrors" as the canonical case. Accurate for rulesets and a few other repos, misleading for the rest. Most projects have git.cjennings.net as their sole remote, and DeepSat lives on deepsat.ghe.com. The push loop itself (for r in $(git remote)) is already remote-agnostic; the prose just needed to catch up.
New wording covers both the mirror case and the different-audience-per-remote case without naming any specific host.
|
| |
|
|
|
|
|
|
|
|
| |
New sub-step under Step 3 surfaces [#A] and [#B] tasks in todo.org that have neither DEADLINE: nor SCHEDULED: directly under the heading. Candidates land in the same lint-followups.org the next morning's daily-prep merges in, so the operator reviews them at the start of the day instead of discovering the drift later.
Why both timestamp shapes matter: DEADLINE is external (RFP cutoffs, partner-announced dates, regulatory). SCHEDULED is social (a commitment to surface to the team). The asymmetry drives the promotion rule — DEADLINE inside 7 days auto-promotes to [#A], SCHEDULED passing surfaces for re-eval without auto-promoting. High-priority work carrying neither is suspicious; the scan flags it, the operator decides whether to add a date, drop the priority, or confirm no-date-by-intent.
Inline awk does the scan (no new script). Output appends to the follow-ups file under a dated heading; if no candidates, no append. Conservative: surfaces every candidate, expects false positives to be cheap dismissals.
Counterpart to the DEADLINE-vs-SCHEDULED practice section just added to todo.org's '* Work Priority' header on the work side.
|
| |
|
|
|
|
|
| |
Byte-identical pull of .ai/scripts/lint-org.el,
.ai/scripts/tests/test-lint-org.el, and the new Step 3 lint section in
.ai/workflows/wrap-it-up.org. Upstream: claude-templates 138f35f (feat)
and 4eba98c (docs).
|
| |
|
|
|
|
|
|
|
|
| |
When a parent task in todo.org gets reprioritized, its children frequently keep their original (lower) priority cookies, which then mismatches the parent's new importance. The new mode walks every heading with a priority cookie and bumps any direct child whose own cookie is lower (D ranks below A in org's default scheme). Down-only: parents are never bumped up to a child's priority. Priority-less parents and priority-less children are both left alone — sync does not invent priorities.
Children opt out by carrying the :no-sync: literal tag, useful for Follow-up:/Spike: sub-tasks that are deliberately deprioritized. The tag match is literal regex against the heading line rather than going through org-get-tags, because org's default tag character class excludes hyphens — :no-sync: would not be parsed as a real tag in batch mode without a custom org-tag-re.
org-map-entries visits headings in document order, so a multi-level chain [#A] → [#B] → [#D] collapses to the top priority in one pass: the middle bumps to [#A] before the walk reaches the leaf.
wrap-it-up.org Step 3 now invokes --sync-child-priority after --archive-done. --check-child-priority is the report-only alias (--sync-child-priority --check) for previewing before applying. Default cadence is auto-apply, same as --archive-done.
|
| |
|
|
| |
New on-demand triage-intake workflow. It scans every inbox source (the three mail accounts, Slack, Linear, open PRs, both calendars, recent todo.org edits), surfaces what moved, runs the Linear Dev-Review sweep, and marks all unread INBOX mail plus every touched Slack conversation read. Also registered in INDEX.org, and the stale triage-intake reference dropped from wrap-it-up.org.
|
| |
|
|
| |
The wrap-up flow already runs the hygiene pass on todo.org; it now also runs --archive-done, which relocates completed level-2 subtrees from "Open Work" to "Resolved". Both passes are idempotent and skip cleanly when the file lacks the named sections, and any moves land in the wrap-up commit's diff for review before push.
|
| |
|
|
| |
Replace the old "intentional carryover" default in wrap-it-up.org. End every session with an empty `git status`: classify each leftover as a runtime artifact, a forgotten change, or pre-existing dirt, apply a concrete resolution unless the user explicitly defers, and log any deferral in the valediction so the next session knows it was a choice, not a miss.
|
| |
|
|
| |
Sweep Dev-Review tickets assigned to Craig before the wrap-up commit. Any whose linked PR has merged gets proposed for Done (chores, refactors, test backfills, dead-code removal) or PM Acceptance (real fixes or features users can verify). Tickets stuck in Dev Review after the PR merges hide real in-progress work. The step is idempotent and skips when Linear is not in use.
|
| |
|
|
|
|
|
|
| |
I deleted humanizer/SKILL.md now that all three callers (commits.md, respond-to-cj-comments.md, start-work.md) invoke /voice instead. The 25 humanizer patterns live on as patterns 1-25 in voice/SKILL.md. Same source (Wikipedia's Signs of AI writing), same prose, same examples — just renumbered alongside the universal good-writing additions and the personal-only patterns.
I also updated .ai/notes.org and .ai/workflows/wrap-it-up.org to reference /voice personal instead of the old humanizer + manual-passes flow. The wrap-it-up change landed upstream in claude-templates first so it survives the next startup rsync.
todo.org gets the matching update: the voice TODO is marked DONE with a "Built and shipped" timestamp, the publish-mode terminology is renamed to personal-mode throughout, the V1 scope checklist is ticked, the open questions are resolved with the answers we landed on during implementation, and the migration section records the delete-not-alias decision.
|
|
|
Replace the seed notes.org with project-specific context (layout, install modes, task tracker location, recent inflection point). Bring in the synced template surfaces (protocols, workflows, scripts, references, retrospectives, someday-maybe) as tracked content for this content/documentation project.
|