feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: add structured output to report and status built-ins - #306

Merged
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins
Aug 19, 2026
Merged

feat: add structured output to report and status built-ins#306
ankitranjan7 merged 3 commits into
agentrhq:mainfrom
Agnik47:feat/175-structured-output-builtins

Conversation

@Agnik47

Copy link
Copy Markdown
Contributor

Part of #175 (tracking: #171). This is the first of the two PRs I proposed in #175 (comment) — the non-browser built-ins. Browser reads follow separately.

What

validate, verify, doctor, bare skills, daemon status, and profile list all returned stable data internally but rejected -f/--format and printed hand-written text only. Each now routes through the shared resolveOutputFormat + render path from #190.

webcmd validate -f json
webcmd verify -f yaml
webcmd doctor -f json
webcmd daemon status -f json
webcmd profile list -f json
webcmd skills -f json

adapter status is on the issue's list but already gained -f in #190, so it needed no change here.

Behavior

Each command keeps its human-readable report as the table rendering, which stays the default. Any other format returns the underlying result object.

I followed the convention-audit precedent from #190 and branch on the raw format rather than the TTY-resolved one. I first tried resolving through the implicit non-TTY rule, but that moves profile list's prose onto the structured path whenever stdout is a pipe, which breaks the guidance contract two existing tests encode (reports stale daemon instead of no profiles…, uses runtime profile wording…). Branching on the raw format means no existing implicit behavior changes and nothing here is breaking — the issue asks for these commands to stop rejecting -f, not to change what an unflagged invocation prints.

Two commands needed a real data model rather than a straight serialization:

  • daemon status gains a projection mirroring the text rendering: running, stale, pid, version, cliVersion, uptimeMs, runtimeConnected, runtimeName, runtimeVersion, profileRequired, profileDisconnected, profiles, memoryMB, port. It returns { "running": false } when no daemon is reachable.
  • profile list returns one row per profile — contextId, alias, default, connected, runtimeVersion — covering both connected profiles and saved aliases that are not currently connected, which the prose surfaced but no caller could parse. That aligns it with the hosted profile-list row set.

For those two, daemon guidance ("Daemon is not running…", stale-daemon hints) goes to stderr under structured formats so stdout stays parseable. It stays on stdout for table.

Bare skills and skills list now share one renderer instead of duplicating the row set with a hardcoded format, which is the de-duplicating half of the issue's "or make it a true alias" option.

Still open from my issue comment

Neither of these blocks review, and I'm happy to adjust:

  1. Bare skills — I shared the renderer rather than restructuring the Commander wiring into a literal alias. Say the word if you'd prefer the true alias.
  2. profile list — I kept the local field set (alias, default marker, runtime version) and matched hosted's format handling rather than adopting hosted's column set, since the local fields have no hosted equivalent.

Testing

  • npm run typecheck, npm run build — clean
  • npm run check:hosted-contract — contract bytes unchanged
  • npm run check:plugin-parity, check:package-bin, check:codex-plugin — pass
  • 14 new tests in src/cli.test.ts covering JSON/YAML per command family, the stdout/stderr split, bare-skills/skills list equivalence, and -f xml rejection (exit 2, before any side effects)
  • Verified against the built CLI, including that profile list -f json 2>/dev/null emits clean []

On the full suite I get 122 pre-existing failures on this Windows machine (symlink EPERM and a build-test timeout). I confirmed that count is identical on a clean main — same 12 files — and that passing tests go 5450 → 5464, exactly the 14 added. No regressions; CI should be a cleaner signal than my local box.

@github-actions

github-actionsBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

The two red jobs — Unit tests (ubuntu-latest, shard 1/2) and Plugin tests (ubuntu-latest) — are a runner infrastructure failure, not a test failure. Both died in the Set up job step after 3–4s:

##[error]An action could not be found at the URI
'https://codeload.github.com/actions/checkout/tar.gz/d23441a48e516b6c34aea4fa41551a30e30af803'
##[error]Failed to download archive '...' after 1 attempts.

That is codeload failing to serve actions/checkout@v6; the job never reached a test. Unit tests (ubuntu-latest, shard 2/2) ran on the same image and passed, and every other job is green — builds on all three OSes, both macOS and Windows unit shards, macOS/Windows plugin tests, Bun, audit, and docs sync.

I can't re-run them myself (needs admin on this repo), and I'd rather not push an empty commit and re-trigger the whole matrix for a CDN blip. A re-run of just those two should clear it whenever someone gets a chance.

@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from 228982c to af84f96CompareAugust 14, 2026 07:30
@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Resolved — no re-run needed after all. I amended the commit (identical tree, git diff 228982c af84f96 is empty) to pick up fresh runners, and both ubuntu jobs now pass: unit shard 1/2 in 43s and plugin tests in 1m12s. All checks green.

That confirms it was the transient codeload fetch of actions/checkout@v6 rather than anything in the diff. Sorry for the noise on your notifications.

@Agnik47

Copy link
Copy Markdown
ContributorAuthor

Thanks for the review! Quick check before this goes further — I'd left a scoping comment on #175 proposing to split this into two PRs (builtins here, browser reads separately), but it seems to have disappeared. Also saw an older comment on #175 mentioning it might already be spoken for via #190 — that one actually closed #172, a sibling issue, so I want to make sure #175 itself is still open for me to work on before I start phase 2.

Part of agentrhq#175. `validate`, `verify`, `doctor`, bare `skills`, `daemon status`,
and `profile list` returned stable data internally but rejected `-f/--format`
and printed hand-written text only. Each now routes through the shared
`resolveOutputFormat` + `render` path introduced in agentrhq#190.
`adapter status` already gained `-f` in agentrhq#190, so it needed no change here.
Each command keeps its human-readable report as the `table` rendering, which
remains the default, and returns the underlying result object under any other
format. Following the `convention-audit` precedent, the human text is chosen on
the raw format rather than the TTY-resolved one, so no existing implicit
behavior changes.
`daemon status` gains a machine-readable projection that mirrors the text
rendering, reporting `{ running: false }` when no daemon is reachable.
`profile list` returns one row per profile covering both connected profiles and
saved-but-disconnected aliases, aligning it with the hosted profile-list row
set. Daemon guidance for those two goes to stderr under structured formats so
stdout stays parseable.
Bare `skills` and `skills list` now share one renderer instead of duplicating
the row set with a hardcoded format.
Browser read commands are intentionally left for a follow-up: they go through
the session/bridge layer and need separate care around the streaming and
JSONL-follow exclusions the issue calls out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVuD882dJuEwWKWBLaf7bs
@Agnik47
Agnik47force-pushed the feat/175-structured-output-builtins branch from af84f96 to eb7b9dcCompareAugust 18, 2026 18:30
The skill pipeline from agentrhq#347 builds skills/ from skill-src/ and `make
verify` rebuilds to compare hashes. The report-and-status paragraph was
applied to the published skills/webcmd-usage/SKILL.md only, so a fresh
build regenerated it from the untouched source and the hashes diverged.
Same text, now in skill-src/webcmd-usage/SKILL.src.md. The webcmd-browser
skill in this branch already had both halves.
@ankitranjan7

Copy link
Copy Markdown
Contributor

Thank you @Agnik47 — this is a clean slice of #175 and a real win for agents that need parseable validate / verify / doctor / skills / daemon status output.

Merged main into the branch so it stays your PR (authorship intact). Landing this now.

@ankitranjan7
ankitranjan7 merged commit 0ee02ce into agentrhq:mainAug 19, 2026
8 checks passed
ankitranjan7 added a commit to Agnik47/webcmd that referenced this pull request Aug 19, 2026
Keep both the agentrhq#306 reports/status docs and the browser verify -f section.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@Agnik47@ankitranjan7@adikulkarni006