Skip to content

feat: apply external gate verdicts#474

Open
iamcxa wants to merge 4 commits into
mainfrom
iamcxa/status-apply-gate
Open

feat: apply external gate verdicts#474
iamcxa wants to merge 4 commits into
mainfrom
iamcxa/status-apply-gate

Conversation

@iamcxa

@iamcxa iamcxa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Motivation

Spacedock gates are increasingly decided outside the FO's immediate text loop: gate UI, chat approval recovery, handoff packets, and future harness integrations can all capture a human verdict before the workflow state is updated. Without a first-class apply seam, agents have to translate those verdicts into ad-hoc status --set mutations, which loses gate identity, bypasses stage semantics, and makes recovery paths harder to audit.

This PR gives Spacedock a small, guarded adoption point for externally captured gate decisions. Callers provide the gate id, entity ref, and verdict; Spacedock resolves the entity, verifies it is actually parked at a declared gate stage, applies the workflow's own approve/revise/reject routing rules, and records the gate decision separately from terminal completion verdicts. That keeps external gate surfaces useful without teaching each harness to mutate frontmatter by hand.

Architecture fit

This is a Spacedock-core seam, not a Helm-specific integration. In the pillar map terms, external surfaces such as a gate UI, chat recovery path, or future harness capture the call at the resolution station; spacedock status --apply-gate is the core ingress that turns that captured resolution into durable workflow record. The command intentionally accepts only generic workflow terms (gate id, entity ref, verdict) and then applies the workflow README's declared stage/gate semantics.

That keeps the five-pillar boundary clean: P2/Malleable UI can present evidence and capture the call without owning frontmatter mutation rules; P0/Spacedock core owns validation, stage movement, and the decision record; P3/Self-improvement can later read that record without depending on which UI or harness captured it.

Summary

  • Add spacedock status --apply-gate --gate <id> --entity <ref> --verdict approve|revise|reject for externally captured gate decisions.
  • Apply gate verdicts through the existing guarded runSet mutation path: approve advances to the next declared stage; revise/reject route to feedback-to when present; non-gate stages fail closed.
  • Record caller-supplied gate-id and gate-verdict as separate entity fields, and document the schema, command reference, and FO write skill surface.
  • Rebase onto latest origin/main and update local host-integration tests for current Codex/agentsview CLI output shapes.
  • Harden the CLI contract from review feedback: partial --gate/--entity/--verdict flags now require --apply-gate, action conflicts fail fast, and JSON emits gate_id instead of ambiguous gate.

Test Plan

  • go test ./internal/status -run ApplyGate -count=1
  • go test ./internal/status
  • go test ./internal/status -race
  • go test ./internal/cli -run 'NativeRunner|RunDefaultsToNativeRunner|status|Status' -count=1
  • go test ./internal/cli -run TestCodexPluginInstallIsHostNative -count=1
  • go test ./skills/integration -run TestSurveyCodexPresenceThroughSync -count=1
  • go test ./...
  • go test ./... -race

Review

  • agy review completed; material findings addressed:
    • trim feedback-to before lookup/write
    • reject --apply-gate combined with another action such as --read or --archive
  • Copilot review checked; material findings addressed or replied to:
    • reject partial gate flags without --apply-gate
    • emit gate_id in JSON output
    • keep mutation --quiet aligned with existing single-line machine-summary contract
  • CL review nit addressed:
    • clarify that gate-id is generated by the surface/harness that captures the decision, not by status --apply-gate
    • move apply-gate usage guidance out of fo-status-viewer and into fo-write-core
  • Claude review blocked locally by Claude session limit: You've hit your session limit · resets 4pm (Asia/Taipei)

@iamcxa iamcxa self-assigned this Jul 6, 2026
@iamcxa iamcxa requested a review from Copilot July 6, 2026 03:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an “external gate verdict apply” surface to the Go-native spacedock status runner so that externally captured gate decisions (approve/revise/reject) can be applied via the existing guarded mutation path, and records that decision in entity frontmatter (gate-id, gate-verdict) with accompanying docs/schema updates.

Changes:

  • Add status --apply-gate --gate <id> --entity <ref> --verdict approve|revise|reject argument parsing and dispatch routing.
  • Implement runApplyGate to validate the entity is currently at a gate: true stage, compute the target stage transition, and write status, gate-id, and gate-verdict via runSet.
  • Extend schema + docs + FO skill surfaces, and add focused unit tests for apply-gate behavior.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
