diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-31 01:11:55 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-31 01:11:55 -0500 |
| commit | 6f49edb17dd23b63e1cb6b4f11ffd0df1a546105 (patch) | |
| tree | fa3eef1e286c5a3d9521b2b5736000168494ab5d | |
| parent | 8c0eca8375db2c2d346f5fd08ac752209349f94e (diff) | |
| download | rulesets-6f49edb17dd23b63e1cb6b4f11ffd0df1a546105.tar.gz rulesets-6f49edb17dd23b63e1cb6b4f11ffd0df1a546105.zip | |
chore(ai): archive session record and resolved tasks
| -rw-r--r-- | .ai/sessions/2026-05-31-01-11-inbox-monitoring-workflow-and-infra-fixes.org | 84 | ||||
| -rw-r--r-- | todo.org | 76 |
2 files changed, 121 insertions, 39 deletions
diff --git a/.ai/sessions/2026-05-31-01-11-inbox-monitoring-workflow-and-infra-fixes.org b/.ai/sessions/2026-05-31-01-11-inbox-monitoring-workflow-and-infra-fixes.org new file mode 100644 index 0000000..5dbacef --- /dev/null +++ b/.ai/sessions/2026-05-31-01-11-inbox-monitoring-workflow-and-infra-fixes.org @@ -0,0 +1,84 @@ +#+TITLE: Session — lint-org verbatim-asterisk checker fix +#+DATE: 2026-05-30 + +* Summary + +** Active Goal + +Post-wrap continuation of 2026-05-30 (the prior session wrapped at 86326c1). A string of infrastructure fixes driven by Craig's directives and cross-project handoffs, capped by building an inbox-monitoring system. Six commits: 4b24597, 1f79945, 9a1bea9, 143feda, e446dab, ddcde66, 8c0eca8 — all pushed. + +** Decisions + +- *Linting shouldn't flag unfixable items* (Craig's rule): fixable → fix; unfixable false positive → message rulesets' inbox about the checker + rule. Applied to the recurring verbatim-asterisk misplaced-heading false positives. +- *Act-vs-file rule* (Craig): when I decide to act → just do it, no asking; when I decide to file → ask first, filing = option 1, "do it now" = option 2; always ask if unsure. Codified in monitor-inbox.org + protocols.org. +- *Startup rsync skip-when-dirty* (jr-estate handoff): option 1, scoped to the synced source paths so unrelated rulesets dirt doesn't block the sync. +- *Per-agent session-context* (Codex Phase 1): AI_AGENT_ID resolves the active path via a helper, backward-compatible (unset → the legacy singleton). Fixes the two-agents-one-project race without the broader runtime refactor. +- *cmail-action send is the default email path* (org-drill handoff): surfaced in protocols.org; send-email.org off the msmtp heredoc; send gained --cc/--bcc + threading. +- *Inbox monitoring as a template workflow* (Craig: "general workflow, for sure"): task-boundary cadence + opt-in background /loop + the act-vs-file rule + reply discipline, with an inbox-status script. + +** Data Collected / Findings + +- lint-org verbatim-asterisk false positives are recurring and unfixable in source — the fix is suppressing the class in the checker, not editing todo.org. +- The startup-rsync propagation anomaly (two files missing from jr-estate) was a timeline artifact (files added in 664bf01 after jr-estate's rsync ran), not a Phase A bug. +- cmail send was a working-but-invisible capability — an org-drill session claimed it couldn't send, then hand-rolled MIME through msmtp. Root cause: discoverability (protocols said nothing about email). + +** Files Modified + +- =lint-org.el= (+ test) — suppress verbatim-asterisk misplaced-heading (lo--verbatim-asterisk-at-line-p). +- =startup.org= — Phase A sync guarded skip-when-dirty (scoped to synced paths), renumbered steps. +- =session-context-path= (new script + bats), =protocols.org= / =startup.org= / =wrap-it-up.org= — AI_AGENT_ID-aware session-context path. +- =cmail-action.py= (+ test) — --cc/--bcc/--in-reply-to/--references via build_message. +- =protocols.org= — "Sending Email" subsection + "Inbox Monitoring Cadence" subsection; =send-email.org= Step 4 rewrite. +- =monitor-inbox.org= (new template workflow), =inbox-status= (new script + bats), =INDEX.org= entry. +- =todo.org= — two [#B] tasks (startup-dirty, Codex Phase 1) marked DONE. + +** Next Steps + +- *Inbox monitoring is now active* — check inbox-status at task boundaries going forward. The opt-in background =/loop= is available when unattended watching is wanted. +- *All today's handoffs confirmed back* to their senders (jr-estate, health, work, org-drill); inbox empty. +- *Signal MCP install at the desktop* still the oldest open carryover (GPG pinentry blocks it remotely). +- Parked [#B]/[#C]: cross-project pattern catalog, the broader runtime-neutral arc (parent of Codex Phase 1). +- Everything reaches downstream projects on their next template sync. + +* Session Log + +** 2026-05-30 ~17:20 CDT — post-wrap continuation: lint-org false-positive fix + +The prior session wrapped at 86326c1 (archived as =.ai/sessions/2026-05-30-16-06-drill-deck-anki-buildout-and-script-tests.org=). Craig then gave two post-wrap directives. + +First (4b24597): the wrap-up lint pass kept re-flagging two verbatim-asterisk misplaced-heading items (=** DONE=, =** Startup Pull Ordering= shown as verbatim refs in prose) that aren't fixable in todo.org. Per Craig's rule — linting shouldn't flag unfixable items; fixable→fix, else message rules' inbox — I filed a checker-bug report to this project's inbox (inbox-send excludes the sender, so a direct write) and dropped the two items from lint-followups.org. + +Then Craig said "fix the org checker" (1f79945). Added =lo--verbatim-asterisk-at-line-p= to =lint-org.el= (mirrors the markdown-bold detector, checks the reported line and the one before it since org-lint marks the blank line after the offender), and the misplaced-heading dispatch now suppresses verbatim-asterisk matches silently like the cj-comment case. TDD: flipped =lo-verbatim-asterisk-is-suppressed= + the mixed-fixture assertion (red), implemented (green). Updated header comments. Verified: 24/24 ERT, =lint-org --check todo.org= → judgment=0, sync-check clean, full suite 405/1skip green. Removed the now-resolved inbox bug report in the same commit. Pushed =4b24597..1f79945=. + +Craig then asked for a fresh session-context file (this one). + +** 2026-05-30 ~17:30 CDT — task 1: startup-rsync-dirty guard + +From jr-estate's handoff: Phase A's =rsync -a --delete= copies rulesets working-tree WIP into downstream projects when rulesets is dirty at their session start. Implemented option 1 (skip-when-dirty), scoped to the synced source paths: startup.org Phase A step 3 now guards the protocols/workflows/scripts rsyncs behind =git status --porcelain= on =claude-templates/.ai/{protocols.org,workflows/,scripts/}= — skips with a message when dirty, syncs when clean. Scoped to the synced paths so unrelated rulesets dirt (stray session-context.org) doesn't block the sync. Folded the three rsyncs into one guarded block, renumbered the Phase A list, added a Notes bullet. Verified the dirty-detection live (flagged my own WIP startup.org → skip). Resolved the reported propagation anomaly: cross-project-broadcast.org + page-signal.org were added in 664bf01 on 2026-05-29, after jr-estate's rsync ran — timeline, not a bug. Marked the [#B] task DONE. sync-check clean, suite 405/1skip green. + +Next: task 2 (Codex Phase 1 — AI_AGENT_ID + session-context.d/<id>.org). + +** 2026-05-30 ~17:45 CDT — task 2: Codex Phase 1 (AI_AGENT_ID) + +Fixed the singleton-session-context race backward-compatibly. New =.ai/scripts/session-context-path= helper resolves the active path from =AI_AGENT_ID=: unset → legacy =.ai/session-context.org= (one-agent default unchanged, per the spec's compatibility rule), set → =.ai/session-context.d/<sanitized-id>.org=. TDD: wrote session-context-path.bats (red, script absent), wrote the helper (green) — 5 cases (unset/empty/set/two-distinct/unsafe-chars). Wired startup.org's existence check + wrap-it-up.org's rename through the helper, each with a singleton fallback for older checkouts; wrap folds the agent id into the archive name. protocols.org documents the rule (new "Agent-scoped path" subsection). Verified the two-agent simulation (distinct paths per id) — the task's stated verification. sync-check clean, full suite 405/1skip + the 5 new bats green. Marked the [#B] task DONE. Pushed =9a1bea9..143feda=. The broader runtime-neutral arc stays parked under the parent [#C] spec. + +Both requested tasks (1 then 2) complete. Commits this session: 4b24597, 1f79945, 9a1bea9, 143feda (plus the wrap commit 86326c1 that closed the prior session). + +** 2026-05-30 ~22:00 CDT — inbox monitoring discussion + org-drill handoff (cmail discoverability) + +Craig asked to monitor the inbox + respond to handoffs, build infra for it, and discuss the act-vs-file rules + cadence. Discussed; Craig set the operating rule: when I decide to file → ask first (file = option 1 recommended, do-now = option 2); when I decide to act → just do it, no asking; always ask if unsure. + +Demonstrated the rule on the live org-drill handoff (cmail send was a working-but-invisible capability — an org-drill session claimed it couldn't send, then hand-rolled MIME through msmtp). All three asks read as act-now, so I did them, no asking: +- #1 + #2 (ddcde66, docs): added a "Sending Email" subsection to protocols.org (cmail = default personal account, dmail = work, cmail-action send = the tool, with examples); rewrote send-email.org Step 4 off the inline-Python/msmtp heredoc to cmail-action send. +- #3 (e446dab, feat, TDD): cmail-action send gained --cc/--bcc (repeatable) + --in-reply-to/--references via build_message; 4 new tests, test _args helper updated, 57 cmail tests + full suite 409/1skip green. +Confirmed back to org-drill via inbox-send; inbox empty. + +STILL OPEN — the monitoring infrastructure build. Craig resolved the act-vs-file rule but not: (a) cadence default (proposed: check at every task boundary during a session + opt-in background /loop), (b) project-workflow vs template scope, (c) new inbox-status script vs extend cross-agent-status. Need those calls before building the monitor-inbox workflow + script. + +** 2026-05-31 — monitoring infrastructure built (8c0eca8) + +Craig: "proceed with your recommendations. general workflow, for sure." Built all three recommendations as a template (general) workflow: +- =inbox-status= script (template, +x, mirror) — lists unprocessed handoffs (excludes .gitkeep / lint-followups.org / PROCESSED-*), exit 0 clean / 1 pending / 2 no-inbox-or-usage, =-q= count-only. 5 bats cases, live-verified. +- =monitor-inbox.org= template workflow — the cadence (task-boundary default + opt-in background =/loop=) + the act-vs-file decision rule + the reply discipline, layered over process-inbox.org (no duplication of the value gate). INDEX.org entry added. +- protocols.org "Inbox Monitoring Cadence" subsection (read every session) so the habit actually fires: check inbox-status at task boundaries, act-now silent / file asks (file = option 1) / ask if unsure, always reply to senders. +Verified: sync-check clean, full suite 409/1skip + 5 new bats green. The cadence is now active — checked the inbox at this boundary (0 pending). @@ -1176,45 +1176,6 @@ Broader refactor proposes runtimes/ adapter manifests, generic install commands, Before any implementation: needs a real review pass on the spec, and a decision on whether to do Phase 1 alone (low risk, fixes the race) vs commit to the larger arc. -** DONE [#B] Startup Phase A rsync propagates dirty rulesets WIP into downstream projects :feature: -CLOSED: [2026-05-30 Sat] -:PROPERTIES: -:CREATED: [2026-05-29 Fri] -:LAST_REVIEWED: 2026-05-29 -:END: -Fixed via option 1 (skip-when-dirty), scoped to the synced source paths: startup.org Phase A now guards the protocols/workflows/scripts rsyncs behind a =git status --porcelain= check on =claude-templates/.ai/{protocols.org,workflows/,scripts/}=, skipping the sync when any are dirty. The propagation anomaly (cross-project-broadcast.org / page-signal.org not reaching jr-estate) was a timeline artifact: both files were added in 664bf01 on 2026-05-29, after jr-estate's Phase A rsync had already run — correct behavior, not a bug. - -From jr-estate handoff 2026-05-29. When rulesets has uncommitted WIP at the moment a downstream project starts a session, Phase A.0 reports "dirty, skipping pull" and proceeds. Phase A's =rsync -a --delete= then runs against the dirty rulesets working tree and copies the WIP state into the downstream project's =.ai/workflows/= and =.ai/scripts/=. The downstream project's =git status= then shows drift the user did not author. Two bad recovery paths: commit the drift as "chore: sync .ai tooling from templates" (creates fake commit history about template state) or leave it dirty (noisy wrap-ups, pressure to commit anyway). - -Three options proposed in the handoff: -1. *Skip-when-dirty.* Make Phase A's workflows/ and scripts/ rsync no-op when Phase A.0 reports rulesets dirty. Simplest defense. -2. *Clean-files-only.* Restrict the rsync to files git considers unmodified in rulesets. Untracked files in rulesets do not propagate. Most precise. -3. *Clean-ref-based.* Cache the last-known-clean state as a git tag or ref and rsync from that ref rather than the working tree. Most decoupled, also the most infrastructure. - -Recommendation (mine): option 1. The downstream impact of skipping a sync once is small (the next session with rulesets clean catches up), and the implementation is one =if [ "$dirty" -eq 0 ]= guard around the existing rsync block. Option 2 adds shellout complexity per file; option 3 requires tagging discipline that has no other reason to exist. - -The original handoff also noted a related anomaly: even with =--delete=, two files that DO exist in rulesets canonical (=cross-project-broadcast.org=, =page-signal.org=) did NOT propagate to jr-estate. Worth confirming whether that was a transient rsync issue or evidence of a deeper Phase A bug. Could be ordering: those files were added to rulesets AFTER the jr-estate Phase A rsync ran, in which case the behavior is correct and the report is misreading the timeline. - -Source: =inbox/2026-05-29-0832-from-jr-estate-investigate-startup-rsync-carried-dirty.org= (processed and deleted). - -** DONE [#B] Codex Phase 1 — AI_AGENT_ID + session-context.d/<id>.org :feature: -CLOSED: [2026-05-30 Sat] -:PROPERTIES: -:CREATED: [2026-05-28 Thu] -:LAST_REVIEWED: 2026-05-28 -:END: -Shipped backward-compatibly. New =.ai/scripts/session-context-path= helper resolves the active path from =AI_AGENT_ID=: unset → the legacy =.ai/session-context.org= singleton (one-agent default unchanged, per the spec's compatibility rule), set → =.ai/session-context.d/<sanitized-id>.org=. startup.org's existence check and wrap-it-up.org's rename now resolve through the helper (with a singleton fallback for older checkouts); wrap folds the agent id into the archive name. protocols.org documents the rule. Verified: 5 bats cases + a two-agent simulation showing distinct paths per id. Larger runtime-neutral arc (runtimes/ manifests, launcher refactor) stays parked under the parent spec. - -Lifted from the broader codex runtime spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]]) as the immediate-correctness slice independent of the larger arc. The singleton =.ai/session-context.org= is unsafe under simultaneous agents — two LLMs running in the same project at the same time would overwrite each other's session state. - -Scope: introduce an =AI_AGENT_ID= environment variable and split the single =session-context.org= into a per-agent =session-context.d/<id>.org= directory. No other phases of the runtime refactor are in this task — keep the surface small, fix the race, ship. - -Touches: =.ai/protocols.org= (rename rule + recovery anchor), =.ai/workflows/startup.org= (Phase A check), wrap-up workflow (rename target), per-project session record discoverability. - -Verification: simulate two agents sharing a project (separate AI_AGENT_ID values) and confirm session-context writes land in distinct files without interleaving. - -Parent: see [[Generic agent runtime support — Codex spec v0]] above for the larger arc this is sliced from. - ** TODO [#B] Add Signal MCP server (rymurr/signal-mcp) :feature: SCHEDULED: <2026-05-29 Fri> :PROPERTIES: @@ -2431,3 +2392,40 @@ Files to update: Investigation: search =.ai/sessions/=, =.ai/notes.org=, inbox archive, and git log for mentions of these workflow docs. Identify review/response/design iterations, dates, and contributors (including agents where known: Claude Code, Codex, local models). Distinguish high-confidence history (commits, dated session entries) from inferred (chat-only context). Recommend whether enough evidence exists to populate the section, and draft the entries if so. Dependency: spec-review.org and spec-response.org have uncommitted edits in flight. Wait for those to land before writing to the files. The read-only research portion (search sessions, identify iterations, draft entries to a scratch file) can run in parallel without conflict. +** DONE [#B] Startup Phase A rsync propagates dirty rulesets WIP into downstream projects :feature: +CLOSED: [2026-05-30 Sat] +:PROPERTIES: +:CREATED: [2026-05-29 Fri] +:LAST_REVIEWED: 2026-05-29 +:END: +Fixed via option 1 (skip-when-dirty), scoped to the synced source paths: startup.org Phase A now guards the protocols/workflows/scripts rsyncs behind a =git status --porcelain= check on =claude-templates/.ai/{protocols.org,workflows/,scripts/}=, skipping the sync when any are dirty. The propagation anomaly (cross-project-broadcast.org / page-signal.org not reaching jr-estate) was a timeline artifact: both files were added in 664bf01 on 2026-05-29, after jr-estate's Phase A rsync had already run — correct behavior, not a bug. + +From jr-estate handoff 2026-05-29. When rulesets has uncommitted WIP at the moment a downstream project starts a session, Phase A.0 reports "dirty, skipping pull" and proceeds. Phase A's =rsync -a --delete= then runs against the dirty rulesets working tree and copies the WIP state into the downstream project's =.ai/workflows/= and =.ai/scripts/=. The downstream project's =git status= then shows drift the user did not author. Two bad recovery paths: commit the drift as "chore: sync .ai tooling from templates" (creates fake commit history about template state) or leave it dirty (noisy wrap-ups, pressure to commit anyway). + +Three options proposed in the handoff: +1. *Skip-when-dirty.* Make Phase A's workflows/ and scripts/ rsync no-op when Phase A.0 reports rulesets dirty. Simplest defense. +2. *Clean-files-only.* Restrict the rsync to files git considers unmodified in rulesets. Untracked files in rulesets do not propagate. Most precise. +3. *Clean-ref-based.* Cache the last-known-clean state as a git tag or ref and rsync from that ref rather than the working tree. Most decoupled, also the most infrastructure. + +Recommendation (mine): option 1. The downstream impact of skipping a sync once is small (the next session with rulesets clean catches up), and the implementation is one =if [ "$dirty" -eq 0 ]= guard around the existing rsync block. Option 2 adds shellout complexity per file; option 3 requires tagging discipline that has no other reason to exist. + +The original handoff also noted a related anomaly: even with =--delete=, two files that DO exist in rulesets canonical (=cross-project-broadcast.org=, =page-signal.org=) did NOT propagate to jr-estate. Worth confirming whether that was a transient rsync issue or evidence of a deeper Phase A bug. Could be ordering: those files were added to rulesets AFTER the jr-estate Phase A rsync ran, in which case the behavior is correct and the report is misreading the timeline. + +Source: =inbox/2026-05-29-0832-from-jr-estate-investigate-startup-rsync-carried-dirty.org= (processed and deleted). +** DONE [#B] Codex Phase 1 — AI_AGENT_ID + session-context.d/<id>.org :feature: +CLOSED: [2026-05-30 Sat] +:PROPERTIES: +:CREATED: [2026-05-28 Thu] +:LAST_REVIEWED: 2026-05-28 +:END: +Shipped backward-compatibly. New =.ai/scripts/session-context-path= helper resolves the active path from =AI_AGENT_ID=: unset → the legacy =.ai/session-context.org= singleton (one-agent default unchanged, per the spec's compatibility rule), set → =.ai/session-context.d/<sanitized-id>.org=. startup.org's existence check and wrap-it-up.org's rename now resolve through the helper (with a singleton fallback for older checkouts); wrap folds the agent id into the archive name. protocols.org documents the rule. Verified: 5 bats cases + a two-agent simulation showing distinct paths per id. Larger runtime-neutral arc (runtimes/ manifests, launcher refactor) stays parked under the parent spec. + +Lifted from the broader codex runtime spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org]]) as the immediate-correctness slice independent of the larger arc. The singleton =.ai/session-context.org= is unsafe under simultaneous agents — two LLMs running in the same project at the same time would overwrite each other's session state. + +Scope: introduce an =AI_AGENT_ID= environment variable and split the single =session-context.org= into a per-agent =session-context.d/<id>.org= directory. No other phases of the runtime refactor are in this task — keep the surface small, fix the race, ship. + +Touches: =.ai/protocols.org= (rename rule + recovery anchor), =.ai/workflows/startup.org= (Phase A check), wrap-up workflow (rename target), per-project session record discoverability. + +Verification: simulate two agents sharing a project (separate AI_AGENT_ID values) and confirm session-context writes land in distinct files without interleaving. + +Parent: see [[Generic agent runtime support — Codex spec v0]] above for the larger arc this is sliced from. |
