gcf-harness-aif-ext 0.9.7 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +124 -122
  2. package/extension.json +1 -1
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,122 +1,124 @@
1
- # gcf-harness-aif-ext
2
-
3
- Claude-Code-specific orchestration for the [Game Context Framework](../gcf-aif-ext). Optional: GCF works without it, by hand.
4
-
5
- > **Claude Code only.** Codex and the other AI Factory runtimes are not supported: the harness is built on Claude Code
6
- > dynamic workflows and `PreToolUse` hooks, which they do not have. AI Factory still copies the `gcf-run` skills into
7
- > every runtime the project is configured for, where they do not work — on a project without Claude Code, do not
8
- > install the harness. GCF itself keeps working on any runtime.
9
-
10
- The harness turns policy-as-text into an executable pipeline. The game's state is on disk in `gcf/` and git, so a run killed at any point restarts and reaches the same state. The runs' own state is in `.gcf-session/`: the agent sessions a rerun resumes, the item worktrees with their uncommitted work, locks and logs. Losing it never breaks the game's model, but it loses those resumes, that work and the diagnosis: delete a single stale file, never the folder.
11
-
12
- ## Requirements
13
-
14
- - [`gcf-aif-ext`](../gcf-aif-ext) `^0.7.14` installed (the peer range of `package.json`), with a `gcf/` tree in the project — declared as a peer dependency, and `gcf-harness init` refuses when the `gcf` command is not registered
15
- - Claude Code 2.1.270+ (hooks, dynamic workflows) — the only supported runtime
16
- - AI Factory 2.x, Node.js ≥ 22.14
17
-
18
- ## Install
19
-
20
- The shortest way is from the core: `ai-factory gcf init` asks whether to install the harness too, and on yes runs both steps below. It asks only in a terminal and only when the project has the Claude Code agent; `gcf init --harness` installs it without asking, `--no-harness` skips the question.
21
-
22
- By hand, into a project that already has the core, from npm or a local checkout:
23
-
24
- ```bash
25
- ai-factory extension add gcf-aif-ext # the core, if not yet installed
26
- ai-factory extension add gcf-harness-aif-ext # npm
27
- # ai-factory extension add ../GCF/packages/gcf-harness-aif-ext # local checkout
28
- ```
29
-
30
- This installs the `gcf-run` and `gcf-run-ingest` skills and registers the `gcf-harness` command. Then initialize the harness in the project — like `gcf init`, once per project:
31
-
32
- ```bash
33
- ai-factory gcf-harness init # per project: .claude/settings.json + .gitignore
34
- ```
35
-
36
- It is **per project**, not global — run it again in every game repository: it adds the readset-guard and implement-guard entries to the project's `.claude/settings.json` (never `~/.claude`) and `.gcf-session/` to `.gitignore`. It also allows what an unattended `claude -p` run needs at least — `Edit`, `Write`, `Bash(git *)`, `Bash(ai-factory *)`, and the same two as `PowerShell(…)` rules, the tool the agent runs commands with on Windows — because print mode cannot ask and denies the rest; add your engine's tools yourself (for example `mcp__<editor-server>` for an editor driven over MCP). Commit `.claude/settings.json`: the rules apply to every Claude session in the project. It is idempotent — a re-run after moving or cloning the project repoints the hook at the new path — refuses when the `gcf` command is not registered, and refuses to rewrite a `settings.json` it cannot parse. It is a separate step for the same reason as `gcf hooks-install`: an AI Factory manifest cannot install Claude Code hooks.
37
-
38
- ## Upgrade
39
-
40
- ```bash
41
- ai-factory extension update gcf-harness-aif-ext
42
- ```
43
-
44
- Updating keeps the hook entry valid — it points into the extension's install directory, which an update refreshes in place.
45
-
46
- 0.5.0 drives work items (`gcf/work/<id>.md`, schema 3) instead of cards and requires `gcf-aif-ext` 0.4.0 — update both together; against an older core the gate refuses with `gcf-aif-ext >= 0.4.0 is required`. A project still holding schema 2 cards in `gcf/cards/` re-creates them first (see the core's "Upgrading from 0.3.x"). What changes for you: `/gcf-run` takes ids of items in `ready`; it no longer stops at `built` but ends each item with `submit`, `close` or `block`; the plan is improved in passes until it converges; the WIP cap counts only items that end waiting for a verdict.
47
-
48
- 0.5.1 is a fix release. During a run, `gcf/config.yml` is always readable, and a Grep inside `gcf/` reads only readset files. An import breaks a `depends:` cycle the pair checks closed and asks a D1 about it. It cuts a section longer than a segment at paragraphs, and lens and pair prompts carry a window around the quote. `/gcf-run` checks the plan against each pillar's invariant and asks each pillar's review question over the diff. Use it with core 0.4.1, which brings the parent feature into the readset.
49
-
50
- 0.9.6 (with core 0.7.14, now the peer range): `/gcf-run-ingest` hands its workflow the sections with their bodies, gets the same delta again after a failed run and ends the import with `gcf anchor --done`; it takes the text of a changed section as `/gcf-ingest` does, and adds resources, entities and measurable constraints by the sequential pass. The workflow marks the GDD as data in every prompt and asks a lens's D2 as a D1. `/gcf-run` reads only `INDEX.md` and `config.yml` beyond the readset, hands fresh subagents the context's graveyard and D2 lines, counts a re-verify after review against `dod_attempts`, files a D1 for a design question on main, never widens the readset by a false `depends:`, and runs in Claude Code only.
51
-
52
- 0.9.5: `gcf-harness metrics` also sums the cost per item over all its runs and per day and week (`items`, `by_day`, `by_week` in `--json`, a `weeks:` line in the text); `gcf-board` 0.2.18 shows them in its Metrics tab. A resumed session's cost no longer counts twice: `claude` reports a resumed session's whole dollar total, so the lessons turn and a rerun after a limit or a cut now count from what the session had already spent (it is kept in `<id>.agent.json`); before, a lessons turn added its session's cost again. The `done in …` line of the log still shows claude's own figure. A core refusal reads as its whole message: a failed `git worktree add` names its cause, not only git's first line.
53
-
54
- 0.9.4 keeps run metrics (Harness-PRD §11) and adds `ai-factory gcf-harness metrics`. Use it with core 0.7.13, which logs the plan checks and the DoD attempts, and refuses `close` and `submit` without a green `gcf verify` of the code as it is. `/gcf-run` runs the verify again after a review fix; implement-guard refuses `gcf close` or `gcf submit` with `--unverified` in a `/gcf-run` session, since a move past the DoD gate is the human's call. A main-mode item whose move went past it anyway (the commit says `(unverified: …)`) reads `— moved without a green gcf verify` on its report line, and `gcf-harness metrics` counts such moves.
55
-
56
- 0.9.2 holds `/gcf-run` to aif-implement. Run `ai-factory gcf-harness init` again after the update: it registers the new hook.
57
- - The implement guard: in a session that runs `/gcf-run`, a write to a code file is denied until the session invokes the aif-implement skill (gcf-run step 13), and so is a plan tick, which only aif-implement sets. Planning stays free: `gcf/`, `.ai-factory/`, `.gcf-session/` and any markdown file. After aif-implement every write is free, the fixes of a red DoD and of the review included. It works in the harness's runs and in an interactive `/gcf-run` alike, and touches no other session.
58
- - `/gcf-run` converges a plan when an improve pass finds nothing blocking: a wrong or missing behavior or task, a broken pillar invariant, a rule conflict, a task no check can prove. Polish (wording, splitting tasks, order) is applied, but no longer keeps the loop going. Before, a pass that changed any task asked for one more, and a fresh reviewer almost always changes something. The report row per pass gives the blocking and polish counts.
59
- - `/gcf-run` answers aif-plan's own questions (tests, logging, docs) itself, from the item, its DoD and the project's rules.
60
- - The run report marks an item whose session wrote code without aif-implement: `— code written outside aif-implement` on its line, `process` in `--json` and in its kept record. It reads the session's own events, its subagents' included, so it also covers a project without the guard registered. A write through Bash is seen by neither: the review of the diff is the check there.
61
- - Lessons (with core 0.7.10): after each agent session the run asks the same session, resumed, what got in its way - tools, rules, the framework, the project template - with the questions of `ai-factory gcf lessons prompt`. Its answers go to the inbox on main as lessons (`gcf lessons add`), and the board shows them on the card, in the drawer and in the inbox. The run passes `--no-lessons` to `/gcf-run`, so the agent carries no lessons instruction while it works. The turn follows a result, a handoff (before the fresh session), a timeout or an error; not a usage limit or a stop, and only for a `claude` agent with a session id. Another agent asks its lessons itself at the end of a run on main; in a worktree it records none. It takes up to 10 minutes; its cost goes on the item, and the report line says `, N lessons`. A failed lessons turn is logged and changes nothing else. A project that turns lessons off, or a core before 0.7.10, gets no turn and no flag.
62
-
63
- 0.9.1 is a fix release:
64
- - A stopped session reads as `no result (stopped)`, and its kept record as `ended: stopped`: before, the kill's exit code (`agent exit 1` on Windows).
65
- - `gcf-harness stop <id>` never kills the run: a stop before the item's session starts (or between two sessions of a handoff) leaves `.gcf-session/runs/<id>.stop`, and that session is stopped as it starts. Before, a stop then killed the whole run with the other items of its batch. A run hung before its first session (in its worktree setup) is not stopped. On main, a stop marks the item too once the run has reached it. Known limit: a stop in the moment between a worktree run's claim of the item and its clearing of an old mark is lost.
66
- - A stop that comes while the session starts no longer misses it.
67
-
68
- 0.9.0, to update together with core 0.7.6:
69
- - The harness's own agent runs with `--permission-mode bypassPermissions`: it may do everything but the project's deny rules, which hold in every mode. The rules come from the deny groups of `gcf/config.yml` (`ai-factory gcf permissions`, or the board): git history and uncommitted work, recursive delete, publishing, the human's GCF moves and the guards are on by default; secrets, changes outside the project and killing processes are off. `git push` is allowed. Deny rules match the command as written: they catch accidents, not a rewording, and `/gcf-run` makes a refused command a stop with `needs permission: <command>`.
70
- - A run loads the project's settings and MCP servers only (`--setting-sources project,local --strict-mcp-config --mcp-config .mcp.json`): the operator's plugins, hooks and claude.ai connectors stay out. So does `env` or `apiKeyHelper` in `~/.claude/settings.json`: an operator who logs in through them, not `claude login`, names the agent with `--agent`. The deny rules and the handoff guard come in `.gcf-session/runs/agent-settings.json` (`--settings`), so a worktree gets them without a commit.
71
- - Context handoff: past `context_handoff_pct` (60 by default) of the window, or at a compaction, the run flags the session; the handoff guard then denies every call of the main agent but the plan's read and edit with the instruction to write `## Handoff` into the plan and end. The run starts a fresh session with `/gcf-run <id> --handoff`, which goes on from the plan: the ticked tasks stay done. A session that works on past its flag is stopped; after 3 handoffs in a row the item is blocked with `context handoff limit`. The window is `context_window`, else the one a result of the same model reported (`.gcf-session/runs/windows.json`); with neither, the first session of a model runs without a handoff and says so. The sessions of an item share one timeout, and their costs add up; `--json` gives `handoffs`.
72
- - `auto_compact_pct` sets the agent's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`, at least 15 points above the handoff share.
73
- - The readset-guard reads the manifest of the directory the session started in (`CLAUDE_PROJECT_DIR`): an agent's `cd` no longer lifts the readset.
74
- - `/gcf-run` writes a plan task's code through aif-implement, so the plan ticks show the item's progress, and answers aif-implement's questions itself: no commit, stash or merge.
75
-
76
- 0.8.0, to update together with core 0.7.0:
77
- - `run_mode: main` in `gcf/config.yml` (or `run --mode main`): items run one after another in the main checkout, for an agent that works through an editor bound to the project folder. The item carries the core's session mark (`gcf claim`), not a run lock, so the agent records its own move; one run works the checkout at a time (`.gcf-session/runs/.main-run.lock`).
78
- - `gcf-harness next [N] --json`: the ready items that can run together now, by priority; each is taken while the batch with it passes the gate.
79
- - `gcf-harness stop <id>`: stops the session that works the item (its run lock names it); the run records no result for it and goes on with the rest. The item stays ready and its work is kept. Known limit: the session is killed at once, so a `gcf` move it was in the middle of may leave `.gcf-session/main.lock` behind (taken over once its pid is gone).
80
- - A run on main refreshes its item's mark every 5 minutes, and the readset-guard hook refreshes live marks on each read: a long build without a gcf command does not expire it.
81
- - `run` refuses an id that is not a slug before it names a lock file or builds the agent's command line.
82
- - The gate lets a session through for the item its own run marked (`GCF_RUN_ITEM`); `/gcf-run` outside a worktree claims each item after its gate and releases one it leaves without a move.
83
-
84
- 0.7.0, to update together with core 0.6.0: an item's `model:` and `effort:` (`gcf item new --model <m> --effort <e>`) go to its agent as `--model <m> --effort <e>`, read from `gcf board --json`; a value that is not one plain word fails that item and starts no session. `--timeout <minutes>` (120 by default) stops a session that runs longer, with every process it started; its item stays ready, and its run lock is freed. The gate counts the items other runs drive now: their places under the WIP limit, and their systems — a board starts one run per click. Requires `gcf-aif-ext` 0.6.
85
-
86
- 0.6.1 is a fix release, to update together with core 0.5.3. The run lock `.gcf-session/runs/<id>.lock` is created exclusively, and a lock left by a dead run is taken over; while it is live, the gate refuses the item to another run and the core refuses any move on it, `/gcf-run` on main included. A session whose log cannot open ends as an error and releases its claim.
87
-
88
- 0.6.0 adds `ai-factory gcf-harness run` (a batch at once, a worktree and an agent session per item, then the integrator) and the `--worktree` mode of `/gcf-run`, whose session ritual now integrates the verified branches a dead run left. It requires `gcf-aif-ext` 0.5.0 (`gcf worktree`, `gcf integrate`, `gcf verify`) — update both together and run `ai-factory gcf init`. The DoD of `/gcf-run` is `ai-factory gcf verify <id>`, and the item's `live:` delta is written before it.
89
-
90
- 0.4.1 is a patch release. `/gcf-run` now commits the implementation first, then flips the card to `built` in a second commit, with `built_at` set to the implementation commit's hash. Update the core to 0.3.1 together with the harness: without it, an audit run before a verdict makes the pre-commit gate refuse that verdict.
91
-
92
- To remove the extension:
93
-
94
- ```bash
95
- ai-factory extension remove gcf-harness-aif-ext
96
- ```
97
-
98
- Removal does not touch `.claude/settings.json`: delete the entries whose command ends in `# gcf-readset-guard` or `# gcf-implement-guard` (under `PreToolUse` and `UserPromptSubmit`) by hand, or the tools they match will report a hook error.
99
-
100
- ## What it adds
101
-
102
- **`/gcf-run <item-id…>`** — drives work items through plan, implementation and DoD, with every gate checked *before* the tokens are spent: the audit ritual, the gate below, the context budget. The plan is written by `aif-plan`, then improved in passes, each by a fresh subagent that reads only the plan and the readset and records every default it picks; `ai-factory gcf plan check <id>` runs after each pass, and a pass with no blocking finding (a wrong or missing behavior or task, a broken pillar invariant, a rule conflict, an unprovable task) ends the loop. A blocking finding left after `plan_passes` passes (3 by default), or a question only the human can answer (a save format, a public API, a new dependency, a pillar conflict), blocks the item before any code is written. The DoD is `ai-factory gcf verify <id>` — the gate's checks, the item's `live:` delta, and the project's `dod.build` and `dod.test` commands from `gcf/config.yml` — plus a review by a fresh subagent, up to `dod_attempts` attempts. Every item ends in a state the core records: `gcf submit` (gate `verdict` or `decision` — waits for the human), `gcf close` (gate `auto` — done, or a soft unit closed as `unplayed`) or `gcf block` with the reason. The verdict and the decision belong to the human: the pipeline stops at `submit` and prints the playtest list.
103
-
104
- **`ai-factory gcf-harness gate <item-id…>`** — the `/gcf-run` gate as code. It reads one `gcf audit --json` report and exits 1 with a one-line reason when the items may not go: a core older than 0.4.0, a `schema:` other than 1 in `gcf/config.yml`, an id with no work item, a feature (run its children; the feature closes when they are finished), an item that is not `ready`, an unplayed dependency, no WIP room for the batch (items awaiting a verdict + the batch's `gate: verdict` items over `wip_built_limit`), or two items of the batch touching the same system unless both say `parallel: ok`. The tune limit is not a gate rule: `verdict tune` itself refuses at the limit, and an item tuned up to it still gets its last build. The skill runs it and stops on a non-zero exit — no model compares the numbers.
105
-
106
- **`ai-factory gcf-harness run <item-id…> [--agent "<cmd>"]`** — runs a batch at once, each item in its own worktree (`gcf worktree <id>`) with its own agent session: `claude -p --output-format stream-json --verbose "/gcf-run <id> --worktree"` by default, or the command in `--agent` / `GCF_RUN_AGENT`. The sessions run unattended, so set the agent's permissions for print mode first. A session ends with a commit and `gcf verify <id> --mark` (the `GCF-Verified` trailer); a question for the human goes into `.gcf-session/outcome.json` in its worktree, and `run` records the block on main. Then `gcf integrate` merges the verified branches and records each move, and `run` prints the playtest session. Its first step, like `/gcf-run`'s, integrates the verified branches a dead run left. A session that ended with no result leaves its item `ready`; the next `run` resumes its worktree and the agent's own session (`--resume <session_id>`, kept in `.gcf-session/runs/<id>.agent.json`), in either run mode; `--fresh` starts a new session instead. A session cut off by Claude's usage limit reports `paused (usage limit, resets 3am (…))` and `limit_resets`. Logs: `.gcf-session/runs/<id>.log`, written as the session works: a `start:` line, then one stamped line per agent message, tool call (`tool: Edit <file>`, `tool: Bash <command>`) and failed tool result, and at the end the agent's final text and `done in 34m, 212 turns, $3.41 (…tokens)`; stderr goes in as it is, and a non-Claude `--agent` keeps its own lines. With `--json`, each item carries the session's `cost_usd`, `tokens`, `turns` and `duration_ms` when the agent reported them. One run drives an item at a time (`.gcf-session/runs/<id>.lock`), and a resumed worktree first gets main merged in, so the answer from an `unblock` reaches the session. A worktree sees only what is committed: keep `.ai-factory.json`, the installed extensions with their `node_modules` (a `node_modules/` line in `.gitignore` drops the core's `yaml` and `cnlp-kit`, and `ai-factory gcf` fails in the worktree) and `.claude/` (skills, the readset-guard hook) in git, or the session has no `/gcf-run` and no `ai-factory gcf`. On Windows a project in a deep folder needs `git config core.longpaths true`, or `git worktree add` fails on `Filename too long`.
107
-
108
- **`ai-factory gcf-harness metrics [--since <date>] [--json]`** — the run metrics of Harness-PRD §11 from `gcf/.metrics`: how many item runs reached `submit` or `close` (a run the usage limit paused or a session cut short does not count as finished), the block reasons, what the runs cost (dollars, minutes, turns, handoffs, code written outside aif-implement), the plan checks per item (the improve passes), the DoD attempts per item and the checks that failed them, and the guard firings by hook and by item. The logs: `run-log.csv` (one line per item of each `run`), `guard-log.csv` (each denial of readset-guard and implement-guard, by hook: `readset`, `implement`, or `verify` for a move past the verify gate), and the core's `plan-log.csv` and `verify-log.csv`. A worktree session's lines go to the main checkout's logs; the next `gcf integrate` commits them.
109
-
110
- **`/gcf-run-ingest <gdd.md>`** — imports a design document as a fan-out workflow: parallel aspect extraction, provenance verified by code rather than by an agent (a quote either is a verbatim substring of its section or it is not), completeness lenses per candidate, and an interaction matrix computed from the candidates that write the same state.
111
-
112
- **readset-guard** — a `PreToolUse` hook on Read/Grep/Glob. While a run manifest exists at `.gcf-session/readset.json`, a path inside `gcf/` that is not in the readset is denied, and so is a Grep from the project root (no `path`, or a `path` above `gcf/`) unless its `glob` starts with a literal directory other than `gcf` (`src/**`, not `**/*.md`), because such a content search would read the whole tree past the gate. Glob and Greps scoped to the game code are never restricted. No manifest means no restriction: manual work is never gated. An honest limit — `cat` through Bash still bypasses it. This is a discipline tool, not a security perimeter.
113
-
114
- **implement-guard** — a `UserPromptSubmit` and `PreToolUse` hook (Skill, the write tools, Bash and PowerShell). A session that starts `/gcf-run` (typed, passed to `claude -p`, or invoked as a skill) gets a state in `.gcf-session/guard/<session_id>.json`; until it invokes the aif-implement skill, Edit, Write, MultiEdit and NotebookEdit are denied outside `gcf/`, `.ai-factory/`, `.gcf-session/` and markdown, and a markdown write that adds a `- [x]` tick is denied too. Any other session is never touched, and an error lets the call through. A `gcf submit` or `gcf close` with `--unverified` is refused in such a session, after its end move too (a close the core refused does not free it for a skip): only the human moves an item past the DoD gate, from a terminal of their own. Such a refusal is logged with the hook name `verify`. The move that ends the item (`gcf block`, `submit` or `close`, through Bash or PowerShell) lets the session go, so the operator's own edits after a blocked run are free again. A plugin's skill (`<plugin>:aif-implement`) counts too. Limits: the flag is per session, so in a batch the first item's aif-implement frees the rest; a write through Bash is not seen, by the run report either.
115
-
116
- ## Docs
117
-
118
- [Harness-PRD](https://github.com/VirtualMaestro/GCF/blob/main/docs/Harness-PRD.md) is the spec: pipeline stages, gates, execution surfaces, the guard's contract.
119
-
120
- ## License
121
-
122
- MIT
1
+ # gcf-harness-aif-ext
2
+
3
+ Claude-Code-specific orchestration for the [Game Context Framework](../gcf-aif-ext). Optional: GCF works without it, by hand.
4
+
5
+ > **Claude Code only.** Codex and the other AI Factory runtimes are not supported: the harness is built on Claude Code
6
+ > dynamic workflows and `PreToolUse` hooks, which they do not have. AI Factory still copies the `gcf-run` skills into
7
+ > every runtime the project is configured for, where they do not work — on a project without Claude Code, do not
8
+ > install the harness. GCF itself keeps working on any runtime.
9
+
10
+ The harness turns policy-as-text into an executable pipeline. The game's state is on disk in `gcf/` and git, so a run killed at any point restarts and reaches the same state. The runs' own state is in `.gcf-session/`: the agent sessions a rerun resumes, the item worktrees with their uncommitted work, locks and logs. Losing it never breaks the game's model, but it loses those resumes, that work and the diagnosis: delete a single stale file, never the folder.
11
+
12
+ ## Requirements
13
+
14
+ - [`gcf-aif-ext`](../gcf-aif-ext) `^0.7.14 || ^0.8.0 || ^0.9.0` installed (the peer range of `package.json`), with a `gcf/` tree in the project — declared as a peer dependency, and `gcf-harness init` refuses when the `gcf` command is not registered
15
+ - Claude Code 2.1.270+ (hooks, dynamic workflows) — the only supported runtime
16
+ - AI Factory 2.x, Node.js ≥ 22.14
17
+
18
+ ## Install
19
+
20
+ The shortest way is from the core: `ai-factory gcf init` asks whether to install the harness too, and on yes runs both steps below. It asks only in a terminal and only when the project has the Claude Code agent; `gcf init --harness` installs it without asking, `--no-harness` skips the question.
21
+
22
+ By hand, into a project that already has the core, from npm or a local checkout:
23
+
24
+ ```bash
25
+ ai-factory extension add gcf-aif-ext # the core, if not yet installed
26
+ ai-factory extension add gcf-harness-aif-ext # npm
27
+ # ai-factory extension add ../GCF/packages/gcf-harness-aif-ext # local checkout
28
+ ```
29
+
30
+ This installs the `gcf-run` and `gcf-run-ingest` skills and registers the `gcf-harness` command. Then initialize the harness in the project — like `gcf init`, once per project:
31
+
32
+ ```bash
33
+ ai-factory gcf-harness init # per project: .claude/settings.json + .gitignore
34
+ ```
35
+
36
+ It is **per project**, not global — run it again in every game repository: it adds the readset-guard and implement-guard entries to the project's `.claude/settings.json` (never `~/.claude`) and `.gcf-session/` to `.gitignore`. It also allows what an unattended `claude -p` run needs at least — `Edit`, `Write`, `Bash(git *)`, `Bash(ai-factory *)`, and the same two as `PowerShell(…)` rules, the tool the agent runs commands with on Windows — because print mode cannot ask and denies the rest; add your engine's tools yourself (for example `mcp__<editor-server>` for an editor driven over MCP). Commit `.claude/settings.json`: the rules apply to every Claude session in the project. It is idempotent — a re-run after moving or cloning the project repoints the hook at the new path — refuses when the `gcf` command is not registered, and refuses to rewrite a `settings.json` it cannot parse. It is a separate step for the same reason as `gcf hooks-install`: an AI Factory manifest cannot install Claude Code hooks.
37
+
38
+ ## Upgrade
39
+
40
+ ```bash
41
+ ai-factory extension update gcf-harness-aif-ext
42
+ ```
43
+
44
+ Updating keeps the hook entry valid — it points into the extension's install directory, which an update refreshes in place.
45
+
46
+ 0.5.0 drives work items (`gcf/work/<id>.md`, schema 3) instead of cards and requires `gcf-aif-ext` 0.4.0 — update both together; against an older core the gate refuses with `gcf-aif-ext >= 0.4.0 is required`. A project still holding schema 2 cards in `gcf/cards/` re-creates them first (see the core's "Upgrading from 0.3.x"). What changes for you: `/gcf-run` takes ids of items in `ready`; it no longer stops at `built` but ends each item with `submit`, `close` or `block`; the plan is improved in passes until it converges; the WIP cap counts only items that end waiting for a verdict.
47
+
48
+ 0.5.1 is a fix release. During a run, `gcf/config.yml` is always readable, and a Grep inside `gcf/` reads only readset files. An import breaks a `depends:` cycle the pair checks closed and asks a D1 about it. It cuts a section longer than a segment at paragraphs, and lens and pair prompts carry a window around the quote. `/gcf-run` checks the plan against each pillar's invariant and asks each pillar's review question over the diff. Use it with core 0.4.1, which brings the parent feature into the readset.
49
+
50
+ 0.9.8 changes no code: its peer range adds core 0.9.0, whose board read is schema 2 (the harness does not read it).
51
+
52
+ 0.9.6 (with core 0.7.14, now the peer range): `/gcf-run-ingest` hands its workflow the sections with their bodies, gets the same delta again after a failed run and ends the import with `gcf anchor --done`; it takes the text of a changed section as `/gcf-ingest` does, and adds resources, entities and measurable constraints by the sequential pass. The workflow marks the GDD as data in every prompt and asks a lens's D2 as a D1. `/gcf-run` reads only `INDEX.md` and `config.yml` beyond the readset, hands fresh subagents the context's graveyard and D2 lines, counts a re-verify after review against `dod_attempts`, files a D1 for a design question on main, never widens the readset by a false `depends:`, and runs in Claude Code only.
53
+
54
+ 0.9.5: `gcf-harness metrics` also sums the cost per item over all its runs and per day and week (`items`, `by_day`, `by_week` in `--json`, a `weeks:` line in the text); `gcf-board` 0.2.18 shows them in its Metrics tab. A resumed session's cost no longer counts twice: `claude` reports a resumed session's whole dollar total, so the lessons turn and a rerun after a limit or a cut now count from what the session had already spent (it is kept in `<id>.agent.json`); before, a lessons turn added its session's cost again. The `done in …` line of the log still shows claude's own figure. A core refusal reads as its whole message: a failed `git worktree add` names its cause, not only git's first line.
55
+
56
+ 0.9.4 keeps run metrics (Harness-PRD §11) and adds `ai-factory gcf-harness metrics`. Use it with core 0.7.13, which logs the plan checks and the DoD attempts, and refuses `close` and `submit` without a green `gcf verify` of the code as it is. `/gcf-run` runs the verify again after a review fix; implement-guard refuses `gcf close` or `gcf submit` with `--unverified` in a `/gcf-run` session, since a move past the DoD gate is the human's call. A main-mode item whose move went past it anyway (the commit says `(unverified: …)`) reads `— moved without a green gcf verify` on its report line, and `gcf-harness metrics` counts such moves.
57
+
58
+ 0.9.2 holds `/gcf-run` to aif-implement. Run `ai-factory gcf-harness init` again after the update: it registers the new hook.
59
+ - The implement guard: in a session that runs `/gcf-run`, a write to a code file is denied until the session invokes the aif-implement skill (gcf-run step 13), and so is a plan tick, which only aif-implement sets. Planning stays free: `gcf/`, `.ai-factory/`, `.gcf-session/` and any markdown file. After aif-implement every write is free, the fixes of a red DoD and of the review included. It works in the harness's runs and in an interactive `/gcf-run` alike, and touches no other session.
60
+ - `/gcf-run` converges a plan when an improve pass finds nothing blocking: a wrong or missing behavior or task, a broken pillar invariant, a rule conflict, a task no check can prove. Polish (wording, splitting tasks, order) is applied, but no longer keeps the loop going. Before, a pass that changed any task asked for one more, and a fresh reviewer almost always changes something. The report row per pass gives the blocking and polish counts.
61
+ - `/gcf-run` answers aif-plan's own questions (tests, logging, docs) itself, from the item, its DoD and the project's rules.
62
+ - The run report marks an item whose session wrote code without aif-implement: `— code written outside aif-implement` on its line, `process` in `--json` and in its kept record. It reads the session's own events, its subagents' included, so it also covers a project without the guard registered. A write through Bash is seen by neither: the review of the diff is the check there.
63
+ - Lessons (with core 0.7.10): after each agent session the run asks the same session, resumed, what got in its way - tools, rules, the framework, the project template - with the questions of `ai-factory gcf lessons prompt`. Its answers go to the inbox on main as lessons (`gcf lessons add`), and the board shows them on the card, in the drawer and in the inbox. The run passes `--no-lessons` to `/gcf-run`, so the agent carries no lessons instruction while it works. The turn follows a result, a handoff (before the fresh session), a timeout or an error; not a usage limit or a stop, and only for a `claude` agent with a session id. Another agent asks its lessons itself at the end of a run on main; in a worktree it records none. It takes up to 10 minutes; its cost goes on the item, and the report line says `, N lessons`. A failed lessons turn is logged and changes nothing else. A project that turns lessons off, or a core before 0.7.10, gets no turn and no flag.
64
+
65
+ 0.9.1 is a fix release:
66
+ - A stopped session reads as `no result (stopped)`, and its kept record as `ended: stopped`: before, the kill's exit code (`agent exit 1` on Windows).
67
+ - `gcf-harness stop <id>` never kills the run: a stop before the item's session starts (or between two sessions of a handoff) leaves `.gcf-session/runs/<id>.stop`, and that session is stopped as it starts. Before, a stop then killed the whole run with the other items of its batch. A run hung before its first session (in its worktree setup) is not stopped. On main, a stop marks the item too once the run has reached it. Known limit: a stop in the moment between a worktree run's claim of the item and its clearing of an old mark is lost.
68
+ - A stop that comes while the session starts no longer misses it.
69
+
70
+ 0.9.0, to update together with core 0.7.6:
71
+ - The harness's own agent runs with `--permission-mode bypassPermissions`: it may do everything but the project's deny rules, which hold in every mode. The rules come from the deny groups of `gcf/config.yml` (`ai-factory gcf permissions`, or the board): git history and uncommitted work, recursive delete, publishing, the human's GCF moves and the guards are on by default; secrets, changes outside the project and killing processes are off. `git push` is allowed. Deny rules match the command as written: they catch accidents, not a rewording, and `/gcf-run` makes a refused command a stop with `needs permission: <command>`.
72
+ - A run loads the project's settings and MCP servers only (`--setting-sources project,local --strict-mcp-config --mcp-config .mcp.json`): the operator's plugins, hooks and claude.ai connectors stay out. So does `env` or `apiKeyHelper` in `~/.claude/settings.json`: an operator who logs in through them, not `claude login`, names the agent with `--agent`. The deny rules and the handoff guard come in `.gcf-session/runs/agent-settings.json` (`--settings`), so a worktree gets them without a commit.
73
+ - Context handoff: past `context_handoff_pct` (60 by default) of the window, or at a compaction, the run flags the session; the handoff guard then denies every call of the main agent but the plan's read and edit with the instruction to write `## Handoff` into the plan and end. The run starts a fresh session with `/gcf-run <id> --handoff`, which goes on from the plan: the ticked tasks stay done. A session that works on past its flag is stopped; after 3 handoffs in a row the item is blocked with `context handoff limit`. The window is `context_window`, else the one a result of the same model reported (`.gcf-session/runs/windows.json`); with neither, the first session of a model runs without a handoff and says so. The sessions of an item share one timeout, and their costs add up; `--json` gives `handoffs`.
74
+ - `auto_compact_pct` sets the agent's `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`, at least 15 points above the handoff share.
75
+ - The readset-guard reads the manifest of the directory the session started in (`CLAUDE_PROJECT_DIR`): an agent's `cd` no longer lifts the readset.
76
+ - `/gcf-run` writes a plan task's code through aif-implement, so the plan ticks show the item's progress, and answers aif-implement's questions itself: no commit, stash or merge.
77
+
78
+ 0.8.0, to update together with core 0.7.0:
79
+ - `run_mode: main` in `gcf/config.yml` (or `run --mode main`): items run one after another in the main checkout, for an agent that works through an editor bound to the project folder. The item carries the core's session mark (`gcf claim`), not a run lock, so the agent records its own move; one run works the checkout at a time (`.gcf-session/runs/.main-run.lock`).
80
+ - `gcf-harness next [N] --json`: the ready items that can run together now, by priority; each is taken while the batch with it passes the gate.
81
+ - `gcf-harness stop <id>`: stops the session that works the item (its run lock names it); the run records no result for it and goes on with the rest. The item stays ready and its work is kept. Known limit: the session is killed at once, so a `gcf` move it was in the middle of may leave `.gcf-session/main.lock` behind (taken over once its pid is gone).
82
+ - A run on main refreshes its item's mark every 5 minutes, and the readset-guard hook refreshes live marks on each read: a long build without a gcf command does not expire it.
83
+ - `run` refuses an id that is not a slug before it names a lock file or builds the agent's command line.
84
+ - The gate lets a session through for the item its own run marked (`GCF_RUN_ITEM`); `/gcf-run` outside a worktree claims each item after its gate and releases one it leaves without a move.
85
+
86
+ 0.7.0, to update together with core 0.6.0: an item's `model:` and `effort:` (`gcf item new --model <m> --effort <e>`) go to its agent as `--model <m> --effort <e>`, read from `gcf board --json`; a value that is not one plain word fails that item and starts no session. `--timeout <minutes>` (120 by default) stops a session that runs longer, with every process it started; its item stays ready, and its run lock is freed. The gate counts the items other runs drive now: their places under the WIP limit, and their systems — a board starts one run per click. Requires `gcf-aif-ext` 0.6.
87
+
88
+ 0.6.1 is a fix release, to update together with core 0.5.3. The run lock `.gcf-session/runs/<id>.lock` is created exclusively, and a lock left by a dead run is taken over; while it is live, the gate refuses the item to another run and the core refuses any move on it, `/gcf-run` on main included. A session whose log cannot open ends as an error and releases its claim.
89
+
90
+ 0.6.0 adds `ai-factory gcf-harness run` (a batch at once, a worktree and an agent session per item, then the integrator) and the `--worktree` mode of `/gcf-run`, whose session ritual now integrates the verified branches a dead run left. It requires `gcf-aif-ext` 0.5.0 (`gcf worktree`, `gcf integrate`, `gcf verify`) — update both together and run `ai-factory gcf init`. The DoD of `/gcf-run` is `ai-factory gcf verify <id>`, and the item's `live:` delta is written before it.
91
+
92
+ 0.4.1 is a patch release. `/gcf-run` now commits the implementation first, then flips the card to `built` in a second commit, with `built_at` set to the implementation commit's hash. Update the core to 0.3.1 together with the harness: without it, an audit run before a verdict makes the pre-commit gate refuse that verdict.
93
+
94
+ To remove the extension:
95
+
96
+ ```bash
97
+ ai-factory extension remove gcf-harness-aif-ext
98
+ ```
99
+
100
+ Removal does not touch `.claude/settings.json`: delete the entries whose command ends in `# gcf-readset-guard` or `# gcf-implement-guard` (under `PreToolUse` and `UserPromptSubmit`) by hand, or the tools they match will report a hook error.
101
+
102
+ ## What it adds
103
+
104
+ **`/gcf-run <item-id…>`** — drives work items through plan, implementation and DoD, with every gate checked *before* the tokens are spent: the audit ritual, the gate below, the context budget. The plan is written by `aif-plan`, then improved in passes, each by a fresh subagent that reads only the plan and the readset and records every default it picks; `ai-factory gcf plan check <id>` runs after each pass, and a pass with no blocking finding (a wrong or missing behavior or task, a broken pillar invariant, a rule conflict, an unprovable task) ends the loop. A blocking finding left after `plan_passes` passes (3 by default), or a question only the human can answer (a save format, a public API, a new dependency, a pillar conflict), blocks the item before any code is written. The DoD is `ai-factory gcf verify <id>` — the gate's checks, the item's `live:` delta, and the project's `dod.build` and `dod.test` commands from `gcf/config.yml` — plus a review by a fresh subagent, up to `dod_attempts` attempts. Every item ends in a state the core records: `gcf submit` (gate `verdict` or `decision` — waits for the human), `gcf close` (gate `auto` — done, or a soft unit closed as `unplayed`) or `gcf block` with the reason. The verdict and the decision belong to the human: the pipeline stops at `submit` and prints the playtest list.
105
+
106
+ **`ai-factory gcf-harness gate <item-id…>`** — the `/gcf-run` gate as code. It reads one `gcf audit --json` report and exits 1 with a one-line reason when the items may not go: a core older than 0.4.0, a `schema:` other than 1 in `gcf/config.yml`, an id with no work item, a feature (run its children; the feature closes when they are finished), an item that is not `ready`, an unplayed dependency, no WIP room for the batch (items awaiting a verdict + the batch's `gate: verdict` items over `wip_built_limit`), or two items of the batch touching the same system unless both say `parallel: ok`. The tune limit is not a gate rule: `verdict tune` itself refuses at the limit, and an item tuned up to it still gets its last build. The skill runs it and stops on a non-zero exit — no model compares the numbers.
107
+
108
+ **`ai-factory gcf-harness run <item-id…> [--agent "<cmd>"]`** — runs a batch at once, each item in its own worktree (`gcf worktree <id>`) with its own agent session: `claude -p --output-format stream-json --verbose "/gcf-run <id> --worktree"` by default, or the command in `--agent` / `GCF_RUN_AGENT`. The sessions run unattended, so set the agent's permissions for print mode first. A session ends with a commit and `gcf verify <id> --mark` (the `GCF-Verified` trailer); a question for the human goes into `.gcf-session/outcome.json` in its worktree, and `run` records the block on main. Then `gcf integrate` merges the verified branches and records each move, and `run` prints the playtest session. Its first step, like `/gcf-run`'s, integrates the verified branches a dead run left. A session that ended with no result leaves its item `ready`; the next `run` resumes its worktree and the agent's own session (`--resume <session_id>`, kept in `.gcf-session/runs/<id>.agent.json`), in either run mode; `--fresh` starts a new session instead. A session cut off by Claude's usage limit reports `paused (usage limit, resets 3am (…))` and `limit_resets`. Logs: `.gcf-session/runs/<id>.log`, written as the session works: a `start:` line, then one stamped line per agent message, tool call (`tool: Edit <file>`, `tool: Bash <command>`) and failed tool result, and at the end the agent's final text and `done in 34m, 212 turns, $3.41 (…tokens)`; stderr goes in as it is, and a non-Claude `--agent` keeps its own lines. With `--json`, each item carries the session's `cost_usd`, `tokens`, `turns` and `duration_ms` when the agent reported them. One run drives an item at a time (`.gcf-session/runs/<id>.lock`), and a resumed worktree first gets main merged in, so the answer from an `unblock` reaches the session. A worktree sees only what is committed: keep `.ai-factory.json`, the installed extensions with their `node_modules` (a `node_modules/` line in `.gitignore` drops the core's `yaml` and `cnlp-kit`, and `ai-factory gcf` fails in the worktree) and `.claude/` (skills, the readset-guard hook) in git, or the session has no `/gcf-run` and no `ai-factory gcf`. On Windows a project in a deep folder needs `git config core.longpaths true`, or `git worktree add` fails on `Filename too long`.
109
+
110
+ **`ai-factory gcf-harness metrics [--since <date>] [--json]`** — the run metrics of Harness-PRD §11 from `gcf/.metrics`: how many item runs reached `submit` or `close` (a run the usage limit paused or a session cut short does not count as finished), the block reasons, what the runs cost (dollars, minutes, turns, handoffs, code written outside aif-implement), the plan checks per item (the improve passes), the DoD attempts per item and the checks that failed them, and the guard firings by hook and by item. The logs: `run-log.csv` (one line per item of each `run`), `guard-log.csv` (each denial of readset-guard and implement-guard, by hook: `readset`, `implement`, or `verify` for a move past the verify gate), and the core's `plan-log.csv` and `verify-log.csv`. A worktree session's lines go to the main checkout's logs; the next `gcf integrate` commits them.
111
+
112
+ **`/gcf-run-ingest <gdd.md>`** — imports a design document as a fan-out workflow: parallel aspect extraction, provenance verified by code rather than by an agent (a quote either is a verbatim substring of its section or it is not), completeness lenses per candidate, and an interaction matrix computed from the candidates that write the same state.
113
+
114
+ **readset-guard** — a `PreToolUse` hook on Read/Grep/Glob. While a run manifest exists at `.gcf-session/readset.json`, a path inside `gcf/` that is not in the readset is denied, and so is a Grep from the project root (no `path`, or a `path` above `gcf/`) unless its `glob` starts with a literal directory other than `gcf` (`src/**`, not `**/*.md`), because such a content search would read the whole tree past the gate. Glob and Greps scoped to the game code are never restricted. No manifest means no restriction: manual work is never gated. An honest limit — `cat` through Bash still bypasses it. This is a discipline tool, not a security perimeter.
115
+
116
+ **implement-guard** — a `UserPromptSubmit` and `PreToolUse` hook (Skill, the write tools, Bash and PowerShell). A session that starts `/gcf-run` (typed, passed to `claude -p`, or invoked as a skill) gets a state in `.gcf-session/guard/<session_id>.json`; until it invokes the aif-implement skill, Edit, Write, MultiEdit and NotebookEdit are denied outside `gcf/`, `.ai-factory/`, `.gcf-session/` and markdown, and a markdown write that adds a `- [x]` tick is denied too. Any other session is never touched, and an error lets the call through. A `gcf submit` or `gcf close` with `--unverified` is refused in such a session, after its end move too (a close the core refused does not free it for a skip): only the human moves an item past the DoD gate, from a terminal of their own. Such a refusal is logged with the hook name `verify`. The move that ends the item (`gcf block`, `submit` or `close`, through Bash or PowerShell) lets the session go, so the operator's own edits after a blocked run are free again. A plugin's skill (`<plugin>:aif-implement`) counts too. Limits: the flag is per session, so in a batch the first item's aif-implement frees the rest; a write through Bash is not seen, by the run report either.
117
+
118
+ ## Docs
119
+
120
+ [Harness-PRD](https://github.com/VirtualMaestro/GCF/blob/main/docs/Harness-PRD.md) is the spec: pipeline stages, gates, execution surfaces, the guard's contract.
121
+
122
+ ## License
123
+
124
+ MIT
package/extension.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/lee-to/ai-factory/2.x/schemas/extension.schema.json",
3
3
  "name": "gcf-harness-aif-ext",
4
- "version": "0.9.7",
4
+ "version": "0.9.8",
5
5
  "description": "GCF orchestration harness for Claude Code: one-command card pipeline, readset guard",
6
6
  "skills": [
7
7
  "skills/gcf-run",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gcf-harness-aif-ext",
3
- "version": "0.9.7",
3
+ "version": "0.9.8",
4
4
  "description": "GCF orchestration harness for Claude Code: one-command card pipeline, readset guard",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "prepack": "node -e \"const p=require('./package.json'),e=require('./extension.json');if(p.version!==e.version)throw new Error('version mismatch: package.json '+p.version+' vs extension.json '+e.version)\""
29
29
  },
30
30
  "peerDependencies": {
31
- "gcf-aif-ext": "^0.7.14 || ^0.8.0"
31
+ "gcf-aif-ext": "^0.7.14 || ^0.8.0 || ^0.9.0"
32
32
  },
33
33
  "files": [
34
34
  "extension.json",