diff --git a/README.md b/README.md index bf969241..21a8491b 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ A Claude Code plugin that provides iterative development with independent AI rev The loop has two phases: **Implementation** (Claude works, Codex reviews summaries) and **Code Review** (Codex checks code quality with severity markers). Issues feed back into implementation until resolved. + ## Install ```bash @@ -45,7 +46,7 @@ Requires [codex CLI](https://github.com/openai/codex) for review. See the full [ /humanize:gen-plan --input draft.md --output docs/plan.md ``` -2. **Refine an annotated plan** before implementation when reviewers add `CMT:` ... `ENDCMT` comments: +2. **Refine an annotated plan** before implementation when reviewers add comments (`CMT:` ... `ENDCMT`, `` ... ``, or `` ... ``): ```bash /humanize:refine-plan --input docs/plan.md ``` diff --git a/commands/refine-plan.md b/commands/refine-plan.md index fc129016..0d97142f 100644 --- a/commands/refine-plan.md +++ b/commands/refine-plan.md @@ -34,7 +34,7 @@ The refined plan MUST reuse the existing `gen-plan` schema. Do not invent new to 1. **Execution Mode Setup**: Parse CLI arguments and derive output paths 2. **Load Project Config**: Resolve `alternative_plan_language` and mode defaults using `config-loader.sh` semantics 3. **IO Validation**: Run `validate-refine-plan-io.sh` -4. **Comment Extraction**: Scan the annotated plan and extract valid `CMT:` / `ENDCMT` blocks +4. **Comment Extraction**: Scan the annotated plan and extract valid comment blocks (`CMT:`/`ENDCMT`, ``/``, ``/``) 5. **Comment Classification**: Classify each extracted comment for downstream handling 6. **Comment Processing**: Answer questions, apply requested plan edits, and perform targeted research 7. **Plan Refinement**: Produce the comment-free refined plan while preserving the `gen-plan` structure @@ -167,7 +167,7 @@ Handle exit codes exactly: - Exit code 0: Continue to Phase 2 - Exit code 1: Report `Input file not found` and stop - Exit code 2: Report `Input file is empty` and stop -- Exit code 3: Report `Input file has no CMT:/ENDCMT blocks` and stop +- Exit code 3: Report `Input file has no comment blocks` and stop - Exit code 4: Report `Input file is missing required gen-plan sections` and stop - Exit code 5: Report `Output directory does not exist or is not writable - please fix it` and stop - Exit code 6: Report `QA directory is not writable` and stop @@ -196,17 +196,32 @@ Track these states while scanning the validated input in document order: Extraction rules: -1. Recognize `CMT:` as the start marker and `ENDCMT` as the end marker. -2. Support both inline and multi-line blocks: +1. Support three comment formats: + - Classic: `CMT:` as start marker and `ENDCMT` as end marker + - Short tag: `` as start marker and `` as end marker + - Long tag: `` as start marker and `` as end marker +2. Support both inline and multi-line blocks for all formats: - Inline: `Text before CMT: comment text ENDCMT text after` + - Inline: `Text before comment text text after` + - Inline: `Text before comment text text after` - Multi-line: ```markdown CMT: comment text ENDCMT ``` -3. Ignore `CMT:` and `ENDCMT` sequences inside fenced code blocks. -4. Ignore `CMT:` and `ENDCMT` sequences inside HTML comments. + ```markdown + + comment text + + ``` + ```markdown + + comment text + + ``` +3. Ignore comment markers inside fenced code blocks. +4. Ignore comment markers inside HTML comments. 5. Update `NEAREST_HEADING` whenever a Markdown heading is encountered outside fenced code and HTML comments. 6. Preserve surrounding non-comment text when removing inline comment blocks from the working plan text. 7. Assign raw comment IDs in document order as `CMT-1`, `CMT-2`, ... only for non-empty blocks. @@ -217,7 +232,7 @@ Extraction rules: For each non-empty comment block, capture: - `id` (`CMT-N`) -- `original_text` exactly as written between `CMT:` and `ENDCMT` +- `original_text` exactly as written between the comment markers - `normalized_text` with surrounding whitespace trimmed - `start_line`, `start_column` - `end_line`, `end_column` @@ -230,8 +245,8 @@ For each non-empty comment block, capture: These are fatal extraction errors: -1. Nested `CMT:` while already inside a comment block -2. `ENDCMT` encountered while not inside a comment block +1. Nested comment start marker while already inside a comment block +2. Comment end marker encountered while not inside a comment block or wrong end marker for the format 3. End of file reached while still inside a comment block Every fatal parse error MUST report: @@ -243,9 +258,9 @@ Every fatal parse error MUST report: Examples of acceptable messages: -- `Comment parse error: nested CMT block at line 48, column 3 near "## Acceptance Criteria" (context: "CMT: split AC-2...")` -- `Comment parse error: stray ENDCMT at line 109, column 1 near "## Task Breakdown" (context: "ENDCMT")` -- `Comment parse error: missing ENDCMT for block opened at line 72, column 5 near "## Dependencies and Sequence"` +- `Comment parse error: nested comment block at line 48, column 3 near "## Acceptance Criteria" (context: "split AC-2...")` +- `Comment parse error: stray comment end marker at line 109, column 1 near "## Task Breakdown" (context: "")` +- `Comment parse error: missing end marker for block opened at line 72, column 5 near "## Dependencies and Sequence"` ### Outputs from Phase 2 @@ -403,7 +418,7 @@ Optional sections that MUST be preserved when present in the input: ### Refinement Rules -1. Remove every resolved `CMT:` / `ENDCMT` tag and all enclosed comment text from the refined plan. +1. Remove every resolved comment marker and all enclosed comment text from the refined plan. 2. Do not add any new top-level schema section. 3. Preserve `AC-X` / `AC-X.Y` formatting. 4. Preserve task IDs unless a comment explicitly requests a structural change. @@ -429,7 +444,7 @@ Rules: Before generating the QA document, verify: 1. All required sections are still present -2. No `CMT:` or `ENDCMT` markers remain +2. No comment markers remain 3. Every referenced `AC-*` exists 4. Every task dependency references an existing task ID or `-` 5. Every task row has exactly one valid routing tag: `coding` or `analyze` diff --git a/docs/usage.md b/docs/usage.md index e12d45b9..0ef06046 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -46,7 +46,7 @@ The quiz is advisory, not a gate. You always have the option to proceed. But tha ```bash /humanize:gen-plan --input draft.md --output docs/plan.md ``` -2. If the plan is reviewed with `CMT:` ... `ENDCMT` annotations, refine it and generate a QA ledger: +2. If the plan is reviewed with comment annotations, refine it and generate a QA ledger: ```bash /humanize:refine-plan --input docs/plan.md ``` @@ -127,7 +127,7 @@ Workflow: 5. Generates a structured plan.md with acceptance criteria 6. Optionally starts `/humanize:start-rlcr-loop` if `--auto-start-rlcr-if-converged` conditions are met -If reviewers later annotate the generated plan with `CMT:` ... `ENDCMT` blocks, run +If reviewers later annotate the generated plan with comment blocks, run `/humanize:refine-plan --input ` before starting or resuming implementation. ### refine-plan @@ -169,9 +169,10 @@ how each comment was handled. **Annotated comment block format:** -`refine-plan` looks for reviewer comments wrapped in `CMT:` and `ENDCMT` markers. Both inline -and multi-line comment blocks are supported: +`refine-plan` supports three comment formats for reviewer annotations. Both inline +and multi-line comment blocks are supported in all formats: +**Classic format (CMT:/ENDCMT):** ```markdown Text before CMT: clarify why AC-3 is split here ENDCMT text after ``` @@ -183,11 +184,36 @@ If the dependency is unclear, add a pending decision instead of guessing. ENDCMT ``` +**Short tag format ():** +```markdown +Text before clarify why AC-3 is split here text after +``` + +```markdown + +Please investigate whether this task should depend on task4 or task5. +If the dependency is unclear, add a pending decision instead of guessing. + +``` + +**Long tag format ():** +```markdown +Text before clarify why AC-3 is split here text after +``` + +```markdown + +Please investigate whether this task should depend on task4 or task5. +If the dependency is unclear, add a pending decision instead of guessing. + +``` + Rules: -- At least one non-empty `CMT:` block must exist in the input file. -- `CMT:` and `ENDCMT` markers inside fenced code blocks or HTML comments are ignored. +- At least one non-empty comment block must exist in the input file. +- Comment markers inside fenced code blocks or HTML comments are ignored. - Empty comment blocks are removed but do not create QA ledger entries. - The input plan must still follow the `gen-plan` section schema. +- All three formats can be mixed within the same file. **QA output structure:** diff --git a/scripts/validate-refine-plan-io.sh b/scripts/validate-refine-plan-io.sh index f0ca70c0..4ed807f5 100755 --- a/scripts/validate-refine-plan-io.sh +++ b/scripts/validate-refine-plan-io.sh @@ -5,7 +5,7 @@ # 0 - Success, all validations passed # 1 - Input file does not exist # 2 - Input file is empty -# 3 - Input file has no valid CMT:/ENDCMT blocks or has malformed CMT syntax +# 3 - Input file has no valid comment blocks or has malformed comment syntax # 4 - Input file missing required gen-plan sections # 5 - Output directory does not exist or is not writable, or input directory is not writable for in-place mode # 6 - QA directory not writable @@ -51,14 +51,67 @@ scan_cmt_blocks() { heading = current_heading() if (kind == "nested") { - printf "Comment parse error: nested CMT block at line %d, column %d near \"%s\" (context: \"%s\")\n", line_num, column, heading, excerpt > "/dev/stderr" + printf "Comment parse error: nested comment block at line %d, column %d near \"%s\" (context: \"%s\")\n", line_num, column, heading, excerpt > "/dev/stderr" } else if (kind == "stray_end") { - printf "Comment parse error: stray ENDCMT at line %d, column %d near \"%s\" (context: \"%s\")\n", line_num, column, heading, excerpt > "/dev/stderr" + printf "Comment parse error: stray comment end marker at line %d, column %d near \"%s\" (context: \"%s\")\n", line_num, column, heading, excerpt > "/dev/stderr" } exit fatal_code } + function find_comment_markers(text, start_pos, markers, i, pos, min_pos, closest_marker, closest_pos) { + # Initialize markers array + markers["CMT:"] = "classic_start" + markers[""] = "cmt_tag_start" + markers[""] = "comment_tag_start" + markers["ENDCMT"] = "classic_end" + markers[""] = "cmt_tag_end" + markers[""] = "comment_tag_end" + markers[""] = "html_end" + + closest_marker = "" + closest_pos = 0 + min_pos = length(text) + 1 + + for (marker in markers) { + pos = index(substr(text, start_pos), marker) + if (pos > 0) { + pos = start_pos + pos - 1 + if (pos < min_pos) { + min_pos = pos + closest_marker = marker + closest_pos = pos + } + } + } + + if (closest_marker == "") { + return "" + } else { + return closest_marker "|" closest_pos + } + } + + function get_end_marker_for_format(format) { + if (format == "classic") return "ENDCMT" + if (format == "cmt_tag") return "" + if (format == "comment_tag") return "" + return "" + } + + function get_marker_length(marker) { + if (marker == "CMT:") return 4 + if (marker == "") return 5 + if (marker == "") return 9 + if (marker == "ENDCMT") return 6 + if (marker == "") return 6 + if (marker == "") return 10 + if (marker == "") return 3 + return 0 + } + BEGIN { count = 0 in_fence = 0 @@ -71,6 +124,7 @@ scan_cmt_blocks() { cmt_open_heading = "Preamble" cmt_open_excerpt = "" cmt_has_text = 0 + cmt_format = "" # Track format: "classic", "cmt_tag", "comment_tag" fatal = 0 fatal_code = 0 } @@ -126,26 +180,8 @@ scan_cmt_blocks() { } if (in_cmt) { - html_rel = index(rest, "