skills/fo-write-core/SKILL.md Documents FO write authority including the new apply-gate mutation surface.
skills/fo-status-viewer/SKILL.md Extends the FO-facing status invocation docs to mention --apply-gate.
internal/status/parse.go Adds argument parsing for --apply-gate.
internal/status/native_runner.go Wires apply-gate parsing and dispatch, with incompatibility checks for some read/mutate flags.
internal/status/apply_gate.go Implements the apply-gate mutation and output/JSON emission.
internal/status/apply_gate_test.go Adds tests covering approve advance, reject routing to feedback-to, and refusal on non-gate stages.
docs/site/reference/frontmatter-contract.md Documents gate-id / gate-verdict as distinct from terminal verdict.
docs/site/reference/command-reference.md Adds --apply-gate to the command reference entry for spacedock status.
docs/schema/entity.mdschema.yml Adds gate-id and gate-verdict to the entity schema’s optional canonical fields.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread skills/fo-write-core/SKILL.md Outdated
Comment thread internal/status/parse.go
Comment on lines +268 to +272
func parseApplyGateArgs(args []string) (*applyGateRequest, error) {
if !contains(args, "--apply-gate") {
return nil, nil
}
gateID, err := parseSingleArg(args, "--gate", "gate-id")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in da0b09c. --gate, --entity, and --verdict now fail fast when used without --apply-gate, with coverage in TestApplyGateRejectsGateFlagsWithoutApplyGate so partial invocations cannot fall through to read output.

Comment thread internal/status/native_runner.go
Comment thread internal/status/apply_gate.go
Comment on lines +69 to +75
case quiet:
fmt.Fprintf(stdout, "apply-gate slug=%s gate=%s verdict=%s status=%s->%s\n",
resolved.slug, req.gateID, req.verdict, currentStatus, nextStatus)
default:
fmt.Fprintf(stdout, "apply-gate slug=%s gate=%s verdict=%s status=%s->%s\n",
resolved.slug, req.gateID, req.verdict, currentStatus, nextStatus)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing this one. In this repo, mutation --quiet means a single machine-readable success line, not silence; json_quiet_test.go already pins that behavior for --set --quiet and --archive --quiet. Keeping apply-gate aligned with that mutation contract is intentional.

@iamcxa iamcxa force-pushed the iamcxa/status-apply-gate branch from 7c97341 to 5dee228 Compare July 7, 2026 05:43
@iamcxa iamcxa deployed to CI-E2E July 7, 2026 05:44 — with GitHub Actions Active
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Journey cost delta

Scenario Runtime Model Turns Δ Cache Read Δ Cache Creation Δ Tokens Δ (total) Cost Δ (USD) Duration Δ (ms) Baseline
feedback-3-cycle-escalation claude claude-opus-4-8 +1 +61848 +2579 +64989 +0.0610 +13662 latest published
feedback-3-cycle-escalation claude sonnet +1 +76365 -431 +80005 +0.0246 -18067 latest published
filing claude claude-opus-4-8 -3 -94457 +631 -94154 -0.0488 +2835 latest published
filing claude sonnet +2 +111661 +3341 +120756 +0.0763 -4822 latest published
gate-guardrail claude claude-opus-4-8 -2 -60568 +584 -60249 -0.0332 -1189 latest published
gate-guardrail claude sonnet +0 +22428 +2328 +30691 +0.0468 +4605 latest published
merge-hook-guardrail claude claude-opus-4-8 +0 +5721 +794 +6236 +0.0034 -3206 latest published
merge-hook-guardrail claude sonnet +1 +42408 +668 +47993 +0.0330 +6815 latest published
rejection-flow claude claude-opus-4-8 -9 -891932 +15118 -892252 -0.7339 -200350 latest published
rejection-flow claude sonnet +12 -2245039 -54463 -2311442 +0.6451 +8775 latest published
self-evidence-merge-triage claude claude-opus-4-8 n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) none (new observation)
self-evidence-merge-triage claude sonnet n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) none (new observation)
shallow-boot claude claude-opus-4-8 -2 -47949 +2216 -45281 +0.0012 +8441 latest published
shallow-boot claude sonnet +1 +64514 +2276 +72660 +0.0538 -9628 latest published
shallow-boot-window claude claude-opus-4-8 -2 +563 +1766 +2330 +0.0000 +0 latest published
shallow-boot-window claude sonnet +1 +2133 +256 +2388 +0.0000 +0 latest published
smallest-sufficient-mechanism claude claude-opus-4-8 n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) none (new observation)
smallest-sufficient-mechanism claude sonnet n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) n/a (new) none (new observation)

Sign up for free to 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.

2 participants