- Problem: the emitted command does not consume the advertised agent chain
(each command owns its own execution behavior), and steps mapped to
argument-less commands were emitted as bare commands with no
machine-readable link to the intended step.
- Fix: adopt the small-router role — emit only commands whose documented
argument form can carry the [Plan: <path>#step-<id>] scope marker
(orch-*, /plan), fail closed with a BLOCKED entry and a manual-use note
for every other command, derive quoted argument forms from the command
files instead of an authoritative hand-written table, and drop the
agent-chain machinery entirely. Adds
tests/skills/plan-orchestrate-registry.test.js, which validates every
command the skill names against commands/<name>.md and
docs/COMMAND-REGISTRY.json and fails when they drift.
- Verification: node tests/skills/plan-orchestrate-registry.test.js (7
fixture groups pass; sabotage-checked against chain reintroduction,
wrong scope-carrying claim, and retired-command reference).
* docs(ito-compute): document ito accept and ito_accept MCP workflow
Updates the canonical ECC skill to cover the new quote acceptance path:
- CLI: ecc ito accept <ticket-id>
- MCP: ito_accept tool
- Explicit buyer-authority guard before accepting
- Clear statement that accept routes to desk, does not purchase
* test(ito-compute): assert the four-tool MCP boundary including ito_accept
The exact-boundary test pinned the three-tool description. Runtime
ito-compute-cli now exposes ito_accept (Ito-Markets/ito-cloud-runtime#1453),
so the template boundary assertion moves to four tools.
* docs(ito-compute): drop the firm-quote gate from the accept workflow
Desk quotes are indicative_paper in production (a firm quote requires the
separate human-held signing path and cannot reach the client), so gating
accept on 'a firm quote is ready' described an unfireable condition. Align
with the runtime contract: accept routes the current desk quote to human
review and the result carries quote_class (ito-cloud-runtime#1453).
- Constrain the build-as-feature-verb override so explicit fix/defect/repair
markers keep the primary as fix and the command as /orch-fix-defect.
- Clarify review+security override: it only wins when the step has no
explicit impl or fix intent; lifecycle (impl/fix) + security takes
precedence over review + security.
- Document explicit tie-breaks for overlapping special-case overrides.
- Make the design/plan/lookup agent chains advisory, because the emitted
/plan command runs inline and does not invoke planner, architect, or
docs-lookup subagents.
Greptile noted that /orch-add-feature does not run database-reviewer, yet the plan-orchestrate skill was composing chains that included it. Since no catalogue command exposes database-reviewer directly, drop it from the db and impl+db chains and from the example, and record the db intent only in the command rationale.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Clarify that the quoted task-description form is only for the
commands that explicitly accept it.
- Document the `impl + test` special-case override so compound
"implement and test" steps emit the right `/orch-*` command and
still include test agents in the chain.
- Tighten the `build used as a feature verb` override so feature
phrasing such as "Add a CI pipeline", "Add a compile step", and
"Create a new lint rule" routes to `/orch-add-feature`, while
failure context keeps build repair in `/build-fix`.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Update the /security-scan output form in the plan-orchestrate command table
to quote and escape validated target paths, preserving spaces as a single
argument.
- Reject control characters during path validation while keeping the default
project-root path and allowed-scope checks.
- Reflect the same validation in Phase 3 and the self-check list.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add a build-used-as-feature-verb override so steps like "Build a new
authentication API" select impl and /orch-add-feature instead of
/build-fix.
- Keep explicit-agent resolution inside the catalogue: map python-reviewer
steps to /code-review rather than emitting language-specific commands
that are not in the skill catalogue.
- Preserve explicit loop patterns (continuous-pr, rfc-dag, infinite) in
the /loop-start output form, defaulting to sequential only when
unspecified.
- Clarify reviewer-class tail rule so it applies to chains that already
contain a reviewer; base chains without a reviewer (design, plan,
lookup, docs, loop) may end with a non-reviewer.
- Extend the plan-input safety gate to validate /security-scan paths
against the command's allowed scope and exclude blocked steps from the
Batch block.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Rename `## When to Activate` to `## When to Use`.
- Remove `build` and `port` from the `impl` trigger words to reduce tag overlap.
- Add explicit `impl`+`security` and `review`+`security` special-case overrides so net-new feature work is not reduced to a scan.
- Make the precedence order explicit and no longer contradictory with the multi-tag notes.
- Default `build` and `review` chains to `build-error-resolver` and `code-reviewer`, aligning with the emitted `/build-fix` and `/code-review` commands; use `<lang>-*` only when a matching language-specific command is emitted.
- Strengthen chain composition: append secondary agents before the tail reviewer, enforce reviewer-class tail, and handle length overflow with a deterministic drop order.
- Detect TypeScript from `tsconfig.json`/TypeScript files/explicit dependency rather than `package.json` alone, and fall back to `code-reviewer`/`build-error-resolver` when no `<lang>-*` agent exists.
- Allow `/code-review <pr-url>` in addition to `<pr-number>`.
- Add untrusted-input guard before emitting quoted task descriptions, and enforce 200–600 character length in the self-check.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The skill now composes the per-step agent chain before mapping it to the
resolvable ECC slash command that runs the equivalent pipeline. This keeps the
decomposition, tagging, and chain-composition logic that #2862 asks for while
still emitting a single ready-to-paste command per step.
- Re-add `--lang` input and language detection so `<lang>-reviewer` and
`<lang>-build-resolver` can be resolved in the chain.
- Add an Agent chain catalogue and chain composition rules.
- Include an `Agent chain` field in the overview table and per-step output.
- Update Phase 2/4/5 and the worked example to reflect the chain.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Emit bare/flag forms for commands that do not accept quoted task descriptions
(/build-fix, /code-review, /security-scan, /test-coverage, /update-docs, /loop-start).
- Add explicit tag precedence so lifecycle-domain words (build, test, migration,
review, security) win over broad impl/fix matches.
- Add Output form column and worked examples for bare commands.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The uninstall cases run two full CLI passes (install, then uninstall)
over several hundred files under a flat 30s timeout, which is tight
enough on Windows CI to fail intermittently with spawnSync ETIMEDOUT.
install-apply.test.js already scales its timeout by platform for the
same reason; match that precedent rather than re-running past the flake.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The guided installer asks how ECC hooks should run, but that consent
lived only in the wizard path. Running install-apply directly with a
profile that includes hooks-runtime still materialized the hook runtime
with no disclosure and no decision.
Gate the apply layer instead, so every entry point is covered:
- disclose the six hook capability groups when a plan would materialize
the hook runtime, and refuse to apply until the caller decides
- --enable-hooks confirms the hook runtime; --no-hooks installs the rest
of the selection without it and records the reduced module closure in
install-state
- surface the pending decision as a dry-run warning
- show the same capability disclosure in the guided installer's plan
preview, so the wizard's hook question states what it is asking about
Plans that never materialize hooks (Kimi, --profile minimal,
--without baseline:hooks) are unaffected and need no flag. Repair and
uninstall operate on already-recorded state and stay unchanged.
The capability taxonomy and the held-materialization behavior come from
Samarjeet Singh Tomar's PR #2634, reworked to fit the single-decision
consent model that shipped with the guided installer in #2649.
Co-Authored-By: Samarjeet Singh Tomar <samar_tomar@hotmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_parse_stream_json() persisted raw tool_input/tool_response content into
ObservationEvents that grade() scores and generate_report() writes to
results/<skill>.md -- a report meant to be shared and reviewed.
--add-dir restricts the agent's additional accessible directory to the
sandbox (SANDBOX_BASE = /tmp/skill-comply-sandbox), but that doesn't stop
the agent's own tool calls (a Bash command using ~ expansion, a scenario
setup_commands entry referencing a dotfile) from emitting the operator's
home directory into tool_input/tool_response -- which then lands
verbatim, truncated but not sanitized, in the written report.
Adds _redact_home_path(), pure stdlib (Path.home()), applied to both
input_str and output_str before they're stored on the ObservationEvent.
Scoped deliberately to the home directory only -- grade() needs real
tool-call semantics for LLM-based compliance classification, so
truncating/stripping content the way a pure logging hook could isn't an
option here; only the operator-identifying path component needs to go.
New TestParseStreamJsonRedactsHomePath class in
skills/skill-comply/tests/test_runner.py (3 tests) -- full file now
10/10 passing, up from 7/7. Confirmed tests/test_invariant_runner.py (the
sandbox-execution security tests from #2149) still passes clean, 4/4.
Fixes#2730
The find -> sort -> read chain in both scripts used newline-delimited
records (plain read -r), so a skill directory name containing a
literal newline would be split across two records. Verified with a
directory literally named "evil\nskill": the old reader produced a
truncated "evil" fragment plus an orphan "skill/SKILL.md" fragment,
inflating the skill count and throwing awk/date errors on the garbage
paths.
Switch to -print0 / sort -z / read -r -d '' in both scripts so a path
is always read as a single record, regardless of its contents. Paths
under scan are untrusted input.
Addresses further CodeRabbit review feedback on PR #2640.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhDjpSfrbPpnpqT3CZBEX1
Following up on the -L fix: find -L can now traverse symlinks, but a
broken symlink target or an unreadable directory makes find skip that
entry and exit non-zero. Both scripts previously redirected find's
stderr to /dev/null and never checked its exit status, so a scan could
silently under-count skills with no indication anything was wrong.
Capture find's exit status and stderr in both scripts; on failure,
print a warning (with the underlying find error) to stderr while still
emitting the best-effort results for whatever was found. Verified with
a permission-denied skill directory: real BSD find exits 1 and reports
"Permission denied" on stderr, now surfaced as an explicit warning
instead of silently dropped.
Addresses CodeRabbit review feedback on PR #2640.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhDjpSfrbPpnpqT3CZBEX1
scan.sh and quick-diff.sh both used `find "$dir" -name "*.md" -type f`,
which missed symlinked skill directories (no -L) and miscounted any
non-skill markdown file sitting in a skills directory as a skill
(matched *.md instead of SKILL.md). Both call sites now use
`find -L "$dir" -name "SKILL.md" -type f`.
Repro (temp dir with 1 real skill, 1 symlinked skill, 1 stray .md file):
before: 2 skills found (real skill + the stray .md, symlinked skill invisible)
after: 2 skills found (real skill + symlinked skill, stray .md excluded)
Fixes#2598
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhDjpSfrbPpnpqT3CZBEX1
Extends scripts/ci/validate-skills.js to also scan docs/{locale}/skills/
translated mirrors, not just curated skills/. Adds detection for the
YAML defect classes from #2630 without a parser dependency: unquoted
values containing ": " (glued next key / dropped quoting), values
starting with the reserved '@'/'`' indicators, and missing frontmatter
blocks entirely (required only for docs mirrors; curated skills/ keeps
its existing tolerant behavior).
Greptile flagged that the env-access guard in
gateguard-env-documented.test.js could be bypassed via reflective reads
of process.env (Reflect.get/has/set/deleteProperty/defineProperty/
getOwnPropertyDescriptor/ownKeys), since none of the existing
UNSUPPORTED_ACCESS patterns matched that form.
Add a rule that rejects Reflect.get/has/set/deleteProperty/
defineProperty/getOwnPropertyDescriptor/ownKeys(process.env, ...) and
three self-check fixture cases (Reflect.get, Reflect.has,
Reflect.ownKeys) so the guard is pinned against silently missing them
again.
Negative control: commenting out only the new rule reproduces exactly
the reported gap (the 3 new fixture cases fail with "access guard
missed: Reflect.get, Reflect.has, Reflect.ownKeys"); restoring it goes
back to 10/10.