aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* fix(scripts): stop org table helpers rewriting block contentCraig Jennings16 hours13-74/+370
| | | | | | 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.
* chore: archive completed tasks and close out the day's recordsCraig Jennings18 hours4-186/+377
| | | | The archive sweep moves the finished routing feature and the cancelled ntfy proposal into Resolved, todo.org carries the day's review stamps and dated build entries, and the session record lands under its dated name.
* chore(todo): finish the task review — full backlog now currentCraig Jennings18 hours1-9/+21
| | | | Eleven tasks reviewed: the ntfy two-way-comms proposal is CANCELLED (home tore that channel down on 07-04; the Signal pager task and agent-page are its living successors), the triage-intake phone-push task is re-pointed at agent-page so its send half is buildable now, coverage-summary's docs-only remainder gained quick and solo tags, and the rest were confirmed as-is. Zero top-level tasks remain unreviewed.
* fix(elisp): validate-el.sh prefers source over stale bytecodeCraig Jennings18 hours1-0/+2
| | | | Both emacs invocations in the hook now set load-prefer-newer, matching the project-side Makefile and early-init guards. Without it, the PostToolUse hook after a pull that changed a module ran tests against the module's stale .elc and every test failed void-function on the newly-added symbols. From .emacs.d's 2026-07-13 handoff, repro-verified there; inbox/2026-07-13-1712-from-.emacs.d.
* feat(launcher): bare ai picks the agent before the projectsCraig Jennings19 hours3-8/+88
| | | | The interactive flow now opens with a runtime picker: claude first (Enter-Enter preserves the old two-keystroke habit), codex labeled as ChatGPT, and one local:<model> line per ollama model, queried live with a short timeout so a dead server just drops those lines. The pick feeds the existing runtime map, then the annotated project multi-select runs as before. --runtime and AI_RUNTIME skip the question, single-directory mode is unchanged, and --print-runtimes exposes the choice list for the two new bats tests.
* feat(launcher): wire the local runtime — codex --oss over ollamaCraig Jennings19 hours3-18/+30
| | | | ai --runtime local now launches codex against the machine's ollama (explicit --local-provider=ollama, model from AI_LOCAL_MODEL, default gpt-oss:120b). Verified end to end with a codex exec completion through the local model. The dependency check probes AGENT_BIN now that AGENT_CMD carries flags. This makes codex-over-ollama the de-facto answer to the runtime spec's first-supported-local-CLI blocker.
* chore(todo): record the verified local-inference stack on the model-floor taskCraig Jennings22 hours1-1/+3
| | | | ollama 0.31.2 with the Vulkan backend forced by systemd override (ROCm first-touch loads were unusable at under 25 MB/s), gpt-oss:120b and qwen3-coder:30b verified at 37.9 and 76 tok/s on 100% GPU, four legacy dense models dropped, the orphaned user store purged. The child's remaining work is purely the instruction-following evaluation.
* feat(pager): add agent-page, the runtime-neutral phone pagerCraig Jennings23 hours11-14/+188
| | | | The Signal pager reconcile found one pager identity, registered in velox's signal-cli, reachable from other machines only by hand-rolled ssh. agent-page wraps that: direct signal-cli on velox, ssh relay over the tailnet from everywhere else, a desktop-fallback hint when the relay fails, and the UUID target baked in so nobody pages the unregistered phone number again. Four bats tests stub ssh/uname/signal-cli to verify command construction; the real path was verified with a live phone push today. protocols.org's Paging Craig section now teaches both channels (notify for the desk, agent-page for the phone) and demotes signal-mcp to a velox-local nicety; page-me.org, work-the-backlog, and the INDEX carry the same two-channel story. Every project inherits on its next startup sync and make install.
* chore(todo): task-review batch of seven, plus the roam-capture filingsCraig Jennings25 hours1-2/+20
| | | | Signal pager re-graded C to B: the runtime-portability inventory showed the claude.ai-side signal-mcp is the only paging path, home currently has no live channel at all, and off-Claude agents have none, so the doc-and-reconcile task now gates real capability rather than tidiness. install-ai-on-PATH tagged quick and solo. The launcher-hardening task and the agent-switching fold-in came from today's roam capture. The other five reviewed tasks were confirmed as-is.
* docs(runtime): session plumbing assessed, no build neededCraig Jennings25 hours2-2/+13
| | | | session-context-path already carries a runtime segment, the anchor cycle is plain files, and self-inject is harness-agnostic with only its payload Claude-shaped. A codex auto-flush is a documented payload variant whose second injected line carries the resume instruction, replacing the SessionStart hook. Wire it when a codex session first wants it.
* feat(launcher): add ai --runtime for choosing the agent CLICraig Jennings25 hours3-16/+146
| | | | The ai launcher can now start codex sessions: --runtime claude|codex (or AI_RUNTIME), a runtime-to-CLI map with local reserved behind a clear error until the local-model evaluation picks a CLI, and a runtime-aware dependency check. A new --print-launch mode prints the pane launch command without touching tmux or fzf, and is the seam the six new bats tests drive. Both current CLIs take the opening line as a positional prompt, so only the command name varies.
* feat(runtime): add the thin-pointer AGENTS.md agent entry fileCraig Jennings26 hours8-4/+119
| | | | claude-templates/AGENTS.md points any harness at protocols.org, the rules locations, and the /name-to-file resolution rule, and tells it to degrade per each rule's documented fallback instead of skipping gates. make install links it to ~/.codex/AGENTS.md (new CODEX_DIR stanza) and install-ai.sh seeds a project-owned copy at bootstrap, never overwriting an existing one. The rulesets root carries a tracked symlink as dogfood. Five new bats tests cover the link idiom and the seeding. This resolves the generic-instruction-file blocker from the runtime spec, and velox picks up the global link on its next session's make install.
* docs(runtime): skill parity resolves to one bootstrap resolution ruleCraig Jennings27 hours2-2/+17
| | | | All 29 skill and command bodies are markdown, so a single sentence in the future non-Claude entry file (a /name reference resolves to the skill or command file, read and follow it) carries the whole library. Auto-invocation degrades to by-name, which the publish flow already uses. flush stays Claude-only, owned by the session-plumbing child.
* feat(runtime): complete the hook, MCP, and memory portability inventoriesCraig Jennings27 hours3-7/+71
| | | | The new inventories doc maps what's actually Claude-bound. Hooks: only PreCompact and Stop-teardown carry porting decisions, both now decided (prose downgrade, Codex notify or manual). MCP: everything ports mechanically except paging, since signal-mcp exists only claude.ai-side, so the Signal-pager task gains runtime portability as a second motivation. Memory: the KB is already the cross-agent store, and knowledge-base.md now tells agents without harness memory to capture into the session log. Three inventory child tasks closed as dated entries under the generic-agent-runtime parent.
* fix: pin the session model to fable as intendedCraig Jennings28 hours1-1/+1
| | | | d5bc9b3 was meant to keep the opus-to-fable flip but recorded only a case change (opus to Opus) — the harness had rewritten the file before staging. This lands the value Craig actually chose.
* chore(todo): file runtime-portability child tasks and stamp a reviewCraig Jennings28 hours1-0/+28
| | | | Eight child tasks under the generic-agent-runtime parent decompose what's left to run a non-Claude agent (Codex-style or local LLM) in this system: instruction bootstrap, skill parity, hook parity, launcher flag, session plumbing, memory story, MCP portability, local model floor. Each names the spec blocker decision it feeds. Also stamps the build-to-prototype task's review.
* chore(todo): fold home's Signal-pager status into the pager doc taskCraig Jennings30 hours1-0/+3
|
* chore: switch session model from opus to fableCraig Jennings30 hours1-1/+1
|
* feat(rules): add visuals-display rule for EAT and a zsh word-split noteCraig Jennings30 hours3-0/+23
| | | | interaction.md gains a Showing Craig Visuals section: EAT renders SendUserFile and inline images as a text line, so visuals open in the browser or imv (per desktop-capture.md), with inline sixel as the quick-glance lane behind a capability gate (patched EAT answering CSI 14 t plus tmux terminal-features sixel, diagnosed 2026-07-13). protocols.org gains the zsh no-word-split gotcha next to the exa alias note. takuzu sent the proposal as inbox handoff 2026-07-11-2137; the sixel findings correct its capability claim.
* feat(rules): add SVG-first rendering guidance for Emacs app UIsCraig Jennings34 hours2-0/+23
| | | | emacs.md gains an SVG Rendering section: default to svg.el for Emacs app UIs with real visual structure, prototype in HTML first, and stay inside the librsvg-safe constraint sheet from jotto's Emacs 30.2 pgtk spike. ui-prototyping.md points Emacs UI prototypes at the svg.el port target. jotto sent the proposal as inbox handoff 2026-07-11-0248.
* chore(todo): archive completed tasks, file build-to-prototype follow-upCraig Jennings4 days5-112/+249
|
* chore(todo): file three rulesets ideas from the roam inboxCraig Jennings4 days1-0/+18
|
* chore: file processed inbox handoffs and add two backlog tasksCraig Jennings4 days13-1/+332
|
* fix(task-review): accept org-native LAST_REVIEWED stamps, warn on bad onesCraig Jennings4 days6-20/+170
| | | | | | task-review-staleness.sh expected a bare 2026-07-09 and treated an org inactive timestamp ([2026-07-09 Thu], the form matching the CREATED:/CLOSED: cookies in the same drawer) as unparseable. The count branch folded that into the stale count, so a freshly-reviewed task reported as never-reviewed, and a full review pass never dropped the startup nudge. Both the bare and bracketed forms now normalize to the ISO date. A value that is neither warns loudly to stderr (file:line:value) and stays out of the count, since a data error shouldn't hide as "never reviewed." task-review.org documents the accepted format. Tested red/green: 5 new bats cases (bracketed fresh and stale, list-mode sort by real date, malformed warns and is excluded). Full suite 273 ok.
* docs(todo-format): warn against double-counting rarity in the bug matrixCraig Jennings4 days1-0/+23
| | | | | | Grading a bug's severity by how rare it is to enter the failure state double-counts the frequency axis, which already carries that rarity. It buries the compounding bugs, the ones where a rare trigger produces unbounded harm. Three rules added to the severity × frequency section: grade severity by the rate of harm once the failure state is entered, record the band, row, and arithmetic in the task body so a misgrade can be re-checked against the source, and disagree with a grade by fixing an input rather than overriding the letter. A chime watchdog bug graded [#D] moved to [#C] an hour later, once the read was written down and re-checked.
* docs: add off-workspace window/capture ruleCraig Jennings4 days2-0/+59
| | | | | | When an agent opens a window or takes a screenshot to verify its own work, it shouldn't hijack the workspace the user is actively using. New claude-rules/desktop-capture.md: render self-captures on an off-screen output (a Hyprland headless output) and tear them down. When showing the user something, open it on a separate real workspace and name it. verification.md points at it. The principle is environment-general. The recipe is Hyprland-specific. Verified non-disruptive on ratio 2026-07-06.
* docs(spec): add UI-prototyping process for non-trivial-UI specsCraig Jennings4 days5-0/+94
| | | | | | For a spec whose deliverable is a real UI, a design argued on paper is a guess. New claude-rules/ui-prototyping.md: research the category first, brainstorm the UX in the spec, build ~5 distinct working prototypes over one engine, iterate one to a final, and record a UI decision only once it's been seen working in a prototype. spec-create gains the step for non-trivial-UI specs. spec-review gates on it: research cited, final prototype linked, iterations in history, decisions backed by a prototype. Prototypes live at docs/prototypes/<spec-name>-prototype-<N>.html. Worked example: archsetup's timer-panel spec and its three prototypes.
* docs(review): drop praise from approve summaries, print inline text at the gateCraig Jennings4 days4-19/+27
| | | | | | | | An approve summary now carries no praise, not even a bare positive like "Clean." or "Solid fix." Lead with the substantive pointer (the design note pinned inline) and close with the verdict. This removes the bare-positive carve-out from review-code's Posted Summary Voice and from voice pattern #40, and updates the worked examples. The review gate must also print the full prose of every inline comment, never a description of it. The exact words post under my name, so I have to see them before I approve. Made explicit in review-code Phase 5 and commits.md Shape 1. From a DeepSat review session where I approved "One design note inline, not a blocker. Approving."
* fix(triage-intake): guard personal-gmail sweeps against the Gmail 100-capCraig Jennings4 days2-0/+30
| | | | | | The google-docs MCP listMessages tool caps at maxResults=100 and exposes no pageToken, so an unread pile over 100 truncates silently and every later anchored sweep skips the tail below the cap. That's how a 300+ backlog built up unseen by 2026-07-08. Two Scan-section rules close it: when a scan returns exactly 100, walk the tail in date slices and dedupe by id, and never report resultSizeEstimate as a count. A cheap backlog-residue probe each sweep (before:<anchor>, maxResults=5) surfaces pre-anchor unread loudly, so an anchored "no changes" can't mask a window the scan never saw. personal-gmail is the only gmail-family plugin here, so it's the only file that changed.
* chore: make remove.sh executableCraig Jennings5 days1-0/+0
|
* chore: drop AI co-author from generated-document headersCraig Jennings5 days104-103/+132
| | | | | | | | | | 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.
* chore(todo): archive three audit-closed tasks to ResolvedCraig Jennings10 days4-185/+254
|
* fix(startup): skip the .ai/ template sync when the project branch is behindCraig Jennings10 days2-10/+42
| | | | | | | | | | Phase A step 3 guarded its template rsync only on whether rulesets' own source was clean, never on whether the project branch was current. When a branch is diverged or behind-and-dirty, Phase A.0 correctly declines to fast-forward, but the rsync then landed templates on the stale committed .ai/ baseline. The diff came out huge (measured against old content) and conflicted once the branch reconciled to upstream's newer templates. home hit it today: a 3-ahead/46-behind divergence produced ~25 files of phantom drift nobody authored. I added a second guard: after Phase A.0's reconcile, it re-checks git rev-list @{u}...HEAD and skips the rsync when behind>0. It composes with the rulesets-clean guard, so both a stable source and a current branch are required before the sync runs. No-upstream and ahead-only both fall through and sync, which is correct. It's deliberately not an auto-discard: a legitimate local stopgap in a synced file can't be told from accidental drift by content alone, so prevention is safe where blind cleanup isn't. Phase C's churn safety net still surfaces pre-existing dirt. home proposed this via inbox handoff.
* chore(todo): close three tasks the audit confirmed doneCraig Jennings10 days4-27/+36
| | | | | | | | | | The audit found three tasks code-complete with only validation left, so I closed each and flipped its spec to IMPLEMENTED: - Docs-lifecycle convention: all four build phases plus the file-to-id link conversion had shipped. Manual validation and the org-agenda vNext moved out to their own tasks. - Wrap-up inbox/transcript routing: the recommendation engine, the route-candidate marker, the wrap-up router, and route-batch all shipped green. Manual end-to-end validation and transcript filing moved out. - Cross-machine memory sync: verified the sync round-trip live across velox and ratio (a probe made on one reached the other, its deletion propagated back, both clones on one HEAD, no conflicts). The work and unknown-project write-refusal checks moved out. I also stamped the audit marker.
* chore(settings): switch default model from fable to opusCraig Jennings10 days1-1/+1
|
* chore(todo): archive five completed tasksCraig Jennings12 days3-93/+200
| | | | Host-identity guard, the no-approvals speedrun, the inbox-send collision fix, page styling, and template-sync policy all moved to Resolved. The vNext agenda-view child keeps its deliberate [#D] under a :no-sync: tag.
* chore(metrics): record the first loop cycle's two task outcomesCraig Jennings13 days1-0/+2
|
* fix(page): pages are info-level, not alarm-redCraig Jennings13 days6-30/+102
| | | | | | Craig's verdict on the all-red page styling: it reads like the system is about to crash. page-me and the work-the-backlog end-of-set page now use notify info --persist, still persistent and audible, never crash-scary. status-check's success and fail notifications keep their types, since a job outcome isn't a page. The commit also carries the two loop-filed task records and the archive sweep counterpart from earlier tonight.
* fix(inbox-send): never overwrite on filename collisionCraig Jennings13 days4-4/+188
| | | | Two sends in the same minute whose text starts with the same phrase derived identical filenames, and the second silently replaced the first. A message was lost this way in the wild. An existing target now gets a -2/-3 stem suffix, extension preserved, on both the text and file paths. Four red-first tests reproduce the loss with a fixed timestamp so the same-minute case is deterministic.
* docs(spec): flip autonomous-batch to IMPLEMENTED after the live trialCraig Jennings13 days3-7/+10
| | | | The first speedrun ran Craig's three-task set end to end: pre-flight Q&A once, three reviewed commits, one metrics record per task, one end-of-set page. He confirmed the run and granted :LOOP_MAY_COMMIT:, so the recurring loop may now commit here alongside the existing :COMMIT_AUTONOMY: waiver.
* chore(metrics): record the first speedrun's three task outcomesCraig Jennings13 days1-0/+3
|
* feat(sync): never let untracked or gitignored files block template updatesCraig Jennings13 days5-5/+12
| | | | | | Projects were falling behind on templates because somebody sent them a task: an untracked inbox drop read as a dirty tree to the stricter gates. The policy is now stated where the gates live: dirty means tracked modifications only, and untracked or gitignored files never block a template pull, a fast-forward, or a monitoring gate. The audit found one offender. The inbox monitor's precondition used bare porcelain, counting the very drops it exists to process. It now checks tracked changes only, which is safe because the per-item commit already stages explicitly. The rsync WIP-guard keeps counting untracked files inside the synced source paths on purpose, since a half-written template is exactly the WIP it holds back.
* feat(rules): add the host-identity guard rule and startup probeCraig Jennings13 days4-1/+44
| | | | | | A tracked or synced doc asserting "this machine is X" is false on every machine but its origin, and an agent trusting it reasons backwards all session. It happened live: a stale "ratio" claim steered a session running on velox. The new rule bans fixed identity claims in tracked/synced docs and requires the runtime derivation instead (uname -n, since the hostname binary is often absent). Describing the fleet stays legal. Claiming the current member doesn't. startup gained a read-only probe that greps CLAUDE.md and notes.org for the pattern and surfaces hits as a judgment flag, never a block. Fixture-verified under bash and zsh.
* feat(docs): convert spec-target file links to id formCraig Jennings13 days2-87/+37
| | | | | | All 13 file:docs/specs/ links lived in todo.org. Eleven converted directly. The two carrying a Review-findings search target now point at a new :ID: minted on that heading, since the id index scans whole files and heading-level ids stay rename-safe. The residue grep is zero and every id resolves to its target's :ID:. The commit also carries the routine archive sweep of freshly-closed tasks and the speedrun pre-flight answer stamps.
* chore(tasks): file two roam items and ungate the id-link conversionCraig Jennings13 days1-2/+10
| | | | The id-conversion task's gate cleared: the org-id index for docs/specs landed upstream and a live org-id-find resolves the docs-lifecycle spec. Filed from the roam inbox: template sync passing gitignored-only changes, and the wrap-it-up summary keep-or-cut think-through.
* feat(flush): add auto mode with self-injected /clear for unattended runsCraig Jennings13 days8-5/+371
| | | | | | Long autonomous sessions bloat or hit auto-compaction because /clear is a prompt keystroke no tool call can execute. Auto mode closes that gap: after the write-verified checkpoint, the agent derives its own tmux pane, arms self-inject.sh through tmux run-shell -b, and ends the turn so /clear and a resume line land at an idle prompt. The server-owned arm is load-bearing: a detached child of a tool call dies at the turn boundary. The pane must be derived before arming because ancestry detection can't work under the tmux server. self-inject.sh joins the synced scripts with a six-test bats suite, tmux stubbed at the boundary. work-the-backlog now auto-flushes between tasks when context grows heavy, and its speedrun preset gained the per-item disposition rule: feature-level work gets a spec, unguessable decisions get a VERIFY, well-defined tasks get implemented. The mechanism was proven live in another project's session and its design note is preserved under docs/design/.
* feat(backlog): add the metrics synthesis step to org-roamCraig Jennings13 days5-4/+30
| | | | | | "synthesize backlog metrics" reads the JSONL union across personal projects and computes the per-run rollups, the trends, and the corrections signal (a later revert or fix touching an autonomous commit's files within ~14 days, a flag for review rather than a conviction). It writes one :agent:metrics: KB node linking back to prior synthesis nodes. Work and unknown projects are excluded by the denylist classification and reported per the refusal contract. The step is read-only over the logs plus the single KB write. It never mutates the JSONL, todo.org, or any project tree.
* feat(backlog): add the per-task JSONL metrics recordCraig Jennings13 days3-8/+74
| | | | | | One record per task at outcome time, appended to the project's .ai/metrics/work-the-backlog.jsonl. The field table follows the spec, with commit_sha called out as the corrections-signal key and comma-separated when a task decomposes into several commits. A failed append warns in the run summary but never blocks or aborts the run. I added the "failed" outcome the spec's error-handling section required but its enum missed: a mid-implementation failure leaves the tree working, gets surfaced, and the run continues.
* feat(backlog): flesh the defer mechanics, pre-flight Q&A, and pageCraig Jennings13 days3-10/+40
| | | | | | | | The defer checklist gained its filing mechanics. A deferral VERIFY now dedups against an existing sibling before filing, since the deferred task stays TODO and every later run would otherwise re-file. Placement, heading, and body follow the todo conventions. A quick-question gap routes to the pre-flight Q&A only under the speedrun preset, and only for one-line factual or preference picks. Three or more questions means the task is underspecified and files instead. The data-loss item never routes to the Q&A. The batch-ask is one message with recommendation-first numbered options, and answers land as dated lines in the task bodies before the run starts. The page fires exactly once, on set-done or cap-hit, via notify --persist.
* feat(backlog): pin the commit-autonomy waiver and its degrade contractCraig Jennings13 days4-8/+39
| | | | | | The waiver is now a machine-read marker: ":COMMIT_AUTONOMY: yes" in notes.org's Workflow State, with ":LOOP_MAY_COMMIT: yes" as the separate grant for the unattended loop. An absent or non-yes marker reads as no, and the read is a fresh grep each run, never memory. A caller requesting autonomous-commit without the marker degrades to file-only, surfaced in both the run intro and the summary. I stamped rulesets' own :COMMIT_AUTONOMY: and left :LOOP_MAY_COMMIT: ungranted. Letting the recurring loop commit unattended is a separate trust decision.