Skip to content

Commit 1c45548

Browse files
authored
Merge pull request #141 from Horacehxw/dev
feat(explore-idea): add explore-idea command + gen-idea directions.json companion (v1.17.0)
2 parents 8986bf3 + 3ffd75e commit 1c45548

54 files changed

Lines changed: 4358 additions & 214 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ This is a Claude Code plugin that provides iterative development with Codex revi
77
- Version number must be in format of `X.Y.Z` where X/Y/Z is numeric number. Version MUST NOT include anything other than `X.Y.Z`. For example, a good version is `9.732.42`; Bad version examples (MUST NOT USE): `3.22.7-alpha` (extra "-alpha" string), `9.77.2 (2026-01-07)` (useless date/timestamp).
88
- The plan template in `commands/gen-plan.md` (Phase 5 Plan Structure section) and `prompt-template/plan/gen-plan-template.md` are intentionally kept in sync. When modifying either file, ensure both are updated to maintain consistency.
99
- Conversely, changes to `prompt-template/plan/gen-plan-template.md` must also be reflected in the Plan Structure section of `commands/gen-plan.md`.
10+
- The directions.json schema v1 is defined in two places that must stay in sync: the jq validation expression in `scripts/validate-directions-json.sh` and the schema documentation in `commands/gen-idea.md` (Step 4.5). When adding, removing, or renaming a field in either place, update the other.
11+
- Worker constraints (hard caps, isolation rules, no-push rule, sentinel format) are documented in four places that must stay in sync: `commands/explore-idea.md` (coordinator phases), `prompt-template/explore/worker-prompt.md` (worker instructions), `scripts/validate-explore-idea-io.sh` (cap enforcement), and `docs/usage.md` (user-facing option docs). Any change to a cap value or constraint must be reflected in all four.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ temp
44
# Local Claude client settings
55
/.claude/settings.json
66
/.claude/scheduled_tasks.lock
7+
/.claude/worktrees/
78

