Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ ambient local state. The repo is a private pnpm workspace shell (`@agentic-workf
or makes a public SDK/provider/MCP stability promise. The real
execution-host path is now selectable on macOS and proves an honest `weak` `process-group` posture
at compose time; the current real GitHub Forge/GitHub Issues path includes blocked-PR surfacing,
held-merge replay safety, landing-path redaction, and origin-bearing work-source provenance.
held-merge replay safety, landing-path redaction, and origin-bearing work-source provenance —
held-merge and commit-status legs are unit-proven, with real-effect evidence pending a rerun.
Strong no-phone-home evidence remains future work. EVRUN-partial is recorded; P11 also records a
blocked EVRUN-full capture attempt where the narrow Codex app-server and real-host smokes passed
outside the Codex sandbox, but the combined real GitHub path could not run without sandbox
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ The current CLI surface is `jig setup`, `jig preview`, `jig run`, `jig inspect`,
`jig export`.
The private MCP surface lives in `@agentic-workflow-kit/jig-mcp` and exposes the settled
operator-control verbs as source-checkout tool calls; it is not published and carries no stability
promise.
promise. `jig resume` remains a CLI/SDK recovery operation rather than an MCP operator-control
verb.
Launch binds the track policy plus any configured work profile and repo-policy floors, snapshots
them into the run record, and reconstructs the effective floor-merged policy basis on resume. The
fixture-backed commands below are the supported local way to exercise the repo from a fresh
checkout. The package split is now implementation fact inside this private workspace; Codex
app-server transport work remains future implementation, not a shipped public API, while the real
execution-host path now exercises a local macOS process-group probe and reports an honest `weak`
containment posture.
checkout. The package split and the private Codex app-server transport are now implementation fact
inside this private workspace; neither creates a shipped public API. The real execution-host path
now exercises a local macOS process-group probe and reports an honest `weak` containment posture.

Current evidence proves a scoped real-provider path with a scripted agent leg
(`EVRUN-partial`). P11 also captured an EVRUN-full attempt: the narrow Codex app-server and
real-host smokes pass outside the Codex sandbox, but the combined real GitHub path could not run
without sandbox credentials and an integrity key. The current real GitHub Forge/GitHub Issues path
also carries blocked-PR surfacing, held-merge replay safety, landing-path redaction, and
per-candidate origin-bearing provenance. `EVRUN-full`, remote execution, public package
publication, and a full Codex-driven agent leg remain future work; strong/no-phone-home
execution-host evidence remains in that later proof step.
per-candidate origin-bearing provenance — held-merge and commit-status legs are unit-proven, with
real-effect evidence pending a rerun. `EVRUN-full`, remote execution, public package publication,
and a full Codex-driven agent leg remain future work; strong/no-phone-home execution-host evidence
remains in that later proof step.

## Quick Start

Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ scoped to **Jig the execution engine**.

Current implementation truth includes a private setup command that emits validated owner
configuration, plus a private real GitHub Forge/GitHub Issues path with blocked-PR surfacing,
held-merge replay safety, landing-path redaction, and origin-bearing candidate provenance;
held-merge replay safety, landing-path redaction, and origin-bearing candidate provenance —
held-merge and commit-status legs are unit-proven, with real-effect evidence pending a rerun;
phase-table PR-number status updates still live in delivery docs.

Preserve active design history in place:
Expand Down
123 changes: 66 additions & 57 deletions docs/delivery/target-state-implementation/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Phase 11 - EVRUN-full evidence"
status: "pr #70blocked evidence record"
status: "merged (#70; blocked evidence)"
---

# Phase 11 - EVRUN-full evidence
Expand Down Expand Up @@ -92,12 +92,22 @@ gated on this evidence path. This phase is the proof step: it converts "implemen

## Acceptance Criteria

These criteria remain the bar for closing this phase. The per-AC disposition markers below
record honest current state as of the #70 merge; they do not lower the bar.

1. A committed, dated EVRUN-full evidence record (or record set) exists under
`docs/design/evidence/`, indexed, convention-complete (versions, hashes, Limitations,
redaction statement, ID citations).
**Disposition at #70 merge: not met.** What was delivered instead is the blocked-attempt
record `docs/design/evidence/2026-07-06-evrun-full-capture-attempt.md`. A full capture
re-attempt is still owed before this criterion is met.
2. The record demonstrates: real Codex editing through the owned app-server transport; real,
exercised confinement with honest strength; an adversarial no-phone-home observation; and
multi-run idempotency against a real landed effect.
**Disposition at #70 merge: not met.** The combined EVRUN-full path could not run because
the sandbox GitHub and integrity prerequisites were absent; the blocked-attempt record
`docs/design/evidence/2026-07-06-evrun-full-capture-attempt.md` documents what was observed
instead. A full capture re-attempt remains required before this criterion is met.
3. Hosted/remote operation and Windows behavior are explicitly restated as out of scope in the
Limitations section.
4. README/AGENTS/product status lines about EVRUN reflect the new boundary — no claim exceeds
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Phase 12 - MCP driving adapter"
status: "pr #71"
status: "merged (#71)"
---

# Phase 12 - MCP driving adapter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Phase 13 - Contract v0 freeze readiness"
status: planned
status: blocked
---

# Phase 13 - Contract v0 freeze readiness
Expand Down Expand Up @@ -76,8 +76,8 @@ consumer, which is why the owner decides and this phase only prepares.
[ADR 0026](../../../design/decisions/0026-conformance-self-report-only.md) (verdict
vocabulary constraints)
- P11's evidence records; the golden files under `tests/fixtures/m5b-local-mvp/`
- Source of truth for shipped shapes: `src/plan-validator.ts`, `src/records.ts`,
`src/projection.ts` (post-P02 package locations)
- Source of truth for shipped shapes: `packages/jig-sdk/src/plan-validator.ts`,
`packages/jig-sdk/src/records.ts`, `packages/jig-sdk/src/projection.ts`

## Dependencies

Expand Down
51 changes: 40 additions & 11 deletions docs/delivery/target-state-implementation/verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,27 @@ Gate integrity rules (from [`AGENTS.md`](../../../AGENTS.md)):

- No skipped steps, no threshold adjustments, no widened exclusion lists. Coverage stays
enforced at 90% (aim 95%) across whatever package layout exists after P02.
- **Coverage headroom.** A PR may merge only if its gate run reports branch coverage at or above
90.5%. The enforced floor in `vitest.config.ts` stays 90 — the 0.5-point headroom absorbs
run-to-run coverage jitter so that a green PR cannot produce a red main.
- After P02 the gate additionally enforces the ADR 0027 dependency matrix (see
[package boundary checks](#package-boundary-checks)); later phases inherit that check.
- A phase that must change gate mechanics (for example, P02 re-wiring `pnpm check` to fan out
across workspace packages) changes the mechanics without reducing what is checked, and its PR
review verifies exactly that.

## Review gate

A PR merges only after the automatic hosted review has posted and all of its threads are
resolved. Merging ahead of the review is a recorded escalation in the PR, never silent (incident
class: `#68` merged three minutes before its review posted).

## Post-merge watch

After each squash-merge, the merger watches the main push `check` run to conclusion. A red main
run halts further merges until main is green again (incident class: three consecutive red main
runs went unnoticed).

## Test lanes

The four Vitest lanes in `vitest.config.ts` carry different proof and must not blur:
Expand Down Expand Up @@ -146,8 +161,14 @@ From P02 onward:
- Each phase PR flips its own phase-table row and phase-doc frontmatter status to merged with
its own PR number — no follow-up PRs for status. Since the number does not exist until the PR
is opened: open the PR first, then push a status commit citing the exact number to the same
branch before requesting review, so the squash-merge lands work and status together. The
track front page must never claim less progress than `main`.
branch before requesting review, so the squash-merge lands work and status together.
- **Status-flip rule.** The status commit writes `merged (#N)` _before_ the merge happens, and
this is the sanctioned convention: the squash-merge lands the work and the status atomically in
one commit. Writing an interim status such as `implemented (#N)` or `PR #N` and relying on a
later PR to flip it to `merged` is a rule violation, not a lighter-weight variant — it is the
observed daisy-chain failure mode where the tail row goes stale (the last phase never gets its
follow-up flip and the track front page under-reports `main`). The track front page must never
claim less progress than `main`.

## Reviewer inspection axes

Expand All @@ -169,22 +190,30 @@ The owning sections above remain normative — this list restates them for a sin
pass and is not itself mechanically enforced.

1. Full gate green locally, with the output shown as evidence, not asserted ([The gate](#the-gate)).
2. Goldens are byte-identical, or the change is an owned, declared records-contract change
2. The gate run's reported branch coverage is at or above 90.5%, the enforced-floor headroom
([The gate](#the-gate)).
3. Goldens are byte-identical, or the change is an owned, declared records-contract change
([Golden-record discipline](#golden-record-discipline)).
3. For real-provider phases (P03, P04, P05, P11): a smoke transcript is in the PR body or a
4. For real-provider phases (P03, P04, P05, P11): a smoke transcript is in the PR body or a
committed evidence record; a skipped run is a recorded escalation, not a silent "not run"
([Evidence records and the EVRUN gates](#evidence-records-and-the-evrun-gates)).
4. Smoke and evidence assertions are not satisfiable by a fail-closed refusal
5. Smoke and evidence assertions are not satisfiable by a fail-closed refusal
([Conformance and testkit posture](#conformance-and-testkit-posture)).
5. Any export-map widening names the consumer that needs it
6. Any export-map widening names the consumer that needs it
([Package boundary checks](#package-boundary-checks)).
6. The status flip lands in the same PR: open the PR first, then push a status commit citing
the exact PR number to the phase-table row and the phase-doc frontmatter
7. The status flip lands in the same PR: open the PR first, then push a status commit citing
the exact PR number to the phase-table row and the phase-doc frontmatter, writing `merged
(#N)` directly — never an interim `implemented (#N)`/`PR #N` left for a later PR to flip
([Docs checks](#docs-checks)).
7. Status-bearing docs (root `README.md`, `AGENTS.md`, `docs/README.md`, package descriptions,
8. Status-bearing docs (root `README.md`, `AGENTS.md`, `docs/README.md`, package descriptions,
`skills/README.md` CLI surface list) are updated in the same PR ([Docs checks](#docs-checks)).
8. All review threads are resolved, the PR is squash-merged, and the worktree is cleaned up
after merge (`AGENTS.md`).
9. The automatic hosted review has posted and all review threads (including its own) are
resolved before merge; merging ahead of the review is a recorded escalation, never silent
([Review gate](#review-gate)).
10. The PR is squash-merged and the worktree is cleaned up after merge (`AGENTS.md`).
11. After the squash-merge, the merger watches the main push `check` run to conclusion; a red
main run halts further merges until main is green again
([Post-merge watch](#post-merge-watch)).

## Definition of delivered

Expand Down
23 changes: 15 additions & 8 deletions docs/design/contracts/driving.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ that action. The edge holds no run logic and imports no provider contracts — i
## Owns

- The inbound driving interface jig is operated through.
- The deliberate driving actions: start, preview, watch, inspect, ask-why, decide, stop, export.
- The deliberate driving actions: start, preview, watch, inspect, ask-why, notice-ack,
notice-snooze, decide, stop, export.
- The one-command / one-control-plane-call / SDK-owned-records invariant.
- Keeping the edge free of run logic — orchestration, eligibility, and authorization stay in
core.
Expand Down Expand Up @@ -130,9 +131,13 @@ shipped public package promise.

## Driving actions at current altitude

The driving action set is: start, preview, watch, inspect, ask-why, decide, stop, and export. This
section stays at design altitude only. It names the deliberate actions the port carries without
freezing exact method signatures or adapter-specific representation.
The driving action set is: start, preview, watch, inspect, ask-why, notice acknowledge, notice
snooze, decide, stop, and export. [ADR 0030](../decisions/0030-observation-surface-placement.md)
places notice acknowledge and snooze as owner notice records on this same operator-control port.
ADR 0032 places export on the same port, and ADR 0033 keeps `resume` on the SDK recovery surface
rather than on the operator-control port or MCP adapter. This section stays at design altitude
only. It names the deliberate actions the port carries without freezing exact method signatures or
adapter-specific representation.

## Invocation into cited core surfaces

Expand Down Expand Up @@ -198,12 +203,14 @@ available invariant number is `INV-019`.

## Reconciles to

- `docs/product/jig.md` — "Driving a run" (start, preview, watch, inspect, ask-why, decide, stop;
"You run Jig from a terminal, drive it as a tool from your own agent, or embed it in your own
software"); "Operator-initiated" (see "What Jig isn't (yet)"); "Product boundaries" for no public
package/export/stability promise today.
- `docs/product/jig.md` — "Driving a run" (start, preview, watch, inspect, ask-why, acknowledge or
snooze a notice, decide, stop; "You run Jig from a terminal, drive it as a tool from your own
agent, or embed it in your own software"); "Operator-initiated" (see "What Jig isn't (yet)");
"Product boundaries" for no public package/export/stability promise today.
- ADR 0032 — export is an operator-control action that writes a local audit artifact and records
export audit events outside finalized run logs.
- ADR 0033 — `resume` is a recovery-surface operation and MCP lives in the private `jig-mcp`
adapter package; neither changes the operator-control port verb set.
- ADR 0027 — the `jig-sdk` package boundary is distribution/dependency structure, while this document's
SDK adapter remains a thin driving realization.
- `SEE-1` — full run visibility, surfaced through inspect/ask-why on the operator boundary.
Expand Down
72 changes: 71 additions & 1 deletion scripts/check-delivery-foundation.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readFileSync } from 'node:fs';
import { readdirSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';

const fixtureReadme = resolve('tests/fixtures/m5b-local-mvp/README.md');
Expand Down Expand Up @@ -32,3 +32,73 @@ if (missing.length > 0) {
}

console.log('Delivery foundation fixture conventions are present.');

// Cross-check that every target-state-implementation phase doc's frontmatter status matches
// its phase-table row status in the track README, so the two status surfaces cannot drift
// silently (a phase doc updated without its table row, or vice versa).
const trackReadmePath = resolve('docs/delivery/target-state-implementation/README.md');
const trackReadmeText = readFileSync(trackReadmePath, 'utf8');
const phaseDocsDirectory = resolve('docs/delivery/target-state-implementation/phases');

function normalizeStatus(status) {
return status.trim().toLowerCase().replace(/\s+/g, ' ');
}

const phaseTableRowPattern = /^\|\s*(P\d+)\s*\|\s*\[.*?\]\((\.\/phases\/[^)]+)\)\s*\|\s*(.*?)\s*\|/gm;
const tableStatusByPhaseFile = new Map();
for (const match of trackReadmeText.matchAll(phaseTableRowPattern)) {
const [, phaseId, relativePhasePath, status] = match;
const phaseDocPath = resolve('docs/delivery/target-state-implementation', relativePhasePath);
tableStatusByPhaseFile.set(phaseDocPath, { phaseId, status: normalizeStatus(status) });
}

if (tableStatusByPhaseFile.size === 0) {
console.error(`${trackReadmePath} phase table did not match the expected row pattern.`);
process.exit(1);
}

const frontmatterPattern = /^---\n([\s\S]*?)\n---/;
const frontmatterStatusPattern = /^status:\s*"?(.*?)"?\s*$/m;
const statusMismatches = [];
const expectedPhaseDocPaths = new Set(
readdirSync(phaseDocsDirectory)
.filter((entry) => /^\d{2}-.*\.md$/.test(entry))
.map((entry) => resolve(phaseDocsDirectory, entry)),
);

for (const [phaseDocPath, { phaseId, status: tableStatus }] of tableStatusByPhaseFile) {
const phaseDocText = readFileSync(phaseDocPath, 'utf8');
const frontmatterBlock = phaseDocText.match(frontmatterPattern)?.[1];
if (!frontmatterBlock) {
statusMismatches.push(`${phaseId} (${phaseDocPath}): no frontmatter block found`);
continue;
}
const frontmatterMatch = frontmatterBlock.match(frontmatterStatusPattern);
if (!frontmatterMatch) {
statusMismatches.push(`${phaseId} (${phaseDocPath}): no frontmatter status found`);
continue;
}
const docStatus = normalizeStatus(frontmatterMatch[1]);
if (docStatus !== tableStatus) {
statusMismatches.push(
`${phaseId} (${phaseDocPath}): frontmatter status "${docStatus}" does not match ` +
`phase-table row status "${tableStatus}"`,
);
}
}

for (const phaseDocPath of expectedPhaseDocPaths) {
if (!tableStatusByPhaseFile.has(phaseDocPath)) {
statusMismatches.push(`${phaseDocPath}: phase doc is not represented in the track README table`);
}
}

if (statusMismatches.length > 0) {
console.error('Phase status drift between the track README table and phase-doc frontmatter:');
for (const mismatch of statusMismatches) {
console.error(`- ${mismatch}`);
}
process.exit(1);
}

console.log('Phase-table and phase-doc frontmatter statuses agree.');