diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 70a625d..64bc2e8 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -27,7 +27,7 @@ { "name": "agentic-engineering", "description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md", - "version": "5.1.4", + "version": "5.1.5", "source": "./plugins/agentic-engineering" }, { diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 70a625d..64bc2e8 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -27,7 +27,7 @@ { "name": "agentic-engineering", "description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md", - "version": "5.1.4", + "version": "5.1.5", "source": "./plugins/agentic-engineering" }, { diff --git a/plugins/agentic-engineering/.claude-plugin/plugin.json b/plugins/agentic-engineering/.claude-plugin/plugin.json index a1d2346..a32765a 100644 --- a/plugins/agentic-engineering/.claude-plugin/plugin.json +++ b/plugins/agentic-engineering/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "agentic-engineering", "description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md", - "version": "5.1.4", + "version": "5.1.5", "author": { "name": "devantler-tech", "url": "https://github.com/devantler-tech" diff --git a/plugins/agentic-engineering/agents/portfolio-surveyor.agent.md b/plugins/agentic-engineering/agents/portfolio-surveyor.agent.md index ea73ce6..b441451 100644 --- a/plugins/agentic-engineering/agents/portfolio-surveyor.agent.md +++ b/plugins/agentic-engineering/agents/portfolio-surveyor.agent.md @@ -502,6 +502,21 @@ by a successful consumer of partial output and the read-only role never writes a The bundled `forge-readonly-guard.sh` recognises only this exact installed sibling; offline `--input` remains denied. Exit 0 is a complete classification; exit 2 means `unknown`, never green. +**Read the verdict from the helper's native tool result, never by appending the guard-denied `; echo +"EXIT=$?"` idiom.** The guard rejects shell chaining before the helper runs, while the tool result +already surfaces stdout, stderr, and the process status. Classify that complete result with this closed +set: + +| Native process status and output | Meaning | +|---|---| +| observed native process status 0 and completely empty output | no red runs → that branch is **green** | +| observed native process status 0 and **well-formed TSV rows** — exactly eight tab-separated fields in helper order: numeric `workflow_id`, red `conclusion` (`failure`, `timed_out`, or `startup_failure`), `html_url`, `name`, supported `event`, `path`, valid `created_at`, numeric `run_id` | those are the **red runs** | +| any nonzero or unavailable native process status; or any other output, including mixed valid and malformed rows | the helper FAILED → **`QUERY-UNKNOWN`**; never `nothing_on_fire: true` | + +Every nonempty line must match the complete eight-field row shape. Do not accept a numeric first +field, a diagnostic prefix, or any other partial predicate as sufficient, and never treat merely +nonempty output as red runs. Status 0 plus empty output is the only green case. + Invoke it from a process that already has `GH_TELEMETRY=0` (or `false`) in the environment, or rely on the helper's own export of `GH_TELEMETRY=0` before its remote `gh api` GET — GitHub CLI 2.96.0 otherwise writes `gh/device-id` on a certified read. Do not prefix the helper with diff --git a/plugins/agentic-engineering/plugin.json b/plugins/agentic-engineering/plugin.json index a1d2346..a32765a 100644 --- a/plugins/agentic-engineering/plugin.json +++ b/plugins/agentic-engineering/plugin.json @@ -1,7 +1,7 @@ { "name": "agentic-engineering", "description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md", - "version": "5.1.4", + "version": "5.1.5", "author": { "name": "devantler-tech", "url": "https://github.com/devantler-tech" diff --git a/plugins/agentic-engineering/resources/provider-neutral.desired-state.json b/plugins/agentic-engineering/resources/provider-neutral.desired-state.json index 05d35ec..9756634 100644 --- a/plugins/agentic-engineering/resources/provider-neutral.desired-state.json +++ b/plugins/agentic-engineering/resources/provider-neutral.desired-state.json @@ -66,7 +66,7 @@ "portfolio-surveyor": { "enabled": true, "mode": "delegated-read-only", - "definitionSha256": "53dfcda04e4e404b6d13fb465aa76c574a79401d1b2be1058beae1ccc9bc6425" + "definitionSha256": "8e31a79bb60e0c68f92f95c5f4fbf2abda78e719dd40c04392f9e2f74de91275" }, "agent-improver": { "enabledWhen": "Both optional consumer contract sections are present", diff --git a/plugins/agentic-engineering/scripts/portfolio-surveyor-agent.test.sh b/plugins/agentic-engineering/scripts/portfolio-surveyor-agent.test.sh index fef1d4b..d74cef9 100755 --- a/plugins/agentic-engineering/scripts/portfolio-surveyor-agent.test.sh +++ b/plugins/agentic-engineering/scripts/portfolio-surveyor-agent.test.sh @@ -23,6 +23,26 @@ if grep -Fq -- '--json issueType,blockedBy,assignees' "$SURVEYOR"; then fail 'dependency reads must not enumerate blocker nodes through gh issue view' fi +CI_STEP=$(sed -n \ + '/^### 4\. CI red on the default branch/,/^### 5\. Triage, stale, and advance signals/p' \ + "$SURVEYOR" | tr '\n' ' ' | tr -s '[:space:]' ' ') +[ -n "$CI_STEP" ] || fail 'could not extract the default-branch CI step' +# shellcheck disable=SC2016 # The asserted agent text contains a literal shell idiom. +grep -Fq 'Read the verdict from the helper'"'"'s native tool result, never by appending the guard-denied `; echo "EXIT=$?"` idiom.' \ + <<<"$CI_STEP" || + fail 'default-branch CI must prescribe the native tool result instead of denied shell exit capture' +grep -Fq '| observed native process status 0 and completely empty output | no red runs → that branch is **green** |' \ + <<<"$CI_STEP" || + fail 'green must require both observed native process status 0 and completely empty classifier output' +# shellcheck disable=SC2016 # Backticks belong to the asserted Markdown contract. +grep -Fq '| observed native process status 0 and **well-formed TSV rows** — exactly eight tab-separated fields in helper order: numeric `workflow_id`, red `conclusion` (`failure`, `timed_out`, or `startup_failure`), `html_url`, `name`, supported `event`, `path`, valid `created_at`, numeric `run_id` | those are the **red runs** |' \ + <<<"$CI_STEP" || + fail 'the complete eight-field TSV predicate must map to the red verdict as one table row' +# shellcheck disable=SC2016 # Backticks belong to the asserted Markdown contract. +grep -Fq '| any nonzero or unavailable native process status; or any other output, including mixed valid and malformed rows | the helper FAILED → **`QUERY-UNKNOWN`**; never `nothing_on_fire: true` |' \ + <<<"$CI_STEP" || + fail 'nonzero or unavailable status and malformed or mixed output must fail closed as QUERY-UNKNOWN' + JQ_FILTER=$(sed -n \ "/issueDependenciesSummary{blockedBy totalBlockedBy}/{n;s/^[[:space:]]*--jq '\\(.*\\)'$/\\1/p;}" \ "$SURVEYOR")