| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Both workflows now check that the file under review (or the spec
being responded to) ends with -spec.org before proceeding. If it does
not, the workflow stops and surfaces the mismatch with the rename
suggestion.
The suffix is the identifier per Craig's spec-naming convention:
every design, decision, or planning document under a project's docs/
directory ends with -spec.org. The .org extension alone is not enough
because docs/ holds non-spec org files too (tutorials, frozen
inventories, reference material).
spec-review.org gained a top-level Precondition section between When
to Use and Approach. spec-response.org gained the same Precondition
section in the parallel position, with a note that the review-file
convention <spec-basename>-review.org means a misnamed spec produces
a mis-pointed review file too.
Inbox source: 2026-05-28-0858-from-home-spec-naming-convention-apply-to-spec.org.
Home renamed two docs to the new convention and asked rulesets to
update the template workflows so the next startup rsync in every
project picks up the guard.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
helper
Three coupled additions ship together.
claude-templates/bin/page-signal is a bash wrapper around signal-cli
send. It defaults to --note-to-self for safety. The wrapper supports
--file for attachments, --to <+number> for outbound (explicit per
call, no defaults, no batch), --quiet, and --json. Exit codes: 0
sent, 1 signal-cli failure, 2 usage error, 3 signal-cli not
installed.
claude-templates/.ai/workflows/page-signal.org carries the
discrimination rules and safety rails. When desktop notify covers it,
don't reach for Signal. Long-running task completion is the canonical
case. Outbound to other contacts requires explicit Craig instruction
per send. A known-limitation note covers the current notification
gap. signal-cli registered on Craig's primary number means messages
don't fire notifications until the pending Google Voice registration
lands.
claude-templates/.ai/workflows/cross-project-broadcast.org and its
helper cross-project-broadcast.py fan out a single message file to
every AI project's inbox in one operation. Discovery is
fingerprint-based: any directory under ~/code, ~/projects, ~/.emacs.d
with both .ai/protocols.org and a top-level inbox/ is broadcastable.
Senders are auto-excluded. Verified discovery against 23
broadcastable targets.
Makefile's install target gains a general bin/ loop. The previous
version hardcoded bin/ai. The new version iterates over every
executable under claude-templates/bin/ and symlinks each into
~/.local/bin/. install-hooks (existing Claude hook installer) is
unchanged. install-githooks (sync-check pre-commit hook setup, added
earlier today) is unchanged. The bin/ loop now picks up bin/page-signal
automatically.
INDEX entries for both new workflows landed under Tools and meta.
No bats tests on the new scripts. page-signal was smoke-tested with a
live send. The send succeeded. The notification gap is covered by the
workflow's known-limitation note. cross-project-broadcast.py was
smoke-tested via --list against the live project set. Tests can be
added when the broadcast pattern proves out across multiple use cases.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Pre-commit caught a false-positive on its first real-world run. The
.ai/scripts/__pycache__ directory created by make test (pytest writes
.pyc and .pytest_cache, emacs writes .elc) was flagged as drift
against the canonical's clean tree.
Added matching --exclude patterns to the diff -rq check and the --fix
rsync calls. Patterns: __pycache__, *.pyc, *.pyo, .pytest_cache, *.elc.
The --fix excludes prevent rsync's --delete from wiping the mirror's
__pycache__ when the canonical has none.
Four new bats tests cover the exclusions. All 12 pass.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
open-tasks.org Phase A now runs `emacs --batch -q -l
.ai/scripts/todo-cleanup.el --archive-done todo.org` as a pre-step
before the parallel read batch. A level-2 task that completed during
the session sits as ** DONE under Open Work until something archives
it, which means Next Mode would surface it as a "what's next" candidate
between cleanups. The pre-step ensures Phase A's read of todo.org
reflects current state.
The pre-step skips only in an explicit read-only or dry-run context.
Default is always to sweep.
Common Mistake #13 records "recommending a freshly-DONE task" with the
pointer back to the pre-step.
The proposal came from a pearl handoff on 2026-05-28.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Generic process-inbox workflow at claude-templates/.ai/workflows/ and
mirror. Owns inbox discipline across every project: items are ideas to
evaluate, not orders to execute, and earn a place in todo.org or git
history only when they pass a three-question value gate.
The gate (Phase B):
- Advances an existing TODO (look up by topic).
- Improves how the project works (architecture, workflows, tooling,
rule hygiene).
- Serves the project's stated mission (read from notes.org
Project-Specific Context).
One yes accepts. Three nos reject.
Per-source rejection flow (Phase D):
- From Craig: state in chat, wait for override.
- From another project: write a response via inbox-send naming which
gate question failed plus any reconsideration condition. Silent
rejection on a handoff is worse than no reply.
- From a script or automated system: just delete.
Phase B.1 gates filing on priority-scheme presence. If todo.org has a
scheme at the top, file with cookie + mandatory type tag + optional
effort/autonomy tags. If not, surface a one-sentence nudge to adopt
one (or to skip grading and flag the gap in the commit).
Phase D within accepts splits implement-now / fold-into-existing /
file-as-TODO so the inbox doesn't default to inflating todo.org for
every item that passes the gate.
Phase E stamps :LAST_INBOX_PROCESS: in notes.org Workflow State if the
section exists.
startup.org Phase C step 2 now delegates here instead of inlining the
inbox-processing language. INDEX entry under Tasks and planning lists
the full set of trigger phrases.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Pearl independently built its own no-approvals workflow (handoff in this
morning's inbox) and asked rulesets to take the best from both. That's
cross-project signal that the workflow earns a place at the template tier.
Promoted from =.ai/project-workflows/= to =claude-templates/.ai/workflows/=
with a mirror under =.ai/workflows/=. INDEX entry added under "Tools and
meta" listing the full set of trigger phrases.
Merged from pearl's draft: the prominent "What's Suspended" / "What Stays
On" split (same content as the prior "Contract" section, easier to scan),
wider trigger phrases (the project-only version had fewer), the
mode-resets-when-Craig-switches-topics guard, an explicit destructive-action
carve-out as its own bullet rather than buried in the "real question"
section, and a subagent-review-gate callout.
Kept from the rulesets version: the Session Log update emphasis between
items, the real-question include/exclude lists, and the don't-auto-wrap-up
guard.
A History section at the bottom records the merge for future archaeology.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two changes land together because each is broken without the other.
open-tasks.org gains a new Phase A.1, evaluated only in Next Mode. The
phase reads :LAST_AUDIT: from notes.org and walks five state signals
(reminder/task mismatch, passed scheduled date, "waiting on X" matches a
shipped X, dead file: link, sub-task >75% DONE coverage). If the temporal
threshold of 14 days trips, or any signal fires, Next Mode offers a
task-audit run before producing the recommendation. Item 1 in the offer
is "run task-audit first" per the recommendation-at-item-1 convention.
task-audit.org gains two pieces. Phase C now enforces priority and
type-tag presence per the project's legend, applies the [#A] dating rule
from that legend, and re-assesses :quick: and :solo: from reconciled
facts. Unambiguous calls land autonomously. Ambiguous ones flag
NEEDS-USER instead of being guessed. A new Phase E stamps :LAST_AUDIT:
on completion.
|
| |
|
|
|
|
|
|
|
|
| |
Bundles end-of-session state across three concerns.
claude-templates/.ai/workflows/open-tasks.org: in-flight restructure of Next Mode into a two-question output (cascade + friction filter), +62 lines. Separate from the iteration-history work that landed in 55adf6e and 684b273.
.ai/session-context.org: live session record covering startup through the iteration-history backfill. Captures the no-approvals mode and the full spec-review/spec-response cycle on the working draft.
inbox/: five new arrivals from this session: four pearl notes (pattern catalog, prompts-ux, spec-review implementation, prompt collapse) plus one .emacs.d note (whats-next + task-audit). A sixth file, PROCESSED-prefixed, represents mid-handling state on the open-tasks friction-cascade suggestion from earlier in the session.
|
| |
|
|
|
|
| |
Closes the org-drill backfill TODO. Both workflow files now carry a bottom "Review and iteration history" section with four entries: Draft 1 (linear-emacs origin, 2026-05-23, placeholder timestamp), Review-and-Fold (commit 7f2aea1, 2026-05-23), Requirement addition (commit 55adf6e, 2026-05-28), and this backfill commit. Canonical and mirror updated together. Working directory working/spec-workflows-iteration-history-backfill/ removed on this commit.
The spec-response cycle on the working draft (two Codex reviews, three rulesets responses) validated the entry-shape and the content before splice. Codex caught file-history conflation that would have made per-file provenance inaccurate. Craig's direct rationale on the Iteration 1 and Iteration 3 Why lines replaced the original INFERRED markers.
|
| |
|
|
|
|
| |
Specs reviewed under either workflow now carry a bottom =Review and iteration history= section. Each entry is an org subheading with a compound id (timestamp, contributor, role) plus What/Why/Artifacts body fields. The id is opaque. Timestamp, contributor, and role concatenate without implying any decision ordering.
spec-review.org adds the gate item, the entry-shape spec, and a "Preserve iteration provenance" principle. spec-response.org adds the matching Phase 4 step and a "history explains provenance" principle. Canonical and mirror updated together.
|
| |
|
|
|
|
|
|
|
|
| |
credential
A session false-alarmed on a leak risk when restoring a credentials doc into a tracked .ai/ file. The reasoning was wrong: a tracked secret is only a public-leak risk where the repo can reach a public remote, which means code projects on public GitHub, the ones that already gitignore .ai/. Personal and documentation projects push to a private single-user repo on cjennings.net, so tracked credentials in their .ai/ files are fine and expected.
I added the rule next to the existing "should .ai/ be committed?" decision in protocols.org, since it's a direct corollary of the same code-vs-personal split. The "is this a leak?" question now resolves on which kind of project and remote it is, not on the mere presence of a credential in a tracked file.
Origin: an elibrary session raised the false alarm and Craig corrected it.
|
| |
|
|
|
|
|
|
| |
A project script dropped into .ai/scripts/ gets wiped on the next startup, because that dir syncs from the template with rsync --delete. There was no documented home for a project's own scripts, the script-side counterpart to .ai/project-workflows/.
I added .ai/project-scripts/ to the Directory Architecture table and noted in startup.org that it sits outside the synced set, like project-workflows/. A script a workflow imports lives there. Naming: a Python module imported via sys.path needs an importable name (underscores), while a CLI-invoked script can stay kebab-case like the template tooling.
No mechanism change. Startup Phase A only rsyncs protocols.org, workflows/, and scripts/, so project-scripts/ is already sync-safe. This just documents it.
|
| |
|
|
|
|
| |
I default page notifications to --persist so a page that fires while I'm away from the desk waits for me instead of auto-dismissing after a few seconds.
page-me and status-check already persisted every page. I added --persist to the rest: the alarm, reminder, and meeting-alert examples in protocols.org, the long-running-process completion ping, and the cross-agent-watch message notification. I documented --persist as the default for any page meant to get attention, with a low-value informational ping as the only exception.
|
| |
|
|
|
|
|
|
| |
The triage-intake workflow had every source baked into one file, so adding or changing a source meant editing the workflow itself. I replaced it with a source-agnostic engine plus per-source plugins named triage-intake.<source>.org. The engine carries the anchor/sentinel logic, the four-bucket model, the Phase A-D orchestration, the todo.org persistence convention, and the exit criteria. Each source's scan, classify, render, and action knowledge moved into its own plugin.
Four general plugins ship in the template: personal-gmail, personal-calendar, cmail, and github-prs. Project-specific sources live in the project's .ai/project-workflows/ and are never synced. Phase 0 globs both directories so a project source can't silently drop out of the sweep.
I taught INDEX.org and the startup workflow-discovery drift check the namespace. A file matching <engine>.*.org is a plugin of that engine, not an orphan, and gets no trigger entry of its own. A "run the triage-intake workflow" request routes to the engine, never to a plugin.
|
| |
|
|
|
|
| |
send_file ran filenames through slugify(), which flattens dots to hyphens. That corrupts the engine.plugin.org plugin-namespace convention: triage-intake.personal-gmail.org arrived as triage-intake-personal-gmail.org, which breaks the engine's triage-intake.*.org glob and the routing that depends on the first dot.
I added slugify_filename() for filename stems. It keeps dots, hyphens, underscores, and case, collapses only whitespace runs to hyphens, and truncates on a separator boundary. The prose --text path still uses slugify().
|
| |
|
|
|
|
|
|
| |
These two workflows form a reviewer side and an author side for taking a design spec to implementation-ready. spec-review judges a spec against a readiness gate, reads the code before critiquing, evaluates across dimensions, assigns a rubric (Ready / Ready-with-caveats / Not-ready / Needs-research), and writes a <spec>-review.org file when it isn't ready. spec-response consumes that file: it decides accept / modify / reject for every recommendation, weaves the accepts into the spec body, records the modifies and rejects with reasons in a "Review dispositions" section, and reconciles tensions when coupled specs get reviewed together. The review file is the contract between them.
Both were validated by a real run on 2026-05-23 before landing here. I then reviewed them against established practice and tightened five things. The readiness gate now covers security/privacy and observability, since a spec shouldn't pass with those undefined. Phase 1 is a fast triage and Phase 3 is the authoritative gate after the code read. Finding severity maps to blocking power. A rejection goes back to the reviewer instead of standing as a unilateral call. And the response loop has an explicit termination condition.
I added both to INDEX.org under a new "Specs and design" section with trigger phrases, cross-linked as a pair, and kept the canonical and mirror copies identical.
|
| |
|
|
|
|
| |
The task-review and task-audit workflows already assess :quick:, an effort estimate. I added :solo: alongside it: a task Claude can finish end-to-end without Craig's input, gated on bounded scope, no design or preference call, and local verifiability.
In task-review.org I added a tagging subsection paralleling :quick:, a mention in the close-out summary, and a common-mistake entry against over-tagging. task-audit.org now re-assesses both tags during content reconciliation, since a resolved dependency can make a stuck task newly solo-able. It points at task-review.org for the definitions rather than restating them.
|
| |
|
|
| |
The mark-read step extracted message paths with mu --fields='p', but 'p' is the priority field (returns "normal"), not the path. Every path came back as "normal" and the flag manager errored on all of them. 'l' is the file-location field. Caught during a live triage on 2026-05-22.
|
| |
|
|
| |
A task audit reconciles each open task's recorded content against reality (sessions, email, chat, ticketing, calendar, recordings) and fixes the stale facts. That's distinct from task-review, which grooms relevance and priority. The two compose: review keeps the list lean, and audit keeps the survivors factually honest. Registered it in the workflow INDEX with its trigger phrases.
|
| |
|
|
|
|
|
|
| |
screenshot.py
Extends screenshot.py with --launch CMD, which runs a command on a transient headless Hyprland output, captures it, and tears the output down, so a UI can be verified without touching the visible workspace. --layout (tiled/monocle/floating) and --size control placement: output resolution for tiled/monocle, window size plus centering for floating.
Refactors the testable logic (size parsing, geometry strings, window matching, the exec-rule body, centering) into pure helpers and adds test_screenshot.py covering them across normal, boundary, and error cases. The grim/hyprctl wrappers and the capture orchestration stay thin and are verified functionally.
|
| |
|
|
| |
Adds a grim + hyprctl wrapper so a session can capture the screen or a single window and read the resulting PNG, turning "does this look right?" into an inspectable artifact. Modes: --full (all outputs), --active (focused window), --window REGEX (matched against class or title), and --list to enumerate open windows. Output goes to a chosen path (default a timestamped file in /tmp) and the saved path is printed on stdout so the caller can read it back; the parent directory is created if it does not exist. Syncs into every project's .ai/scripts/ via the startup rsync.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
Startup synced the .ai/ templates into the current project every session but never checked the language bundle (elisp, python) installed in .claude/. Bundle drift went unnoticed until someone re-ran make install-lang by hand: a generic rule added to claude-rules/ after the last install, or a changed validator hook.
scripts/sync-language-bundle.sh closes that gap. It fingerprints which bundle a project has by the presence of the language's own rule files (elisp.md, python-testing.md), then reconciles against the canonical source: auto-fix for rulesets-owned files (.claude/rules/*.md, .claude/hooks/*, githooks/*), surface-only for settings.json, which a project may have customized. CLAUDE.md is left alone. It's seed-only in install-lang and project-owned afterward, the same reason diff-lang skips it.
Startup Phase A step 12 calls it for the current project, guarded so older checkouts that lack the script still boot. It writes only under .claude/ and githooks/, disjoint from the .ai/ rsync paths, so the parallel batch stays safe. A script rather than a make target keeps the Makefile-parse layer off the boot path. The absolute rulesets path it depends on is the same one the rsyncs already carry.
Tested: 11 bats cases (no-bundle, clean, drifted rule/hook auto-fixed, surfaced settings.json asserted unmodified, absent CLAUDE.md not flagged, python detection, $PWD default, bad path). A smoke run against a copy of a real elisp project's .claude/ caught a perpetual "CLAUDE.md missing" alarm, which is what drove dropping CLAUDE.md from the surface set.
|
| |
|
|
|
|
| |
I added a per-task effort check to the task-review walk. If a task looks like 30 minutes or less and isn't already tagged, mark it :quick: on the heading. When the heading and body don't make the effort clear, ask instead of guessing. A mislabeled :quick: defeats the point, since the tag exists so Craig can grab a genuinely small task in a spare moment.
I edited the canonical claude-templates copy and the synced project mirror together, so the next startup rsync won't revert them.
|
| |
|
|
|
|
|
|
|
|
| |
The new task-review.org workflow is the daily habit that retires the old date-coverage scan. It surfaces the oldest-unreviewed top-level tasks, walks them one at a time, and records each outcome — keep, re-grade, kill, mark DOING, or edit — stamping :LAST_REVIEWED: as it goes. It's a pure Claude workflow, no elisp. open-tasks.org displays the list; this one changes it.
task-review-staleness.sh gains a --list mode that emits the N oldest-unreviewed tasks (line, review date, heading), oldest first, so the workflow walks a deterministic batch instead of eyeballing todo.org. Never-reviewed and unparseable-date tasks sort oldest. Seven new bats cases cover ordering, the count limit, exclusions, and output format; count mode is unchanged.
startup.org gains the matching nudge. Phase A counts tasks unreviewed for >7 days and Phase C surfaces one line when that count is non-zero, pointing at the workflow. It lives in the template startup.org rather than the project-only startup-extras layer, so every project picks it up the same way it picks up the wrap-up health check.
The INDEX entry is added with the "task review" triggers the rename freed up.
|
| |
|
|
|
|
|
|
| |
The list-and-pick-next workflow was named task-review.org, but "task review" better describes a list-hygiene habit that re-grades and prunes tasks, not one that just displays them. I'm freeing the task-review.org name (and the "task review" trigger) for that habit, which lands next.
This workflow goes back to open-tasks.org — the name it carried before it merged with whats-next.org. Its content and INDEX entry drop the "task review" trigger and point at task-review.org for the hygiene habit. Behavior is unchanged; only the name and the routing phrases move.
The rename touches both the canonical workflow and the project mirror.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
First component of the daily task-review habit from docs/design/task-review.org. The staleness count is the shared primitive both the wrap-up health check (threshold 30) and the startup reminder (threshold 7) call, so it lives in one tested script rather than being reimplemented in each workflow.
The script counts top-level todo.org tasks whose review has gone stale: depth-2 headings with a TODO/DOING/VERIFY keyword and an [#A]/[#B]/[#C] cookie, where LAST_REVIEWED is missing, unparseable, or older than the threshold. Age uses a strict greater-than, so a task reviewed exactly N days ago is still fresh. Today normalizes to local midnight before the diff, and the day count rounds to the nearest day, so a DST hour can't push a boundary task across the line.
Twelve bats cases cover the normal, boundary, and error categories. Dates are generated relative to the current date rather than hardcoded. The script path resolves as the sibling-of-parent of the test file, so the suite runs identically from the canonical claude-templates tree and the rsync'd project mirror. Makefile test target now globs .ai/scripts/tests for bats alongside scripts/tests.
|
| |
|
|
|
|
| |
tmux's default new-window placement chooses the lowest free index, which can land between existing windows when the session's window indexes have gaps. The -a flag plus the :{end} target makes it explicit: insert after the existing last window, every time.
The change only touches create_window. The two tmux new-session sites (single_mode and multi_mode first window) create fresh sessions; the first window's position is whatever base-index dictates, and there's nothing to append after.
|
| |
|
|
|
|
|
|
|
|
| |
The ai launcher used to send claude a fixed instruction string ('Read .ai/protocols.org and follow all instructions.'). Every window opened the same way, with no signal in the conversation about which machine or project it belonged to. That's fine when there's one window, less fine when an ai-session has 5+ windows across two machines.
The new build_instructions helper formats the opener per project: "This is <host> <name> project. Follow all instructions in .ai/protocols.org." Host comes from uname -n (POSIX, no dependency on the hostname binary which isn't installed by default on Arch). The project name distinguishes windows; the .ai/ prefix on the path stays so claude resolves the file reliably on first read.
The three send-keys call sites all use the helper now (create_window, single_mode new-session, multi_mode first-window). Smoke-tested with rulesets, .emacs.d, jr-estate basenames.
Also fixes the stale Source/Install header comments. They still pointed at ~/projects/claude-templates/bin/ai, the pre-fold path the subtree merge replaced.
|
| |
|
|
|
|
| |
I added claude-rules/working-files.md as the canonical convention. In-progress task artifacts live in working/<task-slug>/ under the project root. On task completion the files get renamed individually with a YYYY-MM-DD-<slug>-<descriptor> shape and moved flat into assets/ (or the area-specific assets/). Never rename the directory as a substitute for filing, since that loses the flat-searchable property of assets/.
claude-templates/.ai/protocols.org gained a short reference to the rule so it propagates to every project's .ai/protocols.org on the next startup rsync.
|
| |
|
|
|
|
|
|
| |
The "If this session crashed right now..." heuristic was the trigger. It pushes the decision onto the agent every turn, and the agent's bias is to defer when no obvious milestone just happened. Four recent sessions in the work project showed the same drift. The pattern: substantive work, no mid-session writes, a wrap-time reconstruction afterward.
The new primary trigger is mechanical. A turn that called any state-modifying tool (Edit, Write, Agent dispatch, MCP write, or Bash that mutates state) writes to the Session Log before the closing user-facing message. Pure-read turns (Read, Glob, Grep, read-only Bash) don't trigger. The existing high-loss bullets stay as elaboration. They aren't the trigger.
The 5-turn safety net remains. The judgment heuristic is gone. The primary trigger replaces it.
|
| |
|
|
|
|
|
|
|
|
| |
org-lint emits three warnings for every `#+begin_src cj: comment ... #+end_src` annotation block: suspicious-language-in-src-block (the language `cj:` isn't a known Babel slug), wrong-header-argument (the trailing `comment` looks like a header arg without a colon), and empty-header-argument (that same `comment` has no value). All three are false positives. The cj-comment block is a Craig-specific annotation marker, not Babel src-block syntax.
I added a helper `lo--cj-comment-block-opener-p` that pattern-matches the opener line, then a short-circuit branch at the top of `lo--handle-item` that silently drops any of the three checkers when they fire on a cj-comment opener. No fix is counted, no judgment is emitted, and the warnings disappear.
Two new tests cover the change. The normal case is a solo cj-comment block, which should produce zero judgments and zero fixes with all three flagged checkers absent from the issue list. The boundary case is a cj-comment block alongside a real `#+begin_src markdown` block. The markdown warning still surfaces, which scopes the suppression to cj openers only — no leak into other src blocks.
Test count goes from 22 to 24, all green. I smoke-tested against rulesets/todo.org: judgment count drops from 7 to 1. Six cj-comment false positives at lines 16 and 1291 are gone, and the unrelated misplaced-heading at 2139 still surfaces correctly.
|
| |
|
|
|
|
|
|
|
|
| |
wrap-it-up's lint-org and date-coverage scans both defaulted LINT_ORG_FOLLOWUPS to `$HOME/projects/work/inbox/lint-followups.org`. The intent was to land findings where the next morning's daily-prep would pick them up. The bug: every project running wrap-up dumped its findings into the work project's inbox regardless of which project's todo.org was scanned. The fallback at `.ai/lint-followups.org` never fired because `$HOME/projects/work/inbox/` exists on every machine.
I found this morning that work's inbox/lint-followups.org had accumulated lint output from .emacs.d, rulesets, and work across multiple wrap-up runs on 2026-05-15 and 2026-05-16. I routed the foreign sections back to the right inboxes via inbox-send.
The fix changes the default to `./inbox/lint-followups.org` in the current project's cwd, with `.ai/lint-followups.org` as the fallback when the project has no `inbox/` directory. The env var still overrides for projects that want to route somewhere else.
I applied the same change to both bash blocks (lint-org sweep at line 137, date-coverage scan at line 173) and rewrote the prose paragraph that documented the old default, with a note explaining why hardcoding a single project's path was wrong.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
Every Action item surfaced by Phase 3 sub-steps 3b/3d/3e/3f (email, Slack, Linear, PR Review) now becomes its own ** TODO in todo.org with :quick: + :reactive: tags plus sharp person/entity tags. The prep doc's * Day's Priorities section references each task as a thin link when it belongs in today's plan; otherwise the task stays in todo.org and surfaces on a later prep via the new sub-step 3a step 4 pull.
The grouped ** Email Response / ** Slack Response / ** Linear Response / ** PR Review sub-headings disappear from the prep doc. Source mix lives in the tags on each task. The Recommended Approach Pattern still applies. The analysis and draft response live in the task body, not in the prep doc.
Mirrors the convention adopted in the work-side triage-intake workflow on 2026-05-15. Closes the 2026-05-12 follow-up about rewording sub-steps 3b–3f.
|
| |
|
|
|
|
| |
cj-scan.py matched =#+begin_src cj:= / =#+end_src= line-by-line without awareness of enclosing block scopes. A cj fence embedded inside =#+begin_example= (typical when documenting what the <cj yasnippet emits) or =#+begin_src snippet= (the yasnippet definition itself) was misclassified as a live cj annotation. Two false positives surfaced from a /respond-to-cj-comments run against an org file with yasnippet docs.
Track an active wrapper_type. When the scanner sees =#+begin_<type>= for any type other than cj: (the cj-open regex is checked first), enter a wrapper state where every line is content until the matching =#+end_<type>= closer fires. Inside a wrapper, both fence patterns and legacy inline cj: lines stay suppressed. Added the TestCjScanNestedFencesIgnored class with 6 tests: nesting inside example, src <other-lang>, and quote; regression guards for clean wrapper close and unclosed-wrapper non-swallow. Canonical pytest: 302 passed, 1 skipped.
|
| |
|
|
| |
The 2026-05-15 claude-templates fold wired the rulesets-first-then-project ordering into startup.org Phase A.0, but the rule itself never landed in protocols.org. This adds a Startup Pull Ordering subsection under IMPORTANT - MUST DO with the ordering, the ff-only guardrail, and the no-auto-stash / merge / rebase rule. Mechanics stay in startup.org; the rule lives in protocols.org because it governs the first action of every session.
|
| |
|
|
|
|
|
|
| |
Canonical .ai/ source moved from ~/projects/claude-templates/ to ~/code/rulesets/claude-templates/ via subtree merge. Phase A.0's "Refresh claude-templates" step is now "Refresh rulesets" since there's only one repo to pull.
Updates:
- startup.org Phase A.0: rsync sources point at the in-repo path
- protocols.org and cross-agent-comms.org: workflow-promotion target paths updated
|
| |
|