aboutsummaryrefslogtreecommitdiff
path: root/.claude/commands/respond-to-cj-comments.md
blob: 2f160994d43a066ba4dbb99d4b7797a14072616d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
---
description: Scan an org file for cj comments — Craig's annotations wrapped in `#+begin_src cj: ... #+end_src` source blocks — and process each via subagent-delegated accuracy. Each item is classified instruction / question / both, then dispatched to an instruction subagent (proposes a file:line patch) or a question subagent (researches with explicit scope, reports answer + evidence + confidence). Main thread reviews proposals before editing; subagents don't write to the source file. Org-mode TODO parents flip to DOING; new content lands under timestamped subheadings one level deeper; on completion, top- and second-level tasks advance to `DONE` while deeper tasks get their heading rewritten to a dated action description (no DONE keyword), becoming an in-place event log. VERIFY tasks at `***` and deeper flip to dated log entries with body replaced by the answer or action taken; a top-level (`**`) VERIFY instead closes as `DONE`/`CANCELLED` + `CLOSED:` like any top-level task, the answer in its body. Public-facing writing (commits, PRs, Slack, email, public docs) gets `/voice personal`; private writing skips it. Summary lists handled instructions, answered questions with evidence + confidence, follow-ups, unresolved items, and an explicit clean / N-remain verdict. Anything needing Craig's input becomes a `VERIFY` task in `todo.org` (top-level or first-level child of a parent task — never deeper) rather than a separate summary file. File/URL references render as clickable org-mode links. Use when an org file accumulates cj comments. Do NOT use for general code review (`/review-code`), new work without cj comments, or trivial items.
---

# /respond-to-cj-comments — Process cj Comments in an Org File

Scan an org file for cj comments (Craig's instructions and questions wrapped in `#+begin_src cj: ... #+end_src` source blocks) and handle each one with subagent-delegated accuracy. Used to batch-process notes Craig leaves in his org files for later action.

## Usage

```
/respond-to-cj-comments [FILE_PATH]
```

If no file is given, ask the user for the target file. If the user references "this file" or similar with a visible editor buffer, confirm the path before starting.

## What counts as a cj comment

A cj comment is Craig's instruction or question wrapped in an org source-block:

```
#+begin_src cj: comment
my next task is to review the photo Eric sent of the branching strategy from
the offsite. Brainstorm with me on what tasks we should create — actionable
ones about both documentation and execution.
#+end_src
```

That's the only form the skill recognizes. Craig keeps all cj annotations in his org files (`todo.org`, daily-prep docs, scratch org notes) — never in source code, configs, markdown, or anything else that gets checked into a non-org artifact. If a cj annotation is about a code change, it lives in the relevant org task body referencing the source path, not in the code file itself. One rule, one place to look.

The `cj:` tag goes where a source-block language identifier normally goes (org doesn't execute it — it's a structural marker that lets the whole block fold and render as a unit). The instruction body is everything between the `#+begin_src cj:` opening line and the matching `#+end_src` line; the body doesn't need any `cj:` prefix on continuation lines because the fences carry the scope.

Common variants:
- `#+begin_src cj: comment` — what Craig's yasnippet emits (`cj` + Tab expands the full fence).
- `#+begin_src cj:` — no trailing label, still valid.
- `#+begin_src cj: <any short label>` — any label after the colon is fine; the parser ignores it.

Removal at cleanup time deletes all three parts: the `#+begin_src cj:` opening line, the body lines, and the closing `#+end_src` line. Don't leave one fence behind.

**Legacy inline `cj:` lines (pre-2026-05-15).** Some older org files may still contain inline `cj: ...` annotations from before the source-block-only convention. Parse them defensively when encountered — treat each as a one-line item and clean up by deleting the line on resolution. Don't author new inline `cj:` lines anywhere going forward.

## Instructions

### 0. Cross-Project Boundary Check (run before reading the file)

Before scanning the target file, compare its path against the current cwd. If the file lives under a *different* project's `.ai/`-scoped root than the cwd does, stop and surface the boundary crossing — don't read the file yet.

Detection: find the nearest ancestor of the target path that contains an `.ai/` directory (or, lacking that, the nearest ancestor that is a git repo root). Do the same for cwd. If the two roots differ, this is a cross-project invocation.

When triggered, present inline numbered options (no popup):

```
The target <path> looks like it belongs to <other-project>'s session
(its root is <other-root>, the current cwd is <cwd-root>).

1. Do it from here — I'll process the file and drop a handoff note in <other-project>/inbox/ so the other project's next session picks up the carry-forward.
2. Switch projects — stop here; reopen Claude with cwd = <other-root> and re-run.

Pick a number.
```

Wait for the answer:

- **Option 1 ("do it from here")** — proceed. Plan to write a handoff file at `<other-project>/inbox/YYYY-MM-DD-handoff-from-<this-project>-<topic>.org` as part of the cleanup pass at the end of the run. The handoff covers: scope of changes, files touched, carry-forward context, any pending Craig-asks (VERIFY entries, drafts awaiting approval), and subagent-output traceability.
- **Option 2 ("switch projects")** — stop the skill, output a short confirmation, exit. Do not read the file.

If the target file is *inside* the cwd's project root, skip this step silently.

Canonical rule: `~/code/rulesets/claude-rules/cross-project.md`.

### 1. Scan the file

**Prefer the script.** If `.ai/scripts/cj-scan.py` exists in the project (it ships with claude-templates and rsync'd into every project on startup), invoke it instead of stitching the picture together with grep + Read:

```bash
python3 .ai/scripts/cj-scan.py <target-file.org>
```

The script outputs JSON with three top-level keys:
- `cj_blocks` — every cj annotation with `file`, `form` (source-block or legacy-inline), `start_line`, `end_line`, `body`, `label`, `parent_heading_chain`, `parent_depth`.
- `verify_tasks` — every VERIFY heading with `line`, `depth`, `heading`, `valid_depth`, `promotion_target`. Use this to flag buried VERIFYs (`valid_depth=false`) and propose promotion before cleanup ends.
- `unclosed_blocks` — any source-block fence that opened but never closed (handle as Unresolved in the summary).

**Fall back to grep + Read** when the script isn't installed: scan for `#+begin_src cj:` and (defensively) `^cj:` lines, then read the surrounding context to reconstruct each block's parent heading chain. This is the slow path; prefer the script.

For each cj item collected, record:

- File path and line range (open fence → close fence for source-block; the single line for legacy inline)
- Enclosing context: the parent heading chain (e.g. `Parent ▸ Subheading ▸ TODO Foo`)
- The full comment body
- Whether the item is a source-block (`#+begin_src cj: ... #+end_src`) or legacy inline (`cj: ...` line) so cleanup deletes the right shape

### 2. Classify each item

For each cj comment, decide whether it's:

- **Instruction** — a request for action. Signals: imperative verbs (check, rewrite, fix, remove, add, draft), "please do X".
- **Question** — a request for information. Signals: ends with `?`, starts with who/what/when/where/why/how, "is this", "does this", "should we".
- **Both** — contains an instruction and a question. Handle the instruction side, answer the question side.

When truly ambiguous, treat as both.

### 3. Delegate to subagents — accuracy over speed

For each non-trivial item, spawn an Agent subagent. Trivial items (e.g. "remove this blank line") the main thread can handle directly without delegation.

Two classes of subagent:

- **Instruction subagent** — given the comment, the enclosing context, and the file path, figures out what change is needed and reports a concrete recommendation. Reports: what should change, file paths + line numbers, any follow-up the user needs to decide.
- **Question subagent** — researches the question. For questions requiring codebase exploration, ticket lookups, web research, or cross-file reasoning, give the subagent explicit scope (files to read, tickets to check, search terms). Reports: direct answer, evidence (file:line refs, quotes, sources), confidence level, any remaining unknowns.

Run subagents in parallel when the items are independent. Wait for review between batches if items depend on each other.

Prompt every subagent with four required fields (see `subagents.md` for the full contract):

1. **Scope** — one bounded comment, named file, specific action or question
2. **Context** — paste the comment verbatim plus the surrounding context from step 1
3. **Constraints** — do not touch other cj comments, do not refactor unrelated code, preserve file formatting
4. **Output format** — for instructions: a specific change proposal (before/after or file:line patch), plus URLs or file paths for every external source consulted. For questions: answer + evidence (including URLs or file:line refs for every claim) + confidence level + under 300 words. Subagents must cite sources. A claim without a URL or file reference doesn't belong in the report.

The main thread applies edits. Subagents report; they do not write to the source file. This keeps formatting consistent and makes review easier.

**Accuracy over speed is the rule.** Three subagents and fifteen minutes to answer one question correctly beats a fast wrong answer.

### 4. Apply changes

For **instructions**:

1. Review the subagent's proposed change before applying. Check that it matches the comment's intent and doesn't introduce a new issue. If the proposal looks wrong or incomplete, dispatch a fix subagent with the failure report as its context. Don't retry the diagnosis in the main thread (see the Context-Pollution Rule in `subagents.md`). After two failed fix attempts, stop and surface the problem to the user.
2. Apply the change once the proposal is sound. Edits come from the main thread.
3. **Org-mode subheader format.** When inserting new content under an existing org-mode task (research findings, drafted messages, log entries, recorded Slack replies), use a timestamped subheader one level deeper than the parent task:

   ```
   *** 2026-04-23 Thu @ 15:20:52 -0500 <short description>
   <content>
   ```

   Use one more `*` than the parent task's heading level. If the parent is `** TODO`, the subheader is `***`. If the parent is `**** TODO`, the subheader is `*****`. Generate the timestamp with `date "+%Y-%m-%d %a @ %H:%M:%S %z"` so it's accurate, not estimated.

4. **Surface URLs.** If the subagent's output includes URLs, file paths, or external references, list them under the updated task content. After applying the edit, offer to convert them into explicit org-mode links (`[[url][label]]` or `[[file:path][label]]`) at the location where the cj comment originated, or elsewhere in the task if that fits better.

5. If the comment is inside an org-mode `TODO` heading, mark that `TODO` as `DOING` when work begins. **When the work is complete, follow the depth-based rule in [todo-format.md → Completion](../../claude-rules/todo-format.md):**

   - **Regular `TODO`/`DOING` at `*` or `**`** — advance to `DONE` + `CLOSED:` line; the keyword and original heading stay visible in the agenda.
   - **Regular `TODO`/`DOING` at `***` and deeper** — rewrite the heading to `<depth> YYYY-MM-DD Day @ HH:MM:SS -ZZZZ <past-tense description>`; drop the keyword/priority/tags.
   - **`VERIFY` — depth decides the heading.** At `***` and deeper, a dated-heading rewrite. At `**`, a terminal keyword (`DONE`/`CANCELLED` + `CLOSED:`) like any top-level task — never a dated `**` header. Either way, replace the body with the information Craig provided (when the VERIFY was a question) or a description of the action taken (when it was an instruction / pending-decision marker).

   **VERIFY-answer pattern.** When a cj annotation's `parent_heading_chain` ends with a `VERIFY ...` heading (i.e., the cj sits directly inside a VERIFY task), the cj is Craig's answer to the question that VERIFY held open. The cj content is the source for the resolved body. Two shapes:

   - *Direct answer.* The cj body IS the answer (a value, decision, link, paste from elsewhere). Lift the cj body verbatim into the new dated body; trim filler ("okay," "approved," "yes,") that isn't load-bearing.
   - *Indirect answer.* The cj points at where the answer lives ("Kostya gave this in Slack — pull it from DM channel X," "see the attached doc"). Execute the instruction first (per step 3 — subagent if research is needed), then the resolved info becomes the dated body.

   Both shapes land at the same end state:

   1. Generate the timestamp with `date "+%Y-%m-%d %a @ %H:%M:%S %z"`.
   2. Rewrite the VERIFY heading by depth: at `***` and deeper, its dated form with a short summary of what got answered; at `**`, a `DONE`/`CANCELLED` keyword + `CLOSED:` line with the heading text kept.
   3. Replace the body with the resolved info (the cj body for direct, the executed result for indirect).
   4. Delete the cj annotation — it's now folded into the body. Don't keep both.

   Detection signal from `cj-scan`: a cj block whose `parent_heading_chain[-1].heading` starts with `VERIFY`.

   Leave a still-in-progress task as `DOING` for the user; only the *completed* ones get the `DONE`-or-dated-rewrite. (Feedback memory: `feedback_done_tasks_become_dated_log_headings` mirrors the rule.)

6. Remove the cj comment from the file. **Prefer the script:**

   ```bash
   python3 .ai/scripts/cj-remove-block.py --file <target> --start <N> --end <M>
   ```

   `cj-remove-block` validates that lines `N..M` actually look like a cj annotation before deleting (a `#+begin_src cj:` / `#+end_src` fence pair, or a single `cj:` line) and refuses if they don't. Use the `start_line`/`end_line` values from `cj-scan`'s output. This protects against accidentally trimming the wrong block when working with long bodies where exact-match Edit is fragile.

   Fall back to the Edit tool when the script isn't installed: for a source-block item delete all three parts (`#+begin_src cj:` opening line, body, `#+end_src` closing line); for a legacy inline item delete the single line.

For **questions**:

1. Capture the answer in the summary (step 5).
2. Remove the cj comment. The user can re-open the thread conversationally if they have follow-ups.

For **writing destined for public channels** (commit messages, PR descriptions, PR comments, Slack or email messages, public docs):

1. Invoke `/voice personal` on the draft. The skill walks 39 patterns covering the signs of AI writing, universal good-writing rules (Strunk & White, Orwell, Plain English, Garner), and personal voice patterns (first-person rewrite, semicolons → periods/commas, contractions, sentence-split, felt-experience cut, sentence-fragment rewrite, terse cut, public-artifact scope flag).

2. Scan the output for AI-attribution tells. If you catch yourself having written any of these, stop, delete, and rewrite:
   - `Co-Authored-By: Claude`
   - `Generated with Claude Code` (with or without the robot emoji)
   - "Created with Claude Code"
   - "Assisted by AI"

   Rewrite as Craig would write it: concise, focused on the content, with no mention of how the text was produced.

If the writing will be *posted* (not just saved as a draft), follow the Review and Publish flow in `commits.md` — draft to `/tmp/`, open in `emacsclient -n`, wait for Craig's explicit approval before posting.

**Private writing** (todo.org entries, session-context.org, scratch notes, internal rulesets) skips `/voice personal`. Use `/voice general` for the AI-detection + universal-good-writing passes when relevant, but the overhead of a draft-and-approve cycle is not warranted for internal notes.

### 5. Report

Produce one summary at the end, structured:

```
## Summary

### Instructions (N)

1. <file:line> <one-line recap>
   → done. <brief what-changed>.
   → TODO status: <DOING | unchanged>.
2. ...

### Questions (N)

1. <file:line> Q: <comment verbatim, trimmed to one line>
   A: <direct answer>
   Evidence: <file:line refs, ticket IDs, URLs, quotes>
   Confidence: <high | medium | low with caveat>
2. ...

### Follow-ups

- <anything the user needs to decide, review, or act on>

### Unresolved

- <any cj comments that couldn't be handled — say why, leave them in place>

### File state

State explicitly one of:
- "File is now clean. All cj comments resolved and removed."
- "File still contains N unresolved cj comment(s), listed under Unresolved above."

Never leave the reader guessing about whether the file is ready for follow-up work.
```

Keep answers direct. If a question has a simple answer, one sentence. If it needs nuance, two or three. Do not pad. The user reads the summary, not the intermediate work.

**Items needing Craig's input go to `todo.org`, not a summary file.** When the run leaves something that needs Craig to decide, answer, or approve — a blocker, an open question, a draft awaiting sign-off, anything in the Follow-ups list above that requires his action — add a `VERIFY` task in `todo.org` under the parent task it belongs to (the one whose subject it concerns). Name the heading so the question or ask is self-evident on scan.

**Placement rule — sibling of the trigger.** Place a new VERIFY as a *sibling* of the heading that triggered its creation:

- Trigger at `**` → VERIFY at `**` (sibling of the trigger, under the same `*` section).
- Trigger at `***` → VERIFY at `***` (sibling under the same `**` parent).
- Trigger at `****` or deeper → VERIFY climbs to `***` (the deepest valid depth); the trigger's parent tree gets flagged for flattening.
- Trigger at `*` (top-level section) → VERIFY at `**`.

Valid VERIFY depths are `**` and `***` only — never deeper. File placement: insert the new VERIFY after the trigger's entire sub-tree ends, alongside any other sub-tasks and dated logs already under the same `**` parent. Without the sibling rule, VERIFYs accumulate one level deeper than the trigger every time and the file goes vertical fast. Canonical rule: [todo-format.md § VERIFY tasks → Creating a new VERIFY](../../claude-rules/todo-format.md).

The placement constraint applies to *new* VERIFYs this skill creates and to *existing* VERIFYs the skill encounters at `****+` — flatten the buried ones up to one of the two allowed depths as part of the cleanup pass.

Form:

```
** VERIFY <self-evident question or ask>            (sibling of a ** trigger)

** TODO [#A] Parent task
*** Some sub-task or dated log under Parent task
*** VERIFY <self-evident question or ask>           (sibling of the *** trigger)
```

Do **not** append a `cj: <placeholder>` line beneath the heading. A well-named VERIFY heading carries the question on its own, scans cleanly in the agenda, and Craig adds his own `#+begin_src cj: ... #+end_src` annotation when he's ready to answer — that's the signal to come back and process the response. Leaving an empty `cj: <fill in>` placeholder is noise.

Pair the VERIFY task with a dated child header for the work-log entry where one fits (`*** YYYY-MM-DD Day @ HH:MM:SS -ZZZZ <desc>` — generate the timestamp with `date "+%Y-%m-%d %a @ %H:%M:%S %z"`). Do **not** default to writing a summary file in `/tmp/` and opening it in `emacsclient` — Craig prefers the in-place `VERIFY` task: it lives next to the work, surfaces in his agenda, and he resolves it inline rather than having to go find a separate doc. The chat summary above still gets written (it's the FYI recap); the `VERIFY` task is the durable home for anything he must act on. (Craig's standing instruction, 2026-05-12; the no-placeholder rule added 2026-05-14.)

**Org-mode links where they help.** When you reference a file or URL — in the chat summary or in a `todo.org` entry — use clickable org-mode link form with absolute paths (`[[file:/absolute/path][label]]`, `[[https://...][label]]`), not `=verbatim=` paths, which aren't clickable in Emacs.

### 6. Cleanup pass

Remove every cj comment that was handled in step 4 (instructions done) or step 5 (questions answered). The file is clean after the skill runs. Any comment left unresolved stays in place and is listed under `### Unresolved` in the summary with the reason.

Confirm the cleanup by re-scanning the file after removals. If any `cj:` line survives that shouldn't, remove it and note the correction.

### 7. Cross-project handoff (only if step 0 triggered)

If step 0 detected a cross-project invocation and Craig picked option 1, write the handoff before exiting:

```
<other-project>/inbox/YYYY-MM-DD-handoff-from-<this-project>-<topic>.org
```

Contents:

- Top-of-file note: this work happened cross-project. The acting Claude was running in `<this-project>` cwd; the file lives in `<other-project>`. The target project's next Claude reads this during inbox processing and folds the work-log into its own `session-context.org` before deleting the handoff.
- Scope of changes: what cj items were processed, what was changed, what's still open.
- Files touched: full paths, line-level granularity where it helps.
- Pending Craig-asks: every `VERIFY` entry the run created or left in place.
- Subagent traceability: which subagents ran, what they cited, what changes they proposed.
- Carry-forward findings: anything substantive the next session needs to know.

Mention the handoff in the current session's own `session-context.org` too, so both projects' logs are internally consistent.

See `~/code/rulesets/claude-rules/cross-project.md` for the canonical rule.

## Principles

- **Accuracy > speed.** Subagent generously. A wrong answer to a cj comment is worse than a slow one.
- **Don't guess.** If a question needs verification and verification isn't possible, say so. Surface unknowns rather than fabricate.
- **Preserve the file.** Don't reformat surrounding lines. Don't reorder tasks. Touch only what the comment asks for, plus the comment's own removal.
- **The user reads the summary, not the process log.** Write summaries that are directly useful.
- **Public writing gets `/voice personal`. Private writing doesn't.** Don't over-process internal notes.
- **Don't write the literal token `cj:` in chat replies, summaries, or todo.org entries you author.** Refer to items as "cj comment(s)" instead. Craig greps his files for `cj:` to find pending annotations; my output should not add noise to that search. ("the cj comment at line 442 asked…", not "the cj: at line 442 asked…"; "per Craig's cj comment", not "per Craig's cj:". The token belongs in the source file Craig wrote, not in my replies about it.)

## Anti-patterns

- Handling complex cj items inline in the main thread instead of subagenting.
- Batching unrelated cj comments into one giant subagent prompt.
- Removing a cj comment before the user has seen the answer in the summary.
- Skipping the `/voice personal` pass on public-facing writing because it "looked fine already."
- Guessing on a question instead of spawning a research subagent.
- Letting a subagent edit the source file directly — review surface loss.

## Example

Input file: `todo.org` containing:

```
** TODO Draft the D2P2 Pillar 1 writeup
#+begin_src cj: comment
what do we actually know about Orion's Belt's partner API contract?
#+end_src
#+begin_src cj: comment
check whether Redwire's AdTech feed is still in scope. Eric mentioned deprecating it in sprint planning.
#+end_src
```

Skill run:

1. Scans, finds two cj items (one question, one instruction-with-verification).
2. Marks the parent `** TODO` as `DOING`.
3. Spawns two subagents in parallel:
   - **Q subagent:** reads `deepsat/knowledge.org`, greps ticket history for "Orion's Belt API", checks recent meeting transcripts. Reports findings with evidence.
   - **Instruction-with-verification subagent:** reads sprint-planning transcripts, searches for "Redwire AdTech deprecation", checks Linear for related tickets. Reports whether the feed is still in scope.
4. Main thread applies the `DOING` status change, writes the summary with both answers, removes both cj blocks (fences and all).
5. Reports:
   - Q1: What we know about Orion's Belt's partner API contract → answer + file:line refs + confidence.
   - Q2/Instruction: Redwire AdTech scope → answer + evidence + recommendation for whether to cite in Pillar 1.

Craig reads the summary, decides what to do with the Redwire finding, and the TODO stays in `DOING` until he advances it.