Repository navigation
Closed
feat(app-control): publish masked CI captures through a hub Mask hand-off and a none: values result#13757
Feature
3 / 33 of 3 issues completed
Copy link
Labels
priority: mediumReal value, no hard deadline; normal backlog flow.Real value, no hard deadline; normal backlog flow.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.Refactors, migrations, contract changes; cross-cutting and hard to reverse.
Description
Refs: #11364
Parent: #11364 (done-when rows 1 and 8). session: App Driven PR Verify
Problem
The CI capture publishes no screenshot, so the pr-verify judge sees only run-e2e's pass and fail lines. The #11364 grade shows it: run 42235412941 recorded 12 captures and uploaded 1 file. There are two causes:
- The hub has no
## Mask..claude/skills/control-claude-code-plugins/SKILL.mdhas no## Masksection, so drive's post-check marks every capturenot-checked(plugins/app-control/skills/drive/reference/evidence.md:99-107). - Key auth has no account values.
claude auth status --jsonreports"authMethod": "api_key"with noemailororgName(probe 2026-11-06, Claude Code 2.1.319).plugins/harness-ops/skills/control-claude-code/cli/account.mjsthen exits 1, and drive treats a failedvalues:source asnot-checked(evidence.md:79-82).
Design (decided; owner decisions on #11364 issuecomment-6689952950 settle the mechanisms)
- Hand-off, not a copy. The hub's
## Maskhands off to the driving control skill's## Mask, as the hub's other sections already hand off (hubSKILL.md:10-12). The 12 mask lines stay in one place (owner standing direction §6).- Resolution rule: the target is the hub named on the hub's
Driving tool:line. - Trusted root:
--trusted-root/trusted-root=covers the target too, so a PR head cannot supply its own masks or values source. - Unreadable target: a target that cannot be read leaves every capture
not-checked.
- Resolution rule: the target is the hub named on the hub's
- The
none:result. Avalues:cli/source may print exactly one line,none: <reason>, and exit 0. That source then resolves with no values; this reuses the## Masknone:grammar (plugins/app-control/reference/control-skill.md:215).- The check applies to each source on a
values:line. - Anything else stays
not-checked: a non-zero exit, empty output, or extra lines alongsidenone:. - The reason is recorded in
report.jsonasvalues_none: [{source, reason}].
- The check applies to each source on a
account.mjsprintsnone:only for key auth. It printsnone: API-key auth has no signed-in accountand exits 0 only whenauthMethodisapi_keywith no email and no organization. An OAuth session with no identity still exits 1.accountValueskeeps returning an array: the driver masks with it at capture time (driver.mjs:716-718).
Work: one PR per plugin, in this order
- app-control (contract):
reference/control-skill.md"The Mask section": the hand-off line, its resolution and trusted-root rule, and thenone:source result.drive/reference/evidence.md"Mask post-check": follow the hand-off, acceptnone:per source, recordvalues_none.map/scripts/check-map.sh(and its test): accept the hand-off, and runmask-missingagainst the resolved target. The fixture is a hub whose Capture listsscreenshotand whose Mask hands off.- Drive evals:
- hand-off →
applied; - unreadable target →
not-checked; - one
none:source → publishable; none:plus a resolved source → the values are scanned;none:plus an extra line →not-checked.
- hand-off →
- Version bump and changelog fragment.
- The repo hub's
## Maskhand-off line ships in this PR.
- testing (
run-e2e/SKILL.md, Step 5 and lines 124-127):- Follow the hand-off when it reads
values:, under the same trusted-root rule, and acceptnone:. - Eval: the hub hands off and the target's
values:source fails →e2e-summary.jsonstays out ofpublishable. - Version bump and changelog fragment.
- Follow the hand-off when it reads
- harness-ops (
control-claude-code):cli/account.mjsprintsnone:for key auth. Tests at theaccount.mjslevel: key auth with no identity → thenone:line, exit 0; OAuth with no identity → exit 1 and empty stdout; unparsable JSON → exit 1.- A rewritten key-auth
/statusfixture, every value invented per.claude/rules/eval-case-transcripts.md, and amaskCellstest with no values. - Version bump and changelog fragment.
PRs 1 and 2 change skill bodies, so they carry do-not-merge until a valid before/after eval lands (hub rule R379/R381).
Done when
- The app-control PR merges, with drive evals for the hand-off, the unreadable target, a lone
none:, mixed sources and an extra line. - The testing PR merges, with the run-e2e eval in which a failed
values:source behind the hand-off keepse2e-summary.jsonout ofpublishable. - The harness-ops PR merges, and
node --test plugins/harness-ops/skills/control-claude-code/driver/driver.test.mjsexits 0 with theaccount.mjsand key-auth fixture cases. -
grep -n "^## Mask" .claude/skills/control-claude-code-plugins/SKILL.mdmatches on main. -
bash plugins/app-control/skills/map/scripts/check-map.test.shexits 0, including the hand-off fixture case.
The live CI capture that shows a published, masked screenshot reaching the judge is #11364's rows 1 and 8. It waits on PR_VERIFY_CLAUDE_API_KEY credit.
Out of scope
- Passing the PR's acceptance criteria to run-e2e in the capture prompt (the feat(harness-ops): verify PR acceptance criteria by driving Claude Code (screenshots, video) before merge #11364 grade, row 1, second gap).
Metadata
Metadata
Assignees
Labels
priority: mediumReal value, no hard deadline; normal backlog flow.Real value, no hard deadline; normal backlog flow.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.Refactors, migrations, contract changes; cross-cutting and hard to reverse.
Type
Fields
Work status
ready
Activity
kyle-sexton commentedon Nov 6, 2026
Claim: the App Driven PR Verify session is building this now. It is three PRs, one per plugin, as the Work section says: app-control and harness-ops in parallel, then testing. Other lanes, please leave it.
github-actions commentedon Nov 6, 2026
Proposed work class: work-class: structural
Basis: automated intake triage; the lanes App applied this class.
Size: Large
Complexity: Medium
Uncertainty: Known
Flags: none
Blocked by: none
Understood: the CI capture publishes almost no screenshots because the hub has no
## Maskhand-off and key auth yields no account values. The issue asks for a hub-to-control-skill Mask hand-off, anone:result forvalues:sources, andaccount.mjsprintingnone:for key auth. The work is three PRs, in app-control, testing and harness-ops.The design and done-when items are exact, so nothing is missing. I found no duplicate among the open issues. #11364 is the parent. The live CI capture check depends on credit and sits with #11364.
Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Nov 6, 2026
Not admitted to the issue lane yet: sub-issue #13759 is open.
melodic-automation-lanes commentedon Nov 6, 2026
Split at intake (owner Q93). This issue is Size Large, so its done-when is split into 3 sub-issues, each holding its task-list lines as written.
Automated split by the lanes App. Admission waits on this issue while a sub-issue is open; work-unblock closes it as completed once every sub-issue is closed as completed by a merge or a listed human and its done-when is covered.
fix(app-control): resolve the Mask hand-off target beside the hub tha…
kyle-sexton commentedon Nov 6, 2026
Re-scope after the owner's local-capture decision (#11364 issuecomment-6692967126) and the CI capture switch-off (PR 13814).
This tree still applies, and not only to CI. A local capture goes through the same drive mask post-check (
plugins/app-control/skills/drive/reference/evidence.md, "Mask post-check"), and the post-check marks every capturenot-checked, so unpublishable, when the hub has no## Mask. Without the hand-off, local screenshots cannot reach the evidence comment either.none:contract, with the hub's## Mask): needed for local capture. PR 13765 closes it; it is held for its before/after eval.account.mjsprintsnone:under key auth): closed by feat(harness-ops): print none: from account.mjs when no account is signed in #13762. It now serves only the CI bonus path.The only part that is CI-only is the key-auth
none:result. It costs nothing locally, whereaccount.mjsreturns the signed-in email and organization. Nothing here is moot, so nothing closes early. This parent closes when #13758 and #13759 close (R233).melodic-automation-lanes commentedon Nov 7, 2026
Every sub-issue of this split is closed as completed by a listed human or a merge (#13758, #13759, #13760), so the lanes App closes it as completed.