Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/install-for-codex.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Or use the unified installer directly:
```

This will:
- Sync `humanize`, `humanize-gen-plan`, `humanize-refine-plan`, and `humanize-rlcr` into `${CODEX_HOME:-~/.codex}/skills`
- Sync `humanize`, `humanize-gen-idea`, `humanize-gen-plan`, `humanize-refine-plan`, and `humanize-rlcr` into `${CODEX_HOME:-~/.codex}/skills`
- Copy runtime dependencies into `${CODEX_HOME:-~/.codex}/skills/humanize`
- Install/update native Humanize Stop hooks in `${CODEX_HOME:-~/.codex}/hooks.json`
- Enable the experimental `codex_hooks` feature in `${CODEX_HOME:-~/.codex}/config.toml` when `codex` is available
Expand All @@ -41,6 +41,7 @@ ls -la "${CODEX_HOME:-$HOME/.codex}/skills"

Expected directories:
- `humanize`
- `humanize-gen-idea`
- `humanize-gen-plan`
- `humanize-refine-plan`
- `humanize-rlcr`
Expand All @@ -55,6 +56,7 @@ Runtime dependencies in `humanize/`:

Installed files/directories:
- `${CODEX_HOME:-~/.codex}/skills/humanize/SKILL.md`
- `${CODEX_HOME:-~/.codex}/skills/humanize-gen-idea/SKILL.md`
- `${CODEX_HOME:-~/.codex}/skills/humanize-gen-plan/SKILL.md`
- `${CODEX_HOME:-~/.codex}/skills/humanize-refine-plan/SKILL.md`
- `${CODEX_HOME:-~/.codex}/skills/humanize-rlcr/SKILL.md`
Expand Down
59 changes: 52 additions & 7 deletions scripts/install-skill.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Install/upgrade Humanize skills for Kimi and/or Codex.
#
# What this does:
# 1) Sync skills/{humanize,humanize-gen-plan,humanize-rlcr} to target skills dir(s)
# 1) Sync target skills to target skills dir(s)
# 2) Copy runtime dependencies into <skills-dir>/humanize/{scripts,hooks,prompt-template}
# 3) Hydrate SKILL.md command paths with concrete runtime root paths
#
Expand Down Expand Up @@ -43,6 +43,10 @@ SKILL_NAMES=(
"humanize-rlcr"
)

CODEX_ONLY_SKILL_NAMES=(
"humanize-gen-idea"
)

usage() {
cat <<'EOF'
Install Humanize skills for Kimi and/or Codex.
Expand All @@ -63,6 +67,10 @@ Options:
EOF
}

target_includes_codex() {
[[ "$TARGET" == "codex" || "$TARGET" == "both" ]]
}

log() {
printf '[install-skills] %s\n' "$*"
}
Expand All @@ -82,7 +90,13 @@ validate_repo() {
[[ -d "$RUNTIME_SOURCE_ROOT/templates" ]] || die "templates directory not found under runtime source root: $RUNTIME_SOURCE_ROOT"
[[ -d "$RUNTIME_SOURCE_ROOT/config" ]] || die "config directory not found under runtime source root: $RUNTIME_SOURCE_ROOT"
[[ -d "$RUNTIME_SOURCE_ROOT/agents" ]] || die "agents directory not found under runtime source root: $RUNTIME_SOURCE_ROOT"
for skill in "${SKILL_NAMES[@]}"; do
local required_skills=("${SKILL_NAMES[@]}")
if target_includes_codex; then
required_skills+=("${CODEX_ONLY_SKILL_NAMES[@]}")
fi

local skill
for skill in "${required_skills[@]}"; do
[[ -f "$SKILLS_SOURCE_ROOT/$skill/SKILL.md" ]] || die "missing $SKILLS_SOURCE_ROOT/$skill/SKILL.md"
done
}
Expand All @@ -105,9 +119,24 @@ resolve_source_layout() {
# <skills-dir>/humanize/scripts/install-skill.sh
# <skills-dir>/humanize-gen-plan/SKILL.md
# <skills-dir>/humanize-rlcr/SKILL.md
# <skills-dir>/humanize-gen-idea/SKILL.md (Codex target only)
if [[ -d "$runtime_root/scripts" ]] && [[ -d "$runtime_root/hooks" ]] && [[ -d "$runtime_root/prompt-template" ]]; then
skills_root="$(cd "$runtime_root/.." && pwd)"
if [[ -f "$skills_root/humanize/SKILL.md" ]] && [[ -f "$skills_root/humanize-gen-plan/SKILL.md" ]] && [[ -f "$skills_root/humanize-refine-plan/SKILL.md" ]] && [[ -f "$skills_root/humanize-rlcr/SKILL.md" ]]; then
local required_skills=("${SKILL_NAMES[@]}")
if target_includes_codex; then
required_skills+=("${CODEX_ONLY_SKILL_NAMES[@]}")
fi

local layout_ok="true"
local skill
for skill in "${required_skills[@]}"; do
if [[ ! -f "$skills_root/$skill/SKILL.md" ]]; then
layout_ok="false"
break
fi
done

if [[ "$layout_ok" == "true" ]]; then
SKILLS_SOURCE_ROOT="$skills_root"
RUNTIME_SOURCE_ROOT="$runtime_root"
return 0
Expand Down Expand Up @@ -166,12 +195,18 @@ install_runtime_bundle() {

hydrate_skill_runtime_root() {
local target_dir="$1"
shift || true
local selected_skills=("$@")
local runtime_root="$target_dir/humanize"
local skill
local skill_file
local tmp

for skill in "${SKILL_NAMES[@]}"; do
if [[ ${#selected_skills[@]} -eq 0 ]]; then
selected_skills=("${SKILL_NAMES[@]}")
fi

for skill in "${selected_skills[@]}"; do
skill_file="$target_dir/$skill/SKILL.md"
[[ -f "$skill_file" ]] || continue

Expand All @@ -193,11 +228,17 @@ hydrate_skill_runtime_root() {

strip_claude_specific_frontmatter() {
local target_dir="$1"
shift || true
local selected_skills=("$@")
local skill
local skill_file
local tmp

for skill in "${SKILL_NAMES[@]}"; do
if [[ ${#selected_skills[@]} -eq 0 ]]; then
selected_skills=("${SKILL_NAMES[@]}")
fi

for skill in "${selected_skills[@]}"; do
skill_file="$target_dir/$skill/SKILL.md"
[[ -f "$skill_file" ]] || continue

Expand Down Expand Up @@ -234,6 +275,10 @@ sync_target() {
local target_dir="$2"
local selected_skills=("${SKILL_NAMES[@]}")

if [[ "$label" == "codex" ]]; then
selected_skills+=("${CODEX_ONLY_SKILL_NAMES[@]}")
fi

log "target: $label"
log "skills dir: $target_dir"

Expand All @@ -246,8 +291,8 @@ sync_target() {
sync_one_skill "$skill" "$target_dir"
done
install_runtime_bundle "$target_dir"
hydrate_skill_runtime_root "$target_dir"
strip_claude_specific_frontmatter "$target_dir"
hydrate_skill_runtime_root "$target_dir" "${selected_skills[@]}"
strip_claude_specific_frontmatter "$target_dir" "${selected_skills[@]}"
}

install_codex_native_hooks() {
Expand Down
149 changes: 149 additions & 0 deletions skills/humanize-gen-idea/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
name: humanize-gen-idea
description: Generate a repo-grounded idea draft from loose input using directed exploration.
type: flow
user-invocable: false
disable-model-invocation: true
---

# Humanize Generate Idea

Transforms loose idea text, or a `.md` file containing an idea, into a repo-grounded draft suitable for `humanize-gen-plan`.

The installer hydrates this skill with an absolute runtime root path:

```bash
{{HUMANIZE_RUNTIME_ROOT}}
```

## Hard Constraint

This flow must only produce an idea draft. Do not implement features, modify source code, create commits, or write any file other than the final draft output selected by the validator.

## Input Requirements

Required:
- One positional idea input: inline text or path to a `.md` file

Optional:
- `--n <int>` - number of directions to explore; default is 6
- `--output <path>` - output draft path; default is resolved by the validator under `.humanize/ideas/`

## Required Sequence

### 1. Parse Arguments Safely

Extract `$ARGUMENTS` into:
- `IDEA_INPUT`
- optional `N`
- optional `OUTPUT_FILE`

Do not pass free-form idea text to the shell unquoted. Inline idea text may contain spaces or shell metacharacters and must be passed as one shell argument.

### 2. Validate IO

Run the validator from the installed runtime root:

```bash
"{{HUMANIZE_RUNTIME_ROOT}}/scripts/validate-gen-idea-io.sh" [--n N] [--output OUTPUT_FILE] "IDEA_INPUT"
```

Handle exit codes:

| Exit Code | Meaning |
|-----------|---------|
| 0 | Success; parse validator stdout and continue |
| 1 | Missing or empty idea input |
| 2 | Input looks like a file path but is missing, unreadable, or not `.md` |
| 3 | Output directory does not exist |
| 4 | Output file already exists |
| 5 | No write permission to output directory |
| 6 | Invalid arguments |
| 7 | Template file missing |

On success, parse these stdout fields:
- `INPUT_MODE`
- `OUTPUT_FILE`
- `SLUG`
- `TEMPLATE_FILE`
- `N`
- `IDEA_BODY_FILE` when `INPUT_MODE` is `file`

For inline input, extract `IDEA_BODY` from the validator's sentinel block between `=== IDEA_BODY_BEGIN ===` and `=== IDEA_BODY_END ===`. For file input, read `IDEA_BODY_FILE`. Preserve the idea body byte-identically for the final draft.

### 3. Generate Orthogonal Directions

Read repository context before proposing directions:
- `README.md`
- `CLAUDE.md`, if present
- `.claude/CLAUDE.md`, if present
- one-level top-level directory listing

Generate exactly `N` direction entries. Each entry must have:
- `name`: 2-5 words
- `rationale`: one sentence explaining why this angle is distinct

Directions must be genuinely orthogonal. If two are near-duplicates, replace one. If the first pass yields fewer than `N` directions, regenerate once. If the second pass still yields fewer than `N` but at least 2, proceed with the reduced count and report a warning. If fewer than 2 directions remain, stop with `direction generation degraded; retry.`

### 4. Explore Each Direction

For each direction, gather objective evidence from the repository. Prefer child-agent or parallel exploration only when available and permitted by the current runtime policy; otherwise perform the explorations sequentially in the current session.

Every exploration must be read-only and must return these fields:

```text
APPROACH_SUMMARY:
OBJECTIVE_EVIDENCE:
KNOWN_RISKS:
CONFIDENCE:
```

Rules for exploration:
- `OBJECTIVE_EVIDENCE` must cite concrete repository paths, prior art, or measurable considerations.
- If no concrete evidence exists, use the literal sentinel `exploratory, no concrete precedent` once.
- Do not fabricate repository references.
- `CONFIDENCE` must be one of `high`, `medium`, or `low`.
- Drop any exploration result missing one of the required fields.
- If fewer than 2 proposals survive, stop with `exploration phase degraded; retry.`

### 5. Synthesize The Draft

Choose the primary proposal using this priority:
1. Evidence density
2. Fit with existing repository patterns
3. Smaller implementation surface for otherwise comparable proposals
4. Higher declared confidence

Generate a 4-10 word Title Case title that captures the primary direction.

Read `TEMPLATE_FILE` and replace:
- `<TITLE>`
- `<ORIGINAL_IDEA>`
- `<PRIMARY_NAME>`
- `<PRIMARY_RATIONALE>`
- `<PRIMARY_APPROACH_SUMMARY>`
- `<PRIMARY_OBJECTIVE_EVIDENCE>`
- `<PRIMARY_KNOWN_RISKS>`
- `<ALTERNATIVES>`
- `<SYNTHESIS_NOTES>`

Alternative sections must use this format:

```markdown
### Alt-<i>: <name>
- Gist: <one-paragraph summary derived from APPROACH_SUMMARY>
- Objective Evidence:
- <bullet from OBJECTIVE_EVIDENCE>
- Why not primary: <one sentence stating the tradeoff vs PRIMARY>
```

### 6. Write And Report

Write the finalized draft to `OUTPUT_FILE` in one operation. Do not write partial output if any prior phase failed.

Report:
- Path written
- Primary direction name
- Requested `N` and actual direction count
- Any warnings
- Next step: run `humanize-gen-plan` with the draft as `--input`
17 changes: 16 additions & 1 deletion tests/test-codex-hook-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ else
fail "Codex install keeps humanize-rlcr entrypoint skill" "skills/humanize-rlcr/SKILL.md exists" "missing"
fi

if [[ -f "$CODEX_HOME_DIR/skills/humanize-gen-idea/SKILL.md" ]]; then
pass "Codex install includes humanize-gen-idea entrypoint skill"
else
fail "Codex install includes humanize-gen-idea entrypoint skill" "skills/humanize-gen-idea/SKILL.md exists" "missing"
fi

if grep -qF "$CODEX_HOME_DIR/skills/humanize/scripts/validate-gen-idea-io.sh" "$CODEX_HOME_DIR/skills/humanize-gen-idea/SKILL.md"; then
pass "Codex install hydrates humanize-gen-idea runtime paths"
else
fail "Codex install hydrates humanize-gen-idea runtime paths" \
"$CODEX_HOME_DIR/skills/humanize/scripts/validate-gen-idea-io.sh" \
"$(sed -n '1,80p' "$CODEX_HOME_DIR/skills/humanize-gen-idea/SKILL.md" 2>/dev/null || echo missing)"
fi

if [[ -f "$HOOKS_FILE" ]]; then
pass "Codex install writes hooks.json"
else
Expand Down Expand Up @@ -253,6 +267,7 @@ PATH="$FAKE_BIN:$PATH" TEST_CODEX_FEATURE_LOG="$FEATURE_LOG" XDG_CONFIG_HOME="$X
--target codex \
--codex-config-dir "$CODEX_HOME_DIR" \
--codex-skills-dir "$CODEX_HOME_DIR/skills" \
--command-bin-dir "$COMMAND_BIN_DIR" \
> "$TEST_DIR/install-2.log" 2>&1

PY_OUTPUT_2="$(
Expand Down Expand Up @@ -308,7 +323,7 @@ EOF
chmod +x "$UNSUPPORTED_BIN/codex"

set +e
PATH="$UNSUPPORTED_BIN:$PATH" \
PATH="$UNSUPPORTED_BIN:$PATH" XDG_CONFIG_HOME="$XDG_CONFIG_HOME_DIR" \
"$INSTALL_SCRIPT" \
--target codex \
--codex-config-dir "$UNSUPPORTED_HOME" \
Expand Down
Loading