89
# Local Codex CLI marker (empty file occasionally left behind in worktree)
910
/.codex

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,35 @@ Requires [codex CLI](https://github.com/openai/codex) for review. See the full [
4545
```bash
4646
/humanize:gen-idea "add undo/redo to the editor"
4747
```
48-
Output goes to `.humanize/ideas/<slug>-<timestamp>.md` by default. Pass a `.md` path to expand existing rough notes. `--n` controls how many parallel directions explore the idea (default 6).
48+
Output goes to `.humanize/ideas/<slug>-<timestamp>.md` and a companion `directions.json` artifact. Pass a `.md` path to expand existing rough notes. `--n` controls how many parallel directions explore the idea (default 6).
4949

50-
2. **Generate a plan** from your draft:
50+
2. **Explore directions as parallel prototypes** (optional — skip if you want to go straight to planning):
5151
```bash
52-
/humanize:gen-plan --input draft.md --output docs/plan.md
52+
/humanize:explore-idea .humanize/ideas/<slug>-<timestamp>.directions.json
5353
```
54+
Dispatches bounded parallel prototype workers (one per direction), each running in an isolated git worktree. After all workers complete, writes `.humanize/explore/<run-id>/explore-report.md` for audit/ranking details and `.humanize/explore/<run-id>/final-idea.md` as the plan-ready synthesis. Worker worktrees are optional prototype fast paths; the default follow-up is to generate a clean plan from `final-idea.md`.
5455

55-
3. **Refine an annotated plan** before implementation when reviewers add comments (`CMT:` ... `ENDCMT`, `<cmt>` ... `</cmt>`, or `<comment>` ... `</comment>`):
56+
3. **Generate a plan** from your draft or explored final idea:
57+
```bash
58+
/humanize:gen-plan --input .humanize/explore/<run-id>/final-idea.md --output docs/plan.md
59+
```
60+
61+
4. **Refine an annotated plan** before implementation when reviewers add comments (`CMT:` ... `ENDCMT`, `<cmt>` ... `</cmt>`, or `<comment>` ... `</comment>`):
5662
```bash
5763
/humanize:refine-plan --input docs/plan.md
5864
```
5965

60-
4. **Run the loop**:
66+
5. **Run the loop**:
6167
```bash
6268
/humanize:start-rlcr-loop docs/plan.md
6369
```
6470

65-
5. **Consult Gemini** for deep web research (requires Gemini CLI):
71+
6. **Consult Gemini** for deep web research (requires Gemini CLI):
6672
```bash
6773
/humanize:ask-gemini What are the latest best practices for X?
6874
```
6975

70-
6. **Monitor progress (in another terminal, not inside Claude Code)**:
76+
7. **Monitor progress (in another terminal, not inside Claude Code)**:
7177
```bash
7278
source <path/to/humanize>/scripts/humanize.sh # Or just add it into your .bashec or .zshrc
7379
humanize monitor rlcr # RLCR loop

commands/explore-idea.md

Lines changed: 388 additions & 0 deletions
Large diffs are not rendered by default.

commands/gen-idea.md

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ description: "Generate a repo-grounded idea draft via directed-swarm exploration
33
argument-hint: "<idea-text-or-path> [--n <int>] [--output <path>]"
44
allowed-tools:
55
- "Bash(${CLAUDE_PLUGIN_ROOT}/scripts/validate-gen-idea-io.sh:*)"
6+
- "Bash(${CLAUDE_PLUGIN_ROOT}/scripts/validate-directions-json.sh:*)"
7+
- "Bash(rm:*)"
68
- "Read"
79
- "Glob"
810
- "Grep"
@@ -16,7 +18,7 @@ Read and execute below with ultrathink.
1618

1719
## Hard Constraint: Draft-Only Output
1820

19-
This command MUST NOT implement features, modify source code, or create commits while producing the draft. Permitted writes are limited to the single output draft file produced in Phase 4; prerequisite directory creation for the default `.humanize/ideas/` path by the validation script is permitted as part of that write. All exploration subagents run read-only.
21+
This command MUST NOT implement features, modify source code, or create commits while producing the draft. Permitted writes are limited to the output draft file and its companion `directions.json` artifact produced in Phase 4; prerequisite directory creation for the default `.humanize/ideas/` path by the validation script is permitted. `rm` is permitted solely to delete those two just-written files when companion JSON validation fails (no-partial-output cleanup). All exploration subagents run read-only.
2022

2123
This command transforms a loose idea into a repo-grounded draft suitable as input to `/humanize:gen-plan`. It applies directed-diversity exploration: a lead picks N orthogonal directions, N parallel `Explore` subagents develop each, the lead synthesizes a draft with one primary direction plus N-1 alternatives. Each direction carries objective evidence from the repo.
2224

@@ -28,7 +30,7 @@ This command transforms a loose idea into a repo-grounded draft suitable as inpu
2830
2. IO Validation
2931
3. Direction Generation
3032
4. Parallel Exploration
31-
5. Synthesis and Write
33+
5. Synthesis, Write Draft, and Write Companion JSON
3234

3335
---
3436

@@ -51,14 +53,15 @@ Run:
5153
```
5254

5355
Handle exit codes:
54-
- `0`: Parse stdout to extract `INPUT_MODE`, `OUTPUT_FILE`, `SLUG`, `TEMPLATE_FILE`, `N` (each appears on its own `KEY: value` line). When `INPUT_MODE` is `file`, stdout additionally contains an `IDEA_BODY_FILE: <path>` line; extract that too. Continue to Phase 2. (`SLUG` is informational — the script has already incorporated it into `OUTPUT_FILE`, so later phases do not need to use `SLUG` directly.)
56+
- `0`: Parse stdout to extract `INPUT_MODE`, `OUTPUT_FILE`, `DIRECTIONS_JSON_FILE`, `SLUG`, `TEMPLATE_FILE`, `N` (each appears on its own `KEY: value` line). When `INPUT_MODE` is `file`, stdout additionally contains an `IDEA_BODY_FILE: <path>` line; extract that too. Continue to Phase 2. (`SLUG` is informational — the script has already incorporated it into `OUTPUT_FILE`, so later phases do not need to use `SLUG` directly.)
5557
- `1`: Report "Missing or empty idea input" and stop.
5658
- `2`: Report "Input looks like a file path but is missing, not readable, or not `.md`" and stop.
5759
- `3`: Report "Output directory does not exist — please create it or choose a different path" and stop.
5860
- `4`: Report "Output file already exists — choose a different path" and stop.
5961
- `5`: Report "No write permission to output directory" and stop.
60-
- `6`: Report "Invalid arguments" with the stdout usage text and stop.
62+
- `6`: Report "Invalid arguments — output path must have `.md` suffix" with the stdout usage text and stop.
6163
- `7`: Report "Template file missing — plugin configuration error" and stop.
64+
- `8`: Report "Companion directions.json already exists — choose a different output path or remove the existing companion file" and stop.
6265

6366
Before `VALIDATION_SUCCESS`, stdout may contain one or more lines starting with `WARNING:` (for example, `WARNING: short idea (<N> chars); proceeding` when an inline idea is under 10 characters). Surface these warnings to the user in your final report but continue Phase 2 normally. `WARNING:` lines are informational, not errors.
6467

@@ -190,13 +193,73 @@ Produce the finalized draft content in memory by replacing placeholders:
190193

191194
Write the finalized content to `OUTPUT_FILE` using the `Write` tool. Single write; no progressive edits.
192195

193-
### Step 4.5: Report
196+
### Step 4.5: Build and Write Companion JSON
197+
198+
Construct the companion `directions.json` in memory using all surviving direction proposals from Phase 3, then write it to `DIRECTIONS_JSON_FILE` (from Phase 1 stdout).
199+
200+
**JSON structure (schema version 1):**
201+
202+
```json
203+
{
204+
"schema_version": 1,
205+
"title": "<TITLE from Step 4.2>",
206+
"original_idea": "<IDEA_BODY verbatim>",
207+
"synthesis_notes": "<SYNTHESIS_NOTES from Step 4.3>",
208+
"metadata": {
209+
"n_requested": <N>,
210+
"n_returned": <count of surviving directions>,
211+
"timestamp": "<YYYYMMDD-HHmmss>",
212+
"draft_path": "<OUTPUT_FILE>"
213+
},
214+
"directions": [
215+
{
216+
"direction_id": "dir-<NN>-<dir-slug>",
217+
"dir_slug": "<lowercase-alphanumeric-hyphen slug derived from direction name>",
218+
"source_index": <original 0-based index from DIRECTIONS list>,
219+
"display_order": <0 for primary, 1..K for alternatives in sequential order>,
220+
"is_primary": <true for PRIMARY, false otherwise>,
221+
"name": "<direction name>",
222+
"rationale": "<direction rationale from Phase 2>",
223+
"raw_phase3_response": "<exact raw subagent response text for this direction>",
224+
"approach_summary": "<APPROACH_SUMMARY from subagent>",
225+
"objective_evidence": ["<bullet item>", ...],
226+
"known_risks": ["<bullet item>", ...],
227+
"confidence": "<high|medium|low>"
228+
}
229+
]
230+
}
231+
```
232+
233+
**Field derivation rules:**
234+
- `direction_id`: `"dir-" + zero-padded source_index (2 digits) + "-" + dir_slug`. Example: `"dir-00-command-history"`.
235+
- `dir_slug`: Derived from direction name — lowercase, replace non-alphanumeric with hyphens, collapse consecutive hyphens, strip leading/trailing hyphens. Must match `^[a-z0-9-]+$`.
236+
- `dir_slug` collision handling: if two direction names slugify to the same value, append `-2`, `-3`, etc. by original `source_index` order until every `dir_slug` is unique.
237+
- `source_index`: The 0-based index of this direction in the original `DIRECTIONS` list from Phase 2 (before any degradation drops).
238+
- `display_order`: 0 for the primary direction, 1 through K for alternatives in their sequential order.
239+
- `is_primary`: `true` for exactly one direction (PRIMARY), `false` for all others.
240+
- `objective_evidence`: Each bullet item from the subagent's `OBJECTIVE_EVIDENCE` field as a string array element.
241+
- `known_risks`: Each bullet item from the subagent's `KNOWN_RISKS` field as a string array element.
242+
- `metadata.n_returned` must equal `directions.length`.
243+
244+
After writing `DIRECTIONS_JSON_FILE`, validate it:
245+
```bash
246+
"${CLAUDE_PLUGIN_ROOT}/scripts/validate-directions-json.sh" "$DIRECTIONS_JSON_FILE"
247+
```
248+
249+
If validation fails, delete both `OUTPUT_FILE` and `DIRECTIONS_JSON_FILE` and stop with error: `companion JSON validation failed — this is a bug in the command; please report it`.
250+
251+
### Step 4.6: Report
194252

195253
Report to the user:
196-
- Path written (`OUTPUT_FILE`).
254+
- Draft path written: `OUTPUT_FILE`
255+
- Companion JSON path written: `DIRECTIONS_JSON_FILE`
197256
- Primary direction name.
198257
- Requested `N` and the actual direction count (note if reduced due to degradation).
199-
- Next-step hint: `To turn this draft into a plan, run: /humanize:gen-plan --input <OUTPUT_FILE> --output <plan-path>`.
258+
- Next-step hints:
259+
```
260+
To explore directions as parallel prototypes, run: /humanize:explore-idea <DIRECTIONS_JSON_FILE>
261+
To turn this draft into a plan, run: /humanize:gen-plan --input <OUTPUT_FILE> --output <plan-path>
262+
```
200263

201264
---
202265

@@ -206,4 +269,5 @@ Report to the user:
206269
- Phase 2 degradation follows the retry-once + ≥2 minimum rule stated above.
207270
- Phase 3 degradation follows the drop-and-continue + ≥2 minimum rule stated above.
208271
- Never fabricate repo references or prior art. The `exploratory, no concrete precedent` sentinel from subagents is preserved verbatim in the draft.
209-
- If any phase stops with an error, do not write a partial `OUTPUT_FILE`.
272+
- If any phase stops with an error, do not write a partial `OUTPUT_FILE` or `DIRECTIONS_JSON_FILE`.
273+
- If companion JSON validation fails after writing both files, delete both files and stop.

commands/start-rlcr-loop.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: "Start iterative loop with Codex review"
3-
argument-hint: "[path/to/plan.md | --plan-file path/to/plan.md] [--max N] [--codex-model MODEL:EFFORT] [--codex-timeout SECONDS] [--track-plan-file] [--push-every-round] [--base-branch BRANCH] [--full-review-round N] [--skip-impl] [--claude-answer-codex] [--agent-teams] [--yolo] [--skip-quiz] [--privacy]"
3+
argument-hint: "[path/to/plan.md | --plan-file path/to/plan.md] [--max N] [--codex-model MODEL:EFFORT] [--codex-timeout SECONDS] [--track-plan-file] [--push-every-round] [--base-branch BRANCH] [--full-review-round N] [--skip-impl] [--claude-answer-codex] [--agent-teams] [--yolo] [--skip-quiz] [--privacy] [--no-privacy]"
44
allowed-tools:
55
- "Bash(${CLAUDE_PLUGIN_ROOT}/scripts/setup-rlcr-loop.sh:*)"
66
- "Read"

docs/install-for-kimi.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ cp -r skills/humanize-gen-plan ~/.config/agents/skills/
5353
cp -r skills/humanize-refine-plan ~/.config/agents/skills/
5454
cp -r skills/humanize-rlcr ~/.config/agents/skills/
5555

56+
# Kimi does not use Codex native Stop hooks, so install the gate-based
57+
# RLCR entrypoint used by scripts/install-skill.sh --target kimi.
58+
cp skills/humanize-rlcr/SKILL-kimi.md ~/.config/agents/skills/humanize-rlcr/SKILL.md
59+
5660
# Copy runtime dependencies used by the skills
5761
# (must match install-skill.sh's install_runtime_bundle)
5862
cp -r scripts ~/.config/agents/skills/humanize/

docs/usage.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ The quiz is advisory, not a gate. You always have the option to proceed. But tha
5959

6060
| Command | Purpose |
6161
|---------|---------|
62+
| `/gen-idea <idea-or-path>` | Generate a repo-grounded idea draft with N parallel directions |
63+
| `/explore-idea <draft-or-directions.json>` | Launch bounded parallel prototype workers and synthesize a two-tier report |
6264
| `/start-rlcr-loop <plan.md>` | Start iterative development with Codex review |
6365
| `/cancel-rlcr-loop` | Cancel active loop |
6466
| `/gen-plan --input <draft.md> --output <plan.md>` | Generate structured plan from draft |
@@ -67,6 +69,52 @@ The quiz is advisory, not a gate. You always have the option to proceed. But tha
6769

6870
## Command Reference
6971

72+
### gen-idea
73+
74+
```
75+
/humanize:gen-idea <idea-text-or-path> [--n <int>] [--output <path>]
76+
```
77+
78+
Generates a repo-grounded idea draft using directed-diversity exploration. A lead agent picks N orthogonal directions, N parallel Explore subagents develop each direction with objective evidence from the repo, and the lead synthesizes a draft with one primary direction plus N-1 alternatives.
79+
80+
**Outputs:**
81+
- Draft file: `.humanize/ideas/<slug>-<timestamp>.md` (or `--output` path)
82+
- Companion JSON: `<draft-path-without-.md>.directions.json` — lossless record of all direction proposals, used as input to `explore-idea`
83+
84+
**Options:**
85+
- `--n <int>` — number of parallel directions (default: 6)
86+
- `--output <path>` — custom output path for the draft (must have `.md` suffix)
87+
88+
### explore-idea
89+
90+
```
91+
/humanize:explore-idea <draft.md | draft.directions.json> [--directions ids] [--concurrency N] [--max-worker-iterations N] [--worker-timeout-min N] [--codex-timeout-min N]
92+
```
93+
94+
Launches bounded parallel prototype workers — one per selected direction — each running in an isolated git worktree. After all workers complete, synthesizes an explore report plus a plan-ready final idea:
95+
- **Tier 1**: Best product direction (ranked by user value, evidence, strategic fit)
96+
- **Tier 2**: Most implementation-ready prototype (ranked by outcome: task status, Codex verdict, tests, commits)
97+
98+
**Options:**
99+
- `--directions <ids>` — comma-separated `direction_id` or `source_index` values to run (default: first 6 by display order)
100+
- `--concurrency <N>` — parallel worker count (default: 6, max: 10)
101+
- `--max-worker-iterations <N>` — per-worker iteration cap (default: 2, max: 3)
102+
- `--worker-timeout-min <N>` — worker timeout in minutes (default: 60, max: 60)
103+
- `--codex-timeout-min <N>` — Codex call timeout in minutes (default: 20, max: 20)
104+
105+
**Run artifacts** stored in `.humanize/explore/<RUN_ID>/`:
106+
- `manifest.json` — coordinator state and per-worker metadata
107+
- `dispatch-prompts/` — exact prompts sent to each worker
108+
- `worker-results.jsonl` — machine-readable result rows
109+
- `explore-report.md` — audit report with two-tier rankings, adoption paths, and cleanup guidance
110+
- `final-idea.md` — plan-ready synthesis artifact for `/humanize:gen-plan`
111+
112+
Default follow-up:
113+
```bash
114+
/humanize:gen-plan --input .humanize/explore/<run-id>/final-idea.md --output docs/plan.md
115+
/humanize:start-rlcr-loop docs/plan.md
116+
```
117+
70118
### start-rlcr-loop
71119

72120
```

hooks/lib/loop-bg-tasks.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ handle_bg_task_short_circuit() {
355355
local guard_state_file guard_stored_sid
356356
guard_state_file=$(resolve_active_state_file "$loop_dir")
357357
if [[ -n "$guard_state_file" ]]; then
358-
guard_stored_sid=$(sed -n '/^---$/,/^---$/{ /^'"${FIELD_SESSION_ID}"':/{ s/^'"${FIELD_SESSION_ID}"': *//; p; } }' "$guard_state_file" 2>/dev/null | tr -d ' ')
358+
guard_stored_sid=$(awk -v key="${FIELD_SESSION_ID}" 'BEGIN{f=0} /^---$/{f++; next} f==1 && $0 ~ "^"key":"{sub("^"key":[[:space:]]*",""); print; exit}' "$guard_state_file" 2>/dev/null | tr -d ' ') || true
359359
if [[ -n "$guard_stored_sid" ]] \
360360
&& [[ -n "$hook_session_id" ]] \
361361
&& [[ "$guard_stored_sid" != "$hook_session_id" ]]; then

hooks/lib/loop-common.sh

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ find_active_loop() {
379379
fi
380380

381381
local stored_session_id
382-
stored_session_id=$(sed -n '/^---$/,/^---$/{ /^'"${FIELD_SESSION_ID}"':/{ s/'"${FIELD_SESSION_ID}"': *//; p; } }' "$any_state" 2>/dev/null | tr -d ' ')
382+
stored_session_id=$(awk -v key="${FIELD_SESSION_ID}" 'BEGIN{f=0} /^---$/{f++; next} f==1 && $0 ~ "^"key":"{sub("^"key":[[:space:]]*",""); print; exit}' "$any_state" 2>/dev/null | tr -d ' ')
383383

384384
# Empty stored session_id matches any session (backward compat).
385385
if [[ -z "$stored_session_id" ]] || [[ "$stored_session_id" == "$filter_session_id" ]]; then
@@ -809,8 +809,8 @@ extract_round_number() {
809809
local filename_lower
810810
filename_lower=$(to_lower "$filename")
811811

812-
# Use sed for portable regex extraction (works in both bash and zsh)
813-
echo "$filename_lower" | sed -n 's/.*round-\([0-9][0-9]*\)-\(summary\|prompt\|todos\|contract\)\.md$/\1/p'
812+
# Use ERE (-E) so | alternation works on both GNU and BSD sed (macOS)
813+
echo "$filename_lower" | sed -En 's/.*round-([0-9]+)-(summary|prompt|todos|contract)\.md$/\1/p'
814814
}
815815

816816
# Check if a file is in the allowlist for the active loop
@@ -820,6 +820,11 @@ is_allowlisted_file() {
820820
local file_path="$1"
821821
local active_loop_dir="$2"
822822

823+
# Canonicalize both paths to resolve symlinks (e.g. /var -> /private/var on macOS).
824+
local canonical_file canonical_loop
825+
canonical_file=$(canonicalize_path "$file_path" 2>/dev/null || echo "$file_path")
826+
canonical_loop=$(canonicalize_path "$active_loop_dir" 2>/dev/null || echo "$active_loop_dir")
827+
823828
local allowlist=(
824829
"round-1-todos.md"
825830
"round-2-todos.md"
@@ -828,7 +833,7 @@ is_allowlisted_file() {
828833
)
829834

830835
for allowed in "${allowlist[@]}"; do
831-
if [[ "$file_path" == "$active_loop_dir/$allowed" ]]; then
836+
if [[ "$canonical_file" == "$canonical_loop/$allowed" ]]; then
832837
return 0
833838
fi
834839
done
@@ -1522,7 +1527,7 @@ Use Write or Edit on: {{CORRECT_PATH}}
15221527
15231528
Rules:
15241529
- Keep the **IMMUTABLE SECTION** unchanged
1525-
- Do not modify `goal-tracker.md` via Bash
1530+
- Do not modify goal-tracker.md via Bash
15261531
- Do not write to an old loop session's tracker"
15271532

15281533
load_and_render_safe "$TEMPLATE_DIR" "block/goal-tracker-modification.md" "$fallback" \

0 commit comments

Comments
 (0)