gcf-harness-aif-ext 0.8.0 → 0.8.1
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.
- package/README.md +1 -1
- package/commands/harness.js +26 -6
- package/extension.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ This installs the `gcf-run` and `gcf-run-ingest` skills and registers the `gcf-h
|
|
|
33
33
|
ai-factory gcf-harness init # per project: .claude/settings.json + .gitignore
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
It is **per project**, not global — run it again in every game repository: it adds the readset-guard `PreToolUse` entry to the project's `.claude/settings.json` (never `~/.claude`) and `.gcf-session/` to `.gitignore`. 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.
|
|
36
|
+
It is **per project**, not global — run it again in every game repository: it adds the readset-guard `PreToolUse` entry 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 *)` — 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
37
|
|
|
38
38
|
## Upgrade
|
|
39
39
|
|
package/commands/harness.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// `ai-factory gcf-harness init` — registers the readset-guard PreToolUse hook in the
|
|
2
2
|
// project's .claude/settings.json (the AIF manifest cannot install Claude Code hooks —
|
|
3
|
-
// same decision as gcf hooks-install for git hooks). Idempotent by marker comment.
|
|
3
|
+
// same decision as gcf hooks-install for git hooks). Idempotent by marker comment. It also
|
|
4
|
+
// allows what a headless agent run needs (AGENT_ALLOW).
|
|
4
5
|
// `ai-factory gcf-harness gate <ids…>` — the /gcf-run gate as code (Harness-PRD §4.3).
|
|
5
6
|
import { readFile, writeFile, mkdir, appendFile } from 'node:fs/promises';
|
|
6
7
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -210,6 +211,20 @@ function registerGuard(settings, command) {
|
|
|
210
211
|
return stale.length ? 'repointed' : null;
|
|
211
212
|
}
|
|
212
213
|
|
|
214
|
+
// What a headless `claude -p` run needs at least: it cannot ask, so anything not allowed is
|
|
215
|
+
// denied. The engine's own tools (an editor's MCP server) are the project's to add.
|
|
216
|
+
const AGENT_ALLOW = ['Edit', 'Write', 'Bash(git *)', 'Bash(ai-factory *)'];
|
|
217
|
+
|
|
218
|
+
/** Adds the rules the settings do not hold yet; returns the ones added. */
|
|
219
|
+
function allowAgent(settings) {
|
|
220
|
+
settings.permissions ??= {};
|
|
221
|
+
settings.permissions.allow ??= [];
|
|
222
|
+
const added = AGENT_ALLOW.filter((r) => !settings.permissions.allow.includes(r));
|
|
223
|
+
settings.permissions.allow.push(...added);
|
|
224
|
+
|
|
225
|
+
return added;
|
|
226
|
+
}
|
|
227
|
+
|
|
213
228
|
/**
|
|
214
229
|
* Only an active rule ignoring the root .gcf-session/ counts — not a comment or a pattern
|
|
215
230
|
* for some other directory that happens to contain the name.
|
|
@@ -235,14 +250,17 @@ async function init(program) {
|
|
|
235
250
|
const guard = path.join(EXT_ROOT, 'hooks', 'readset-guard.js').replaceAll('\\', '/');
|
|
236
251
|
const settings = await readSettings(settingsFile);
|
|
237
252
|
const change = registerGuard(settings, `node "${guard}" # ${MARKER}`);
|
|
238
|
-
|
|
253
|
+
const allowed = allowAgent(settings);
|
|
254
|
+
if (change || allowed.length) {
|
|
239
255
|
await mkdir(path.dirname(settingsFile), { recursive: true });
|
|
240
256
|
await writeFile(settingsFile, `${JSON.stringify(settings, null, 2)}\n`, 'utf8');
|
|
241
|
-
console.log(`readset-guard ${change} → ${settingsFile}`);
|
|
242
|
-
} else {
|
|
243
|
-
console.log('readset-guard already registered');
|
|
244
257
|
}
|
|
245
258
|
|
|
259
|
+
console.log(
|
|
260
|
+
change ? `readset-guard ${change} → ${settingsFile}` : 'readset-guard already registered',
|
|
261
|
+
);
|
|
262
|
+
if (allowed.length) console.log(`agent runs may now: ${allowed.join(', ')}`);
|
|
263
|
+
|
|
246
264
|
await ignoreSession(projectDir);
|
|
247
265
|
}
|
|
248
266
|
|
|
@@ -261,7 +279,9 @@ export function register(program) {
|
|
|
261
279
|
|
|
262
280
|
harness
|
|
263
281
|
.command('init')
|
|
264
|
-
.description(
|
|
282
|
+
.description(
|
|
283
|
+
'Initialize the harness in this project: readset-guard hook, agent permissions (idempotent)',
|
|
284
|
+
)
|
|
265
285
|
.action(() => init(program));
|
|
266
286
|
|
|
267
287
|
harness
|
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.8.
|
|
4
|
+
"version": "0.8.1",
|
|
5
5
|
"description": "GCF orchestration harness for Claude Code: one-command card pipeline, readset guard",
|
|
6
6
|
"skills": [
|
|
7
7
|
"skills/gcf-run",
|