From b98342907f45e7d8c6cfc24fb687827d7ffbecbe Mon Sep 17 00:00:00 2001 From: mergetest Date: Wed, 23 Sep 2026 06:53:44 -0700 Subject: [PATCH 1/2] chore(release): move main to unpublished 0.9.13 v0.9.12 is tagged at the current trunk, so shipped bytes cannot change until the manifests name the next patch. Mirrors the last bump (d270645): the three source manifests, the OpenCode lockfile, and a plugin rebuild. Co-Authored-By: Claude Fable 5.1 --- agentkit/.claude-plugin/plugin.json | 2 +- agentkit/.codex-plugin/plugin.json | 2 +- opencode/package-lock.json | 4 ++-- opencode/package.json | 2 +- plugin/agentkit/.claude-plugin/plugin.json | 2 +- plugin/agentkit/.codex-plugin/plugin.json | 2 +- plugin/opencode/package.json | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/agentkit/.claude-plugin/plugin.json b/agentkit/.claude-plugin/plugin.json index 8ec78423..a7036d38 100644 --- a/agentkit/.claude-plugin/plugin.json +++ b/agentkit/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentkit", - "version": "0.9.12", + "version": "0.9.13", "description": "Board-aware parallel issue and PR review skills, with lifecycle hooks and a per-repository contract.", "author": { "name": "wrzonance", diff --git a/agentkit/.codex-plugin/plugin.json b/agentkit/.codex-plugin/plugin.json index fe92f129..9cf3162e 100644 --- a/agentkit/.codex-plugin/plugin.json +++ b/agentkit/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentkit", - "version": "0.9.12", + "version": "0.9.13", "description": "Board-aware parallel issue and PR review skills, with lifecycle hooks and a per-repository contract.", "author": { "name": "wrzonance", diff --git a/opencode/package-lock.json b/opencode/package-lock.json index cb349ad8..6864512b 100644 --- a/opencode/package-lock.json +++ b/opencode/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wrzonance/agentkit-opencode", - "version": "0.9.12", + "version": "0.9.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wrzonance/agentkit-opencode", - "version": "0.9.12", + "version": "0.9.13", "license": "MIT", "devDependencies": { "@opencode-ai/plugin": "1.18.18" diff --git a/opencode/package.json b/opencode/package.json index c47d56bf..d4fcbe01 100644 --- a/opencode/package.json +++ b/opencode/package.json @@ -1,6 +1,6 @@ { "name": "@wrzonance/agentkit-opencode", - "version": "0.9.12", + "version": "0.9.13", "description": "Agent Kit plugin for OpenCode CLI: injects the environment contract into the model's system prompt at session start.", "type": "module", "main": "./index.js", diff --git a/plugin/agentkit/.claude-plugin/plugin.json b/plugin/agentkit/.claude-plugin/plugin.json index 8ec78423..a7036d38 100644 --- a/plugin/agentkit/.claude-plugin/plugin.json +++ b/plugin/agentkit/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentkit", - "version": "0.9.12", + "version": "0.9.13", "description": "Board-aware parallel issue and PR review skills, with lifecycle hooks and a per-repository contract.", "author": { "name": "wrzonance", diff --git a/plugin/agentkit/.codex-plugin/plugin.json b/plugin/agentkit/.codex-plugin/plugin.json index fe92f129..9cf3162e 100644 --- a/plugin/agentkit/.codex-plugin/plugin.json +++ b/plugin/agentkit/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agentkit", - "version": "0.9.12", + "version": "0.9.13", "description": "Board-aware parallel issue and PR review skills, with lifecycle hooks and a per-repository contract.", "author": { "name": "wrzonance", diff --git a/plugin/opencode/package.json b/plugin/opencode/package.json index c47d56bf..d4fcbe01 100644 --- a/plugin/opencode/package.json +++ b/plugin/opencode/package.json @@ -1,6 +1,6 @@ { "name": "@wrzonance/agentkit-opencode", - "version": "0.9.12", + "version": "0.9.13", "description": "Agent Kit plugin for OpenCode CLI: injects the environment contract into the model's system prompt at session start.", "type": "module", "main": "./index.js", From c8d16c56d2dd6f45711fcc5f9c96b1d6a3981c17 Mon Sep 17 00:00:00 2001 From: mergetest Date: Wed, 23 Sep 2026 07:18:15 -0700 Subject: [PATCH 2/2] fix(parallel-issues): name the selection helper by its shipped path A Codex root on 0.9.12 met bare `pick-issues.sh` in Step 2b, guessed `$agentkit/parallel-issues/scripts/`, searched with rg (which skips the hidden `.shared/`), reported the helper missing, and ended the run (#889): one wasted root turn and one human round trip for a helper that ships. Step 2b now spells `$agentkit/.shared/scripts/pick-issues.sh` where the section first names it, and `degraded=yes` needs `ls -l` output on that path plus the failure text, never a guessed path. The skill body stays under its previous estimated-token count. `triage-issues.sh --help` ends with the next command so the path reaches the root as tool output. `lint-helper-refs.sh` now holds mention order per heading section: a shared or cross-skill helper named bare before its path in the same section is a violation; a skill's own scripts/ helpers are exempt because the natural guess lands there. The gate fails on origin/main at parallel-issues:248 and onboard-repo:250; both are fixed here at zero body growth. The helper tree ceiling moves to the exact new measurement. Closes #889 Co-Authored-By: Claude Fable 5.1 --- .../skills/.shared/scripts/triage-issues.sh | 6 ++-- agentkit/skills/onboard-repo/SKILL.md | 8 ++--- agentkit/skills/parallel-issues/SKILL.md | 12 +++---- tests/lint-helper-refs.sh | 35 +++++++++++++++++-- tests/lint-helper-size.sh | 3 +- tests/test-helper-refs.sh | 23 ++++++++++++ tests/test-parallel-dispatch-contract.sh | 2 +- 7 files changed, 71 insertions(+), 18 deletions(-) diff --git a/agentkit/skills/.shared/scripts/triage-issues.sh b/agentkit/skills/.shared/scripts/triage-issues.sh index 2515fedc..74f21b38 100755 --- a/agentkit/skills/.shared/scripts/triage-issues.sh +++ b/agentkit/skills/.shared/scripts/triage-issues.sh @@ -49,10 +49,10 @@ Recipe: triage once "$agentkit/.shared/scripts/triage-issues.sh" --limit 30 # Alternative explicit mode (replace with the requested numbers; do not run both): # "$agentkit/.shared/scripts/triage-issues.sh" --issues 57,54 + "$agentkit/.shared/scripts/pick-issues.sh" --help # next: mechanical selection over this digest -The digest is evidence: each line includes issue number, board Status, -prior-art verdict, ADR candidates, and referencing PR. It also warms the -project-item cache used by the board mover. +Digest lines are evidence (number, Status, prior-art verdict, ADR candidates, +referencing PR) and warm the board mover's project-item cache. EOF } diff --git a/agentkit/skills/onboard-repo/SKILL.md b/agentkit/skills/onboard-repo/SKILL.md index 452aa1fa..088ad6df 100644 --- a/agentkit/skills/onboard-repo/SKILL.md +++ b/agentkit/skills/onboard-repo/SKILL.md @@ -247,10 +247,10 @@ without a root test command, `agent-run.sh --cmd test` needs a dispatcher. Edit `.agent/config.env` directly — values are line-wise and never sourced. Write active `AGENT_REVIEW_PROVIDERS=...` and each command unquoted, then prove parsing. There is no approval -step for the first run — `agent-run.sh --cmd ` runs a declared command directly — but hand -the first invocation of each name to the user anyway: onboarding is attended, and them running and -reading it once is the actual review moment before this skill leaves the command declared for -every future session: +step for the first run — `$agentkit/.shared/scripts/agent-run.sh --cmd ` runs a declared command +directly — but hand each name's first invocation to the user anyway: onboarding is attended, and +that first run is the review moment before this skill leaves the command declared for every +future session: ```bash [ -d "${agentkit:-}/.shared/scripts" ] && [ "${agentkit_provenance:-}" = ok ] || { printf "%s\n" "agentkit unresolved: prepend THE CACHE REHYDRATION block" >&2; exit 1; } diff --git a/agentkit/skills/parallel-issues/SKILL.md b/agentkit/skills/parallel-issues/SKILL.md index 0d29bbf7..7276c3c5 100755 --- a/agentkit/skills/parallel-issues/SKILL.md +++ b/agentkit/skills/parallel-issues/SKILL.md @@ -245,16 +245,16 @@ referencing it) is documented in Use this for automatic or numbered thematic-Backlog selection; otherwise explicit numbers win. **A thin Ready column is an invitation, not a blocker.** Read [references/triage-and-selection.md](references/triage-and-selection.md#step-2b-choose-the-set-yourself) -in full. Selection consumes `pick-issues.sh` output only: a body-free record carries status, +in full. Selection consumes `$agentkit/.shared/scripts/pick-issues.sh` output only: a body-free record carries status, eligibility, blockers, dispatch/queue state, `predictedWriteSet`, `requirementsDigest`, `bodyCache`, and `workShape`. `workShape: "no-code"` means HOLD before worktree creation; retain `holdReason`, count `no-code-hold`, and use the anchored [work-shape verdict](references/triage-and-selection.md#work-shape-verdict) for ambiguity. -`$agentkit/.shared/scripts/pick-issues.sh` answers only the mechanical half; the root applies Backlog ranking, Step 3 conflict analysis, the slot cap, and the batch board move in order. Emit `Selection funnel:` -exactly once after the final conflict and slot-cap decisions and before dispatch. Full, thin, and -empty sets report requested/eligible/dispatched plus one reason per exclusion. -An empty selection is an answer only with evidence. If `pick-issues.sh` is missing, non-executable, or fails, -report `Selection funnel: degraded=yes; eligible=unknown`, its exact path and failure reason. +The helper answers only the mechanical half; the root applies Backlog ranking, Step 3 conflict analysis, the slot cap, and the batch board move in order. Emit `Selection funnel:` +exactly once after the final conflict and slot-cap decisions and before dispatch. Every set reports +requested/eligible/dispatched plus one reason per exclusion. +An empty selection is an answer only with evidence. Report `Selection funnel: degraded=yes; eligible=unknown` +only with `ls -l "$agentkit/.shared/scripts/pick-issues.sh"` output and its failure text, never a guessed path. Stop automatic selection until it succeeds. A triage fallback cannot justify `eligible=0` or an empty Ready column; any assessor fan-out still uses only the slots available under the spawn cap. Preserve partial evidence as degraded. ### Step 3: Conflict analysis (file-level) diff --git a/tests/lint-helper-refs.sh b/tests/lint-helper-refs.sh index 4c46d2ad..1faf6bfb 100755 --- a/tests/lint-helper-refs.sh +++ b/tests/lint-helper-refs.sh @@ -90,10 +90,25 @@ check_token() { # Only shipped helper basenames belong to this rule: external URLs, repository # scripts, and example commands are not kit interfaces. Keep occurrence order, # including within a line, so a later path cannot conceal an earlier bare name. +# +# The same order holds inside every heading section: agents read SKILL.md by +# anchored section, and a section that spells a helper's path only after its +# bare name has already sent the reader guessing. #889: bare `pick-issues.sh` +# five lines ahead of its path was guessed under the skill's own scripts/ and +# the run stopped. That guess lands for the skill's own helpers, so only +# shared and cross-skill helpers hold the section order. A heading-shaped +# shell comment inside fenced code is not a section break. scan_first_mentions() { - local source_file=$1 line_no content token name candidate - local -A mentioned=() + local source_file=$1 line_no content token name candidate in_fence=0 reported own_scripts + local -A mentioned=() section_bare=() section_path=() + own_scripts=$(skill_root_for "$source_file")/scripts while IFS=: read -r line_no content; do + [[ $content =~ ^[[:space:]]*\`\`\` ]] && in_fence=$((1 - in_fence)) + if ((in_fence == 0)) && [[ $content =~ ^#{1,6}[[:space:]] ]]; then + section_bare=() section_path=() + continue + fi + [[ $content == *.sh* ]] || continue while IFS= read -r token; do name=${token##*/} [[ -n ${helper_paths[$name]:-} ]] || continue @@ -107,14 +122,28 @@ scan_first_mentions() { ;; *) candidate=$skills_dir/${helper_paths[$name]} ;; esac + reported=0 if [[ -z ${mentioned[$name]:-} ]]; then mentioned[$name]=1 if [[ $token != "\$agentkit/"* || ! -f $candidate ]]; then + reported=1 # shellcheck disable=SC2016 # diagnostic names the literal root report "$source_file" "$line_no" "$token" \ "\$agentkit/${helper_paths[$name]}" 'first helper mention; use a $agentkit-relative path for' fi fi + if [[ $token != */* ]]; then + ((reported)) || [[ -n ${section_path[$name]:-}${section_bare[$name]:-} ]] || + [[ -f $own_scripts/$name ]] || section_bare[$name]=$line_no + elif [[ -f $candidate ]]; then + if [[ -n ${section_bare[$name]:-} ]]; then + # shellcheck disable=SC2016 # diagnostic names the literal root + report "$source_file" "${section_bare[$name]}" "$name" \ + "\$agentkit/${helper_paths[$name]}" 'section-first helper mention; a later path in the same section cannot repair' + unset 'section_bare[$name]' + fi + section_path[$name]=1 + fi # lib/ means source-only unless an explicitly documented CLI exists. # contract-cache is currently the sole dual-use library; executable # permission alone does not establish an invocation interface. @@ -124,7 +153,7 @@ scan_first_mentions() { report "$source_file" "$line_no" "$token" 'source/sourced-only library label' 'library interface for' fi done < <(grep -oE '[[:alnum:]_.$/{}/:-]+\.sh' <<< "$content" || true) - done < <(grep -nE '\.sh' "$source_file" || true) + done < <(grep -n '' "$source_file" || true) } scan_file() { diff --git a/tests/lint-helper-size.sh b/tests/lint-helper-size.sh index 5d2fbe81..bd72eaf8 100755 --- a/tests/lint-helper-size.sh +++ b/tests/lint-helper-size.sh @@ -198,7 +198,8 @@ readonly MAX_HELPER_TOKENS=10000 # #873 evidence repair + #874/#875 merge: exact combined helper tree measurement. # #873/#874 + #875 + #876 provider-alias repair: exact combined helper tree measurement. # #873 PR repair: verification-scoped post-run cleanliness and setup compatibility. -readonly MAX_TREE_TOKENS=477429 +# #889: triage --help ends with the selection helper's shipped path: exact tree measurement. +readonly MAX_TREE_TOKENS=477442 violations=0 checked=0 diff --git a/tests/test-helper-refs.sh b/tests/test-helper-refs.sh index e01b7cff..a13a3a47 100755 --- a/tests/test-helper-refs.sh +++ b/tests/test-helper-refs.sh @@ -198,6 +198,29 @@ printf '%s\n' 'Source `$agentkit/.shared/scripts/lib/private-dir.sh` (sourced-on > "$hfixture/demo/SKILL.md" assert_rc 0 'source instructions and the documented contract-cache CLI remain valid' -- "$lint" "$hfixture" +# #889: a section that spelled the helper's path only after its bare name sent +# a root guessing under the skill's own scripts/ and stopped the run. Order +# holds per heading section for shared and cross-skill helpers (that guess +# lands for the skill's own), and a heading-shaped shell comment inside a +# fence is not a section break. +printf '%s\n' 'Run `$agentkit/.shared/scripts/pick-issues.sh` once.' \ + '' '### Later step' 'Selection consumes `pick-issues.sh` output only.' \ + 'Then `$agentkit/.shared/scripts/pick-issues.sh` answers the rest.' > "$hfixture/demo/SKILL.md" +section_output=$("$lint" "$hfixture" 2>&1) +assert_eq 1 "$?" 'a later path in the same section does not repair a bare section-first mention' +assert_contains "$section_output" 'SKILL.md:4' \ + 'the section diagnostic names the bare line, not the later path' +printf '%s\n' 'Run `$agentkit/.shared/scripts/pick-issues.sh` once.' \ + '```bash' '# Step: no guessing' 'pick-issues.sh --help' '```' \ + 'Then `$agentkit/.shared/scripts/pick-issues.sh` answers the rest.' > "$hfixture/demo/SKILL.md" +assert_rc 0 'a heading-shaped comment inside a fence does not start a section' -- "$lint" "$hfixture" +mkdir -p "$hfixture/demo/scripts" +touch "$hfixture/demo/scripts/own-helper.sh" +printf '%s\n' 'Run `$agentkit/demo/scripts/own-helper.sh` once.' \ + '' '### Later step' 'Then `own-helper.sh` again before `$agentkit/demo/scripts/own-helper.sh`.' \ + > "$hfixture/demo/SKILL.md" +assert_rc 0 'a helper shipped in the skill scripts/ directory may go bare before its path in a section' -- "$lint" "$hfixture" + assert_eq yes "$([[ $(wc -c < "$root/agentkit/skills/.shared/six-step-loop.md") -le 6100 ]] && printf yes || printf no)" \ 'six-step-loop policy stays at or under 6100 bytes' diff --git a/tests/test-parallel-dispatch-contract.sh b/tests/test-parallel-dispatch-contract.sh index 1226a012..aba7ab86 100755 --- a/tests/test-parallel-dispatch-contract.sh +++ b/tests/test-parallel-dispatch-contract.sh @@ -516,7 +516,7 @@ assert_contains "$text" 'Selection funnel:' \ assert_contains "$normalized_text" 'exactly once after the final conflict and slot-cap decisions and before dispatch' \ 'selection reconciliation is emitted once at the dispatch boundary' assert_contains "$normalized_text" \ - '`$agentkit/.shared/scripts/pick-issues.sh` answers only the mechanical half; the root applies Backlog ranking, Step 3 conflict analysis, the slot cap, and the batch board move in order' \ + 'The helper answers only the mechanical half; the root applies Backlog ranking, Step 3 conflict analysis, the slot cap, and the batch board move in order' \ 'selection keeps judgment and board mutation root-owned' assert_contains "$triage_and_selection_text" \ 'Selection funnel: requested=3 eligible=3 dispatched=3 exclusions=none' \