Skip to content
Merged
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: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
"name": "goax",
"description": "AI 에이전트 결과 일관성을 환경으로 통제하는 4계층 하네스 (Triage·Constitution·Module·Spec/ADR) + Spirit·Mistake Loop. bash+markdown only, 자연어로 도입. Claude Code·OpenCode 지원.",
"version": "0.7.7",
"version": "0.7.8",
"author": {
"name": "bluecheat",
"email": "itsinil@gmail.com"
Expand All @@ -30,5 +30,5 @@
]
}
],
"version": "0.7.7"
"version": "0.7.8"
}
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "goax",
"version": "0.7.7",
"version": "0.7.8",
"description": "AX 4-Layer harness — Triage / Constitution / Module / Spec·ADR + Spirit·Mistake Loop. Bash + Markdown only, with Claude-driven onboarding. Multi-CLI: Claude Code (native) + OpenCode (Hybrid compat via AGENTS.md SSOT + opencode.json).",
"author": {
"name": "bluecheat",
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ There is no `npm`/`make`/`gradle`. Anything more complex is invoked through Clau
## Repository layout (what each top-level dir does)

- `.claude-plugin/{plugin.json,marketplace.json}` — Claude Code plugin manifest. Both files plus `VERSION` must hold the **same version string** (smoke test fails otherwise).
- `skills/<name>/SKILL.md` — 15 skills (`up`, `onboarding`, `zero`, `doctor`, `spec`, `spec-{tasks,implement,validate}`, `lane`, `audit`, `mistake`, `hud`, `triage`, `adr`, `vendor`). Each starts with frontmatter `name:` + `description:` where description is the trigger-keyword bag. Note: `install` was renamed to `up` (0.1.18), `spec-plan` was retired (0.1.16), `mistake` was added as the capture-only counterpart to `audit`. **`zero` and `lane` were added in 0.5.0** (`lane` was born as `parallel` and renamed in 0.5.1 — the unit of the skill is the lane, and the agents `lane-*` and scripts `lanes-*` already carried that name) — `zero` is the 0→1 entry point (`up` §6 hands greenfield to it; `onboarding` stays brownfield-only), and `lane` sits between `spec-tasks` and `spec-implement` to decide whether the work can be split at all. **`rules` and `spirit` were retired in 0.5.3**: both were prose telling the model to grep; they became `rules-index.sh` and `spirit-lint.sh`, and `doctor` owns their triggers ("rules 보여줘", "spirit 점검"). Big skills keep `SKILL.md` under 500 lines and push box mockups / incident write-ups / mode-specific loops into `<skill>/references/*.md` (`onboarding`, `lane`, `spec-implement`, `triage`, `zero` do this) — `tests/smoke.sh` enforces the line cap, the 1,536-char description cap, and that every referenced `references/<x>.md` exists.
- `skills/<name>/SKILL.md` — 16 skills (`up`, `onboarding`, `zero`, `doctor`, `spec`, `spec-{tasks,implement,validate}`, `lane`, `screen`, `audit`, `mistake`, `hud`, `triage`, `adr`, `vendor`). Each starts with frontmatter `name:` + `description:` where description is the trigger-keyword bag. Note: `install` was renamed to `up` (0.1.18), `spec-plan` was retired (0.1.16), `mistake` was added as the capture-only counterpart to `audit`. **`zero` and `lane` were added in 0.5.0** (`lane` was born as `parallel` and renamed in 0.5.1 — the unit of the skill is the lane, and the agents `lane-*` and scripts `lanes-*` already carried that name) — `zero` is the 0→1 entry point (`up` §6 hands greenfield to it; `onboarding` stays brownfield-only), and `lane` sits between `spec-tasks` and `spec-implement` to decide whether the work can be split at all. **`rules` and `spirit` were retired in 0.5.3**: both were prose telling the model to grep; they became `rules-index.sh` and `spirit-lint.sh`, and `doctor` owns their triggers ("rules 보여줘", "spirit 점검"). Big skills keep `SKILL.md` under 500 lines and push box mockups / incident write-ups / mode-specific loops into `<skill>/references/*.md` (`onboarding`, `lane`, `spec-implement`, `triage`, `zero` do this) — `tests/smoke.sh` enforces the line cap, the 1,536-char description cap, and that every referenced `references/<x>.md` exists.
- `commands/goax.md` — single slash-command index that delegates to skills (other thin per-skill wrappers were retired).
- `agents/{architect,evaluator,lane-scout,lane-worker}.md` — sub-agents invoked by skills. `evaluator` is the Generator/Evaluator separation: `spec-implement` §8 spawns it in a fresh context and it writes `<spec>/review.md` whose first line is `verdict: 진행|보강 필요|재논의 필요`; `tasks-gate.sh` G6 reads that line. `lane-scout`/`lane-worker` are the read-only investigation lane and the file-ownership execution lane that `spec-implement` runs in lane mode.
- `agents/{architect,evaluator,lane-scout,lane-worker,screen-designer}.md` — sub-agents invoked by skills. `screen-designer` is the screen executor: the `screen` skill does intake (`design-caps.sh`), mode and spec-first tables, then spawns it in a fresh context to build → render → measure (`screen-measure.sh`) → fix (≤3) and write a report whose first line is `verdict: 통과|보강 필요|실측 아님`. The pair is **self-contained** — all design knowledge lives in `skills/screen/references/`; MCPs, browsers and simulators are optional accelerators, never requirements. `evaluator` is the Generator/Evaluator separation: `spec-implement` §8 spawns it in a fresh context and it writes `<spec>/review.md` whose first line is `verdict: 진행|보강 필요|재논의 필요`; `tasks-gate.sh` G6 reads that line. `lane-scout`/`lane-worker` are the read-only investigation lane and the file-ownership execution lane that `spec-implement` runs in lane mode.
- `scripts/provision.sh` — the installer. `up` calls it with `--json`; it reads MANIFEST and copies `templates/default/` into the user project. Lives at the plugin root (not `templates/default/.ax/scripts/`) because it *creates* `.ax/` — it cannot live inside what it installs. Root `install.sh` is an unrelated legacy stub that only prints install instructions.
- `templates/default/` — **everything that gets copied into a user project** when the `up` skill runs.
- `templates/default/MANIFEST` — installer SSOT. `up` reads this line-by-line; lines ending in `/` are recursive directory copies, `src -> dst` lines do rename copies. **When you add anything under `templates/default/`, update MANIFEST or the installer will not copy it.** Conditional copies (CLAUDE.md, settings.json, config.yml, mistakes/README.md, .gitignore) are intentionally outside MANIFEST and live in `skills/up/SKILL.md` §5–§6.
- `templates/default/.ax/scripts/bash/` — deterministic shell tooling (42 scripts). All follow the standard in `templates/default/.ax/scripts/bash/README.md`: `set -euo pipefail`, `--json --dry-run --help` options, `[goax]` stderr prefix, exit codes `0` ok / `1` error / `2` skipped. Their `--json` shape is `{status, result, next_step, warnings, errors}`. SKILL.md files invoke these and parse the JSON; they do not reimplement the logic inline.
- `templates/default/.ax/scripts/bash/` — deterministic shell tooling (45 scripts). All follow the standard in `templates/default/.ax/scripts/bash/README.md`: `set -euo pipefail`, `--json --dry-run --help` options, `[goax]` stderr prefix, exit codes `0` ok / `1` error / `2` skipped. Their `--json` shape is `{status, result, next_step, warnings, errors}`. SKILL.md files invoke these and parse the JSON; they do not reimplement the logic inline.
- `templates/default/.ax/hooks/{session-start,pre-compact,user-prompt,pre-bash,pre-edit,post-edit,pre-commit,subagent-start,stop}/*.sh` — sensors. The companion `.claude/settings.json.template` registers them; `doctor` cross-checks installed hooks against this template (it is the SSOT for which hooks *and which event keys* should be registered). `subagent-start/harness-pointer.sh` hands Constitution/Spirit/active-spec/handoff **pointer** to every non-goax subagent (the harness used to stop at the main session); `stop/spec-gate.sh` blocks the end of a turn once when an `implementing`/`review` spec fails `tasks-gate.sh`, unless `current-task.json.handoff.now` records it within 24h (`now_at`) (bounded by `stop_hook_active` and an 8-per-session counter). The two pre-edit injection hooks dedupe per session via `goax_inject_fresh` (`.ax/.session/<sid>/`, 4h TTL) — measured 1,200 repeat injections / 529KB in one real session before this. Four hooks are **fact-forcing gates** that block even in `warning` mode because passing is cheap: `pre-edit/rule-read-gate.sh` denies an edit until every path-matched spirit/module rule file has been Read this session (Read marker, not the model's word; `@`-imported rules are exempt), `pre-bash/destructive-facts.sh` denies an in-project destructive command once and passes the identical retry after the model lists targets/rollback/user instruction, `pre-bash/block-hook-bypass.sh` denies `--no-verify`/`core.hooksPath`/`HUSKY=0`, and `pre-edit/quality-config-gate.sh` denies the first edit per session of an *existing* lint/format/type-check/coverage/git-hook config (cross-ecosystem default file names plus `sensors.quality_configs` — files that mix other settings, like `package.json`/`pyproject.toml`, are deliberately not defaults) until the model writes loosen-or-tighten and the user's instruction. Shell commands are judged by `goax_shell_scan` (shlex tokens; heredoc bodies, here-strings and word-initial `#` comments handled like the shell — shlex's own `commenters` is off because it swallowed the rest of a joined multi-line command) — never by a one-line regex, which reads `-m "fix -n"` as a flag. Python availability is `goax_py_ok` (actually imports; `command -v python3` passes for a broken macOS xcrun shim) and a failed scan returns 3 so the hook degrades to a coarse check instead of passing. Regenerable directories are a cross-ecosystem default plus the project's `sensors.regenerable_paths` — do not grow the built-in list per stack. Every registered hook goes through `goax_hook_enabled <id> <minimal|standard>` (`sensors.disabled_hooks`, `sensors.hook_profile`, `GOAX_DISABLED_HOOKS`); `smoke §53` fails a hook that doesn't, and block-destructive's CATASTROPHIC tier must stay above that switch. `session-start/session-brief.sh` only relays `session-brief.sh --json` (handoff · version lag · overdue audit · same-category mistake recurrence); `pre-compact/snapshot.sh` writes `session-brief.sh --snapshot` facts (branch/HEAD, uncommitted files, active spec's tasks progress) to `.ax/.session/<sid>/precompact.txt` and the `source=compact` SessionStart prepends them once. `post-edit/lint-changed.sh` runs only `commands.lint_file` (`"<glob> => <cmd with {file}>"`, first match) and hands failures to the model as `additionalContext` — it never guesses a linter from the extension; `detect-stack.sh` proposes values from what the project declares (package.json scripts, Makefile/justfile/Taskfile targets, wrappers, manifests) and `config-set.sh` writes them under the `config.yml` lock. In a monorepo the session usually opens at the repo root while `.ax/` lives in `projects/<app>/`, so hooks registered only in the project's settings never fire; `ade-settings.sh --apply` generates the root `.claude/settings.json` entries from the template as `env CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR}/<rel>" bash "…/<rel>/.ax/hooks/…"` (replacing only that project's goax entries), and doctor §3.14 checks it — never hand-write that file (a real monorepo's hand-written copy was missing four hooks). The same script in a single repo (ADE root = project root) is how `.ax/settings.json.suggested` gets merged: never `jq -s '.[0] * .[1]'`, whose `*` replaces the whole `PreToolUse` array and drops the user's own hooks. It writes no backup file — git is the undo. Model-facing hook text goes through `goax_cap_context [max_bytes] [where]` (default `GOAX_CONTEXT_MAX`=8000 bytes): Claude Code moves any `additionalContext`/stdout over 10,000 chars to a file and shows only a 2,000-char preview without asking the model to read it, so the hook cuts first — on a byte budget (bytes ≥ chars in any locale), never mid-UTF-8, with a `… N바이트 생략 — <where>` tail; `smoke §61` feeds each injecting hook a worst-case input and fails a hook that emits `additionalContext` without the helper. Hooks stay synchronous: `async`/`asyncRewake` deliver on the next turn (or wake only on exit 2 via stderr), which would let the model keep editing on top of a lint failure it hasn't seen.
- `templates/default/.ax/spirit/{values.md,tone.md,README.md}` — cross-cut Spirit (shared agent personality), the trio the plugin ships. `spirit/rules/` is user-curated (no plugin-shipped instances) — categories get added via onboarding/audit, seeded from `_templates/spirit/ops.md` as an opt-in baseline. Spirit rule headers must match `## SP-<CAT>-<NNN>: text` — `doctor` lints this.
- `templates/default/.ax/_templates/{spec,adr,module,spirit,mistakes}/` — SDD templates the user copies into their own work. `_templates/spec/.origin` is a sha snapshot the installer writes; `check-templates-drift.sh` diffs current vs `.origin` to detect user edits vs plugin updates.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ The `spec` skill doesn't generate every artifact upfront. The triage result deci
tasks carry lane assignments (lanes-dispatch.sh ledger)
→ completion gate G1–G6 (+ fresh-context evaluator for L / M×L3)
"split into lanes" → lane — first asks whether the work can be split at all
"build this screen" → screen — spec tables first → screen-designer (fresh context) builds,
renders, measures (screen-measure.sh) and fixes before showing
# Design decisions go to ADR (.ax/docs/adr/<id>-*.md)
```

Expand All @@ -147,6 +149,7 @@ Natural-language tier overrides: `"simple"` / `"spec + tasks"` → standard · `
| "split into lanes" / "run in parallel" | lane — decides first whether the work can be split at all |
| "start implementation" / "run tasks" | spec-implement |
| "validate spec" | spec-validate — NEEDS CLARIFICATION gating |
| "build this screen" / "review this mockup" / `/screen` | screen — spec tables first (tokens · components · copy · exceptions), then the `screen-designer` agent builds, renders, measures in px and fixes (≤3) before showing; report starts with `verdict:`. Self-contained: all design knowledge ships in `skills/screen/references/`; MCPs · browsers · simulators are optional |
| "plan the <task>" / "fix" / "refactor" | triage — Size × Risk classify in 30s |
| "write ADR" / "record decision" | adr — new ADR file |
| "spirit check" | doctor → `spirit-lint.sh` — header format · token duplicates · placeholders |
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.7.7
0.7.8
Loading
Loading