@chrono-meta/fh-gate 1.4.52 → 1.4.53
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/.claude/registry/README.md +26 -0
- package/.claude/registry/agent_cards.json +73 -0
- package/.claude-plugin/marketplace.json +25 -0
- package/AGENTS.md +2 -2
- package/CHEATSHEET.md +1 -0
- package/README.md +12 -1
- package/bin/fh-codex-doctor.js +419 -0
- package/docs/codex-compat.md +18 -4
- package/knowledge/shared/harness-core/sonnet_floor_doctrine.md +7 -0
- package/package.json +11 -3
- package/plugins/fh-commons/.claude-plugin/plugin.json +23 -0
- package/plugins/fh-meta/.claude-plugin/plugin.json +36 -0
- package/scripts/count_check.sh +95 -0
- package/scripts/selfcheck.sh +27 -20
- package/templates/CLAUDE.md +87 -0
- package/templates/local_fh_context.md +18 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# .claude/registry
|
|
2
|
+
|
|
3
|
+
Machine-readable registries for the forge-harness automation layer.
|
|
4
|
+
|
|
5
|
+
## agent_cards.json
|
|
6
|
+
|
|
7
|
+
The **canonical machine-readable mirror** of the agent registry. `AGENTS.md` stays the
|
|
8
|
+
human-facing source of truth (roles, rationale, prose); `agent_cards.json` is its structured
|
|
9
|
+
counterpart for tooling — capability discovery, dispatch routing, and count-drift detection.
|
|
10
|
+
|
|
11
|
+
Inspired by the **A2A "Agent Card"** pattern (the 2026 standard for agent capability discovery):
|
|
12
|
+
each card declares an agent's `id`, `file`, `role`, `allowed_tools`, `invoked_by`, and a `writes`
|
|
13
|
+
flag. `agent_count` is asserted at the top level and **should equal the number of tracked `.md`
|
|
14
|
+
files in `.claude/agents/`, `plugins/fh-meta/agents/`, and `plugins/fh-commons/agents/`** —
|
|
15
|
+
re-checked on every agent add/remove by `harness-doctor` Step 11-2-B, which compares
|
|
16
|
+
`agent_count` against the live file count; a mismatch is a State-Degradation signal.
|
|
17
|
+
|
|
18
|
+
### Regeneration
|
|
19
|
+
|
|
20
|
+
Hand- or script-derived from `AGENTS.md` (Agent Registry + Tool-restrictions tables) plus each
|
|
21
|
+
tracked agent `.md` frontmatter. Regenerate whenever an agent is added, removed, or its tools
|
|
22
|
+
change — and re-check `agent_count`. On any disagreement between `AGENTS.md` and an agent's own
|
|
23
|
+
`.md`, **prefer the agent `.md`** (e.g. `challenger.md` has no `tools:` field, so its tools come
|
|
24
|
+
from `AGENTS.md`).
|
|
25
|
+
|
|
26
|
+
> Frontier basis: `knowledge/shared/harness-core/harness_frontier_diagnosis_2026-06-02.md` (identity ① Control Tower — closes the "no canonical machine-readable registry / count drift" gap noted in `fh_ecosystem_positioning.md`).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"generated": "2026-06-07",
|
|
4
|
+
"source": "derived from AGENTS.md (Agent Registry + Tool restrictions tables) and tracked agent files",
|
|
5
|
+
"convention": "A2A Agent Card pattern — machine-readable capability discovery, count-synced to plugin agents/ directories",
|
|
6
|
+
"agent_count": 8,
|
|
7
|
+
"agents": [
|
|
8
|
+
{
|
|
9
|
+
"id": "beginner",
|
|
10
|
+
"file": "plugins/fh-meta/agents/beginner.md",
|
|
11
|
+
"role": "First-contact cold-read standpoint (user-mastery spectrum entry tier) — surfaces onboarding friction a fluent author cannot feel; constructive, not adversarial",
|
|
12
|
+
"allowed_tools": ["Read"],
|
|
13
|
+
"invoked_by": ["sim-conductor", "marketplace-gate", "install-wizard", "direct"],
|
|
14
|
+
"writes": false
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "main-player",
|
|
18
|
+
"file": "plugins/fh-meta/agents/main-player.md",
|
|
19
|
+
"role": "Engaged-user standpoint (user-mastery spectrum core tier) — intelligently scopes Light/Midcore/Heavy; Heavy carries the classic power-user edge/limit lens",
|
|
20
|
+
"allowed_tools": ["Read", "Grep", "Glob"],
|
|
21
|
+
"invoked_by": ["sim-conductor", "direct"],
|
|
22
|
+
"writes": false
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "expert",
|
|
26
|
+
"file": "plugins/fh-meta/agents/expert.md",
|
|
27
|
+
"role": "Domain-authority standpoint (user-mastery spectrum frontier tier) — web-grounded accuracy + SOTA currency, citation-enforced; checks against the external world, not internal assets",
|
|
28
|
+
"allowed_tools": ["Read", "WebSearch", "WebFetch"],
|
|
29
|
+
"invoked_by": ["sim-conductor", "paper-review", "direct"],
|
|
30
|
+
"writes": false
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "challenger",
|
|
34
|
+
"file": "plugins/fh-meta/agents/challenger.md",
|
|
35
|
+
"role": "Frontier-grade adversarial evaluator — adapts attack vectors to artifact type, enforces evidence citation, models its own information asymmetry; U1 absorbs the skeptic 'why not just X?' lens",
|
|
36
|
+
"allowed_tools": ["Read", "Grep", "Glob", "WebSearch", "WebFetch"],
|
|
37
|
+
"invoked_by": ["steel-quench", "harvest-loop", "sim-conductor", "direct"],
|
|
38
|
+
"writes": false
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "fact-checker",
|
|
42
|
+
"file": "plugins/fh-meta/agents/fact-checker.md",
|
|
43
|
+
"role": "Pre-recommendation deduplication — greps hub assets for existing skills/agents/patterns before a new recommendation; catches stale facts and duplicate work",
|
|
44
|
+
"allowed_tools": ["Read", "Grep", "Glob"],
|
|
45
|
+
"invoked_by": ["main-agent-before-new-asset"],
|
|
46
|
+
"writes": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "hub-persona-auditor",
|
|
50
|
+
"file": "plugins/fh-meta/agents/hub-persona-auditor.md",
|
|
51
|
+
"role": "Pre-publication audit of external-facing assets — 3+ persona simulation, 4-axis review (resonance/confusion/resistance/supplement), 3-tier revision proposals",
|
|
52
|
+
"allowed_tools": ["Read", "Grep", "Glob"],
|
|
53
|
+
"invoked_by": ["hub-cc-pr-reviewer", "sim-conductor", "direct"],
|
|
54
|
+
"writes": false
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "persona-innovator",
|
|
58
|
+
"file": "plugins/fh-meta/agents/persona-innovator.md",
|
|
59
|
+
"role": "Naming gap detection + frame proposals + external frontier absorption signals",
|
|
60
|
+
"allowed_tools": ["Read", "Grep", "Glob", "WebSearch", "WebFetch"],
|
|
61
|
+
"invoked_by": ["sim-conductor", "harvest-loop", "direct"],
|
|
62
|
+
"writes": false
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "quench-challenger",
|
|
66
|
+
"file": "plugins/fh-commons/agents/quench-challenger.md",
|
|
67
|
+
"role": "Steel-quench dedicated adversary — 3-DNA synthesis of Devil + Innovator + Prescriber; every attack paired with a concrete fix direction",
|
|
68
|
+
"allowed_tools": ["Read", "Grep", "Glob"],
|
|
69
|
+
"invoked_by": ["steel-quench", "install-doctor", "marketplace-gate"],
|
|
70
|
+
"writes": false
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "forge-harness",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "chrono-meta",
|
|
5
|
+
"email": "chrono-meta@users.noreply.github.com"
|
|
6
|
+
},
|
|
7
|
+
"metadata": {
|
|
8
|
+
"description": "forge-harness — Multi-instance persona orchestration and meta-tooling marketplace for Claude Code. Harness engineering toolkit for teams that want to evolve their AI collaboration practices.",
|
|
9
|
+
"pluginRoot": "./plugins"
|
|
10
|
+
},
|
|
11
|
+
"plugins": [
|
|
12
|
+
{
|
|
13
|
+
"name": "fh-meta",
|
|
14
|
+
"version": "1.4.53",
|
|
15
|
+
"description": "Hub meta-operations toolkit — 33 skills + 7 agents. New in 1.4.53: `fh-codex-doctor` (npm bin) — Codex adapter drift scanner; reads the documented M1/M2/M3 skill tier map + skill/agent source and reports codex-native/adapter-required/claude-native/unclassified per unit, wired into `npm test`/`prepublishOnly` (fail-closed on unclassified Claude-native primitives). New in 1.4.49: steel-quench gains Step 0.6 Verdict-Invariance Probe (groundedness axis — a load-bearing judged gate's verdict must track behavior, not rubric phrasing; measured flip-count over cross-family paraphrases; arXiv:2605.06161 Policy Invariance anchor); multi_model_sidecar_strategy §Vendor-native harness (a model is strongest in its own vendor CLI — Claude/CC, GPT/codex, Gemini/Antigravity; a universal router degrades all of them, so it stays an autocomplete/QA sidecar, never orchestration); predelete_check.sh fail-closed rewrite; memory-hygiene A-TMA anchor. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor command-output axis (route to rtk/proxy for verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce envs). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard queryable-wiki scaffold (INDEX + session-start read + R/W/C ingest). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment) + video-ingest (capability-routed video ingestion). New in 1.4.x: verify-axis check-class taxonomy (mandatory-pass/measured/judged), no-reinvention Tier-0 inventory, 7-class failure taxonomy, Destructive-Op Gate, Wave-T (Temper), tier-floor governance, Mode D Model Notice, FC consent lane, default-Sonnet guidance. New in 1.3.0: public-surface-audit, field-harvest Mode B auto-trigger, 4-axis gate scope ext. Validated cross-CLI: Claude Code, Codex, Gemini.",
|
|
16
|
+
"source": "./plugins/fh-meta"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "fh-commons",
|
|
20
|
+
"version": "1.4.53",
|
|
21
|
+
"description": "Project-agnostic utility skills — 4 skills (convergence-loop · deliberation · mcp-circuit-breaker · token-budget-gate) + 1 agent (quench-challenger). Domain-independent utilities transplantable into any project.",
|
|
22
|
+
"source": "./plugins/fh-commons"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
package/AGENTS.md
CHANGED
|
@@ -138,8 +138,8 @@ echo "Apply the following skill to the artifact below." | \
|
|
|
138
138
|
|
|
139
139
|
| Tier | Definition | Examples |
|
|
140
140
|
|---|---|---|
|
|
141
|
-
| **M1 — Full** | All phases run without CC-native dependencies — no Stop hook, no `.claude/agents/` dispatch, no `/model` | `token-budget-gate`, `asset-placement-gate`, `phantom-quench`, `deep-clarify`, `
|
|
142
|
-
| **M2 — Partial** | Core workflow runs; CC-native phases require manual adaptation or skip | `steel-quench` (Wave 1–3 ✅; quench-challenger agent = manual), `harness-doctor`, `context-doctor`, `sim-conductor`, `harvest-loop` (git scan phase ✅; PR auto-proposal = manual) |
|
|
141
|
+
| **M1 — Full** | All phases run without CC-native dependencies — no Stop hook, no `.claude/agents/` dispatch, no `/model` | `token-budget-gate`, `asset-placement-gate`, `phantom-quench`, `deep-clarify`, `convergence-loop` |
|
|
142
|
+
| **M2 — Partial** | Core workflow runs; CC-native phases require manual adaptation or skip | `deliberation` (Mediator/Jury Agent steps = manual), `steel-quench` (Wave 1–3 ✅; quench-challenger agent = manual), `harness-doctor`, `context-doctor`, `sim-conductor`, `harvest-loop` (git scan phase ✅; PR auto-proposal = manual) |
|
|
143
143
|
| **M3 — CC-only** | Requires CC Stop hook or session-scoped agent dispatch; methodology reference only | `goal-quench` (Phase 3 Stop hook), `hub-cc-pr-reviewer` (CC session context), `install-wizard` (settings.json write) |
|
|
144
144
|
|
|
145
145
|
**M2 adaptation pattern**: when a step references `Agent(subagent_type=...)` or a slash command, substitute with `fh-run` (preferred) or a direct `codex exec` call reading the sub-agent's SKILL.md — same workflow, different runtime.
|
package/CHEATSHEET.md
CHANGED
|
@@ -197,6 +197,7 @@ FH_BACKEND=codex npx --package @chrono-meta/fh-gate fh-gate # Codex backend (d
|
|
|
197
197
|
# Run a skill or agent doc through a backend, outside Claude Code
|
|
198
198
|
npx --package @chrono-meta/fh-gate fh-run --skill <name>
|
|
199
199
|
npx --package @chrono-meta/fh-gate fh-goal "<goal text>" # goal runner
|
|
200
|
+
npx --package @chrono-meta/fh-gate fh-codex-doctor --strict # Codex adapter drift check
|
|
200
201
|
```
|
|
201
202
|
|
|
202
203
|
| Knob | Values | Effect |
|
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ forge-harness is structured as **two distinct layers**:
|
|
|
95
95
|
| Layer | Contents | AI compatibility |
|
|
96
96
|
|---|---|---|
|
|
97
97
|
| **Methodology layer** | `tracks/`, `knowledge/`, `SKILL.md` docs, session protocols | Any AI model |
|
|
98
|
-
| **Automation layer** | `.claude/agents
|
|
98
|
+
| **Automation layer** | `plugins/*/agents/` (FH agents), `.claude/agents/` (field-project overrides), hooks, slash commands, `CLAUDE.md` rules | Claude Code only |
|
|
99
99
|
|
|
100
100
|
The methodology layer is the portable core — persistent hub, accumulating learnings, curating cross-project knowledge. The automation layer makes it frictionless when running Claude Code.
|
|
101
101
|
|
|
@@ -149,6 +149,17 @@ FH_BACKEND=codex npx --package @chrono-meta/fh-gate fh-run --skill phantom-quenc
|
|
|
149
149
|
FH_BACKEND=codex npx --package @chrono-meta/fh-gate fh-run --agent fh-commons:quench-challenger --file plugins/fh-meta/skills/foo/SKILL.md
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
+
To check whether a changed FH skill/agent surface still has a clean Codex adapter path, run:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npx --package @chrono-meta/fh-gate fh-codex-doctor --strict
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`fh-codex-doctor` scans the canonical skill/agent registry and reports which units are Codex-native,
|
|
159
|
+
adapter-required, Claude-native, or unclassified. It is a drift detector for the thin adapter boundary;
|
|
160
|
+
it does not try to clone the Claude Code automation layer. When run from an FH checkout it scans the
|
|
161
|
+
current working tree; outside a checkout it scans the installed package.
|
|
162
|
+
|
|
152
163
|
For Codex-primary work, keep using Codex's native goal/session features when available. `fh-goal` is only a portable wrapper for one-off non-interactive runs that should be followed by FH governance:
|
|
153
164
|
|
|
154
165
|
```bash
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
function usage() {
|
|
8
|
+
process.stdout.write(`Usage:
|
|
9
|
+
fh-codex-doctor [--root <path>] [--json] [--strict]
|
|
10
|
+
|
|
11
|
+
Scans FH skills and agents for Codex runtime compatibility drift.
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
--root <path> Repository/package root. Defaults to cwd when it looks like FH,
|
|
15
|
+
otherwise this package root.
|
|
16
|
+
--json Emit machine-readable JSON.
|
|
17
|
+
--strict Exit 1 when high-severity drift is found.
|
|
18
|
+
--help Show this help.
|
|
19
|
+
`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = { root: defaultRoot(), json: false, strict: false };
|
|
24
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
25
|
+
const arg = argv[i];
|
|
26
|
+
if (arg === '--help' || arg === '-h') {
|
|
27
|
+
out.help = true;
|
|
28
|
+
} else if (arg === '--json') {
|
|
29
|
+
out.json = true;
|
|
30
|
+
} else if (arg === '--strict') {
|
|
31
|
+
out.strict = true;
|
|
32
|
+
} else if (arg === '--root') {
|
|
33
|
+
i += 1;
|
|
34
|
+
if (!argv[i]) throw new Error('--root requires a path');
|
|
35
|
+
out.root = path.resolve(argv[i]);
|
|
36
|
+
} else {
|
|
37
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function looksLikeFHRoot(dir) {
|
|
44
|
+
return exists(path.join(dir, 'package.json')) &&
|
|
45
|
+
exists(path.join(dir, 'plugins')) &&
|
|
46
|
+
exists(path.join(dir, 'AGENTS.md'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function defaultRoot() {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
if (looksLikeFHRoot(cwd)) return cwd;
|
|
52
|
+
return path.resolve(__dirname, '..');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readText(file) {
|
|
56
|
+
return fs.readFileSync(file, 'utf8');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function maybeReadText(file) {
|
|
60
|
+
try {
|
|
61
|
+
return readText(file);
|
|
62
|
+
} catch (_err) {
|
|
63
|
+
return '';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function exists(file) {
|
|
68
|
+
try {
|
|
69
|
+
fs.accessSync(file, fs.constants.F_OK);
|
|
70
|
+
return true;
|
|
71
|
+
} catch (_err) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function walk(dir, predicate) {
|
|
77
|
+
const results = [];
|
|
78
|
+
if (!exists(dir)) return results;
|
|
79
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
80
|
+
for (const entry of entries) {
|
|
81
|
+
const p = path.join(dir, entry.name);
|
|
82
|
+
if (entry.isDirectory()) {
|
|
83
|
+
results.push(...walk(p, predicate));
|
|
84
|
+
} else if (!predicate || predicate(p)) {
|
|
85
|
+
results.push(p);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function rel(root, file) {
|
|
92
|
+
return path.relative(root, file).split(path.sep).join('/');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function parseFrontmatter(text) {
|
|
96
|
+
if (!text.startsWith('---\n')) return {};
|
|
97
|
+
const end = text.indexOf('\n---', 4);
|
|
98
|
+
if (end === -1) return {};
|
|
99
|
+
const block = text.slice(4, end).split('\n');
|
|
100
|
+
const out = {};
|
|
101
|
+
for (const line of block) {
|
|
102
|
+
const m = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
103
|
+
if (!m) continue;
|
|
104
|
+
out[m[1]] = m[2].replace(/^["']|["']$/g, '');
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function extractBacktickNames(line) {
|
|
110
|
+
const names = [];
|
|
111
|
+
const re = /`([^`]+)`/g;
|
|
112
|
+
let m;
|
|
113
|
+
while ((m = re.exec(line)) !== null) {
|
|
114
|
+
const value = m[1].trim();
|
|
115
|
+
if (/^[a-z0-9][a-z0-9-]*$/.test(value)) names.push(value);
|
|
116
|
+
}
|
|
117
|
+
return names;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function documentedTiers(root) {
|
|
121
|
+
const sources = [
|
|
122
|
+
path.join(root, 'AGENTS.md'),
|
|
123
|
+
];
|
|
124
|
+
const tiers = new Map();
|
|
125
|
+
const evidence = [];
|
|
126
|
+
for (const source of sources) {
|
|
127
|
+
const text = maybeReadText(source);
|
|
128
|
+
if (!text) continue;
|
|
129
|
+
const lines = text.split('\n');
|
|
130
|
+
lines.forEach((line, index) => {
|
|
131
|
+
const tierMatch = line.match(/\|\s*\*\*(M[123])\b/);
|
|
132
|
+
if (!tierMatch) return;
|
|
133
|
+
const tier = tierMatch[1];
|
|
134
|
+
for (const name of extractBacktickNames(line)) {
|
|
135
|
+
tiers.set(name, { tier, source: rel(root, source), line: index + 1 });
|
|
136
|
+
evidence.push({ name, tier, source: rel(root, source), line: index + 1 });
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return { tiers, evidence };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function compatDocTierMentions(root, skillNames) {
|
|
144
|
+
const source = path.join(root, 'docs', 'codex-compat.md');
|
|
145
|
+
const text = maybeReadText(source);
|
|
146
|
+
const mentions = new Map();
|
|
147
|
+
if (!text) return mentions;
|
|
148
|
+
const lines = text.split('\n');
|
|
149
|
+
lines.forEach((line, index) => {
|
|
150
|
+
const tierMatch = line.match(/\b(M[123])\b/);
|
|
151
|
+
if (!tierMatch) return;
|
|
152
|
+
const tier = tierMatch[1];
|
|
153
|
+
for (const name of extractBacktickNames(line)) {
|
|
154
|
+
if (!skillNames.has(name)) continue;
|
|
155
|
+
if (!mentions.has(name)) mentions.set(name, []);
|
|
156
|
+
mentions.get(name).push({ tier, source: rel(root, source), line: index + 1 });
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return mentions;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const PRIMITIVES = [
|
|
163
|
+
{
|
|
164
|
+
id: 'agent-dispatch',
|
|
165
|
+
severity: 'adapter',
|
|
166
|
+
regexes: [/Agent\s*\(/, /\bsubagent_type\b/, /\bAgent View\b/, /\bAgent\b tool\b/, /\bAgent invocation instruction\b/, /\bparallel-Agent dispatch\b/],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'slash-command',
|
|
170
|
+
severity: 'adapter',
|
|
171
|
+
regexes: [/(^|[\s`])\/[a-z][a-z0-9-]+(?=($|[\s`),.;:}]))/m],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'hook',
|
|
175
|
+
severity: 'claude-native',
|
|
176
|
+
regexes: [/\bStop hook\b/i, /\bPostToolUse\b/, /\bSessionStart\b/],
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: 'model-command',
|
|
180
|
+
severity: 'claude-native',
|
|
181
|
+
regexes: [/(^|[\s`])\/model\b/m],
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
function scanPrimitives(text) {
|
|
186
|
+
const hits = [];
|
|
187
|
+
for (const primitive of PRIMITIVES) {
|
|
188
|
+
for (const regex of primitive.regexes) {
|
|
189
|
+
const m = regex.exec(text);
|
|
190
|
+
if (!m) continue;
|
|
191
|
+
hits.push({
|
|
192
|
+
id: primitive.id,
|
|
193
|
+
severity: primitive.severity,
|
|
194
|
+
line: text.slice(0, m.index).split('\n').length,
|
|
195
|
+
match: m[0].trim(),
|
|
196
|
+
});
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return hits;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function classify(docTier, primitives) {
|
|
204
|
+
const hasClaudeNative = primitives.some((p) => p.severity === 'claude-native');
|
|
205
|
+
const hasAgentDispatch = primitives.some((p) => p.id === 'agent-dispatch');
|
|
206
|
+
const hasAdapter = primitives.some((p) => p.severity === 'adapter');
|
|
207
|
+
if (docTier === 'M1' && (hasClaudeNative || hasAgentDispatch)) return 'tier-drift';
|
|
208
|
+
if (docTier === 'M1') return 'codex-native';
|
|
209
|
+
if (docTier === 'M2') return 'adapter-required';
|
|
210
|
+
if (docTier === 'M3') return 'claude-native';
|
|
211
|
+
if (hasClaudeNative) return 'claude-native-unclassified';
|
|
212
|
+
if (hasAdapter) return 'adapter-required-unclassified';
|
|
213
|
+
return 'codex-native-candidate';
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function collectSkills(root) {
|
|
217
|
+
const skillsRoot = path.join(root, 'plugins');
|
|
218
|
+
const files = walk(skillsRoot, (p) => path.basename(p) === 'SKILL.md');
|
|
219
|
+
return files.sort().map((file) => {
|
|
220
|
+
const text = readText(file);
|
|
221
|
+
const fm = parseFrontmatter(text);
|
|
222
|
+
const skillName = fm.name || path.basename(path.dirname(file));
|
|
223
|
+
return {
|
|
224
|
+
type: 'skill',
|
|
225
|
+
name: skillName,
|
|
226
|
+
path: rel(root, file),
|
|
227
|
+
frontmatter: fm,
|
|
228
|
+
primitives: scanPrimitives(text),
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function collectAgents(root) {
|
|
234
|
+
const agents = [];
|
|
235
|
+
for (const plugin of ['fh-meta', 'fh-commons']) {
|
|
236
|
+
const dir = path.join(root, 'plugins', plugin, 'agents');
|
|
237
|
+
for (const file of walk(dir, (p) => p.endsWith('.md')).sort()) {
|
|
238
|
+
const text = readText(file);
|
|
239
|
+
agents.push({
|
|
240
|
+
type: 'agent',
|
|
241
|
+
name: path.basename(file, '.md'),
|
|
242
|
+
path: rel(root, file),
|
|
243
|
+
plugin,
|
|
244
|
+
primitives: scanPrimitives(text),
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return agents;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function loadAgentCards(root) {
|
|
252
|
+
const file = path.join(root, '.claude', 'registry', 'agent_cards.json');
|
|
253
|
+
if (!exists(file)) return { present: false, count: 0 };
|
|
254
|
+
try {
|
|
255
|
+
const parsed = JSON.parse(readText(file));
|
|
256
|
+
const count = Array.isArray(parsed)
|
|
257
|
+
? parsed.length
|
|
258
|
+
: (Array.isArray(parsed.agents) ? parsed.agents.length : (parsed.agent_count || Object.keys(parsed).length));
|
|
259
|
+
return { present: true, path: rel(root, file), count };
|
|
260
|
+
} catch (err) {
|
|
261
|
+
return { present: true, path: rel(root, file), error: err.message, count: 0 };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function buildReport(root) {
|
|
266
|
+
const docs = documentedTiers(root);
|
|
267
|
+
const skills = collectSkills(root).map((skill) => {
|
|
268
|
+
const doc = docs.tiers.get(skill.name);
|
|
269
|
+
return {
|
|
270
|
+
...skill,
|
|
271
|
+
documentedTier: doc ? doc.tier : null,
|
|
272
|
+
tierEvidence: doc || null,
|
|
273
|
+
codexMode: classify(doc && doc.tier, skill.primitives),
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
const agents = collectAgents(root);
|
|
277
|
+
const skillNames = new Set(skills.map((s) => s.name));
|
|
278
|
+
const compatMentions = compatDocTierMentions(root, skillNames);
|
|
279
|
+
const findings = [];
|
|
280
|
+
|
|
281
|
+
for (const item of skills) {
|
|
282
|
+
if (item.documentedTier === 'M1') {
|
|
283
|
+
const bad = item.primitives.filter((p) => p.severity === 'claude-native' || p.id === 'agent-dispatch');
|
|
284
|
+
if (bad.length > 0) {
|
|
285
|
+
findings.push({
|
|
286
|
+
severity: 'HIGH',
|
|
287
|
+
code: 'M1_HAS_CLAUDE_NATIVE_PRIMITIVE',
|
|
288
|
+
path: item.path,
|
|
289
|
+
message: `${item.name} is documented M1 but contains ${bad.map((p) => p.id).join(', ')}`,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (const entry of docs.evidence) {
|
|
296
|
+
if (!skillNames.has(entry.name)) {
|
|
297
|
+
findings.push({
|
|
298
|
+
severity: 'WARN',
|
|
299
|
+
code: 'DOC_TIER_REFERENCES_MISSING_SKILL',
|
|
300
|
+
path: `${entry.source}:${entry.line}`,
|
|
301
|
+
message: `${entry.name} is listed as ${entry.tier} but no matching SKILL.md was found`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
for (const item of skills) {
|
|
307
|
+
const mentions = compatMentions.get(item.name) || [];
|
|
308
|
+
for (const mention of mentions) {
|
|
309
|
+
if (item.documentedTier && mention.tier !== item.documentedTier) {
|
|
310
|
+
findings.push({
|
|
311
|
+
severity: 'HIGH',
|
|
312
|
+
code: 'CODEX_COMPAT_TIER_DISAGREES_WITH_AGENTS',
|
|
313
|
+
path: `${mention.source}:${mention.line}`,
|
|
314
|
+
message: `${item.name} is ${item.documentedTier} in AGENTS.md but ${mention.tier} in docs/codex-compat.md`,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const counts = {
|
|
321
|
+
skills: skills.length,
|
|
322
|
+
agents: agents.length,
|
|
323
|
+
modes: {},
|
|
324
|
+
tiers: { M1: 0, M2: 0, M3: 0, unclassified: 0 },
|
|
325
|
+
findings: {
|
|
326
|
+
HIGH: findings.filter((f) => f.severity === 'HIGH').length,
|
|
327
|
+
WARN: findings.filter((f) => f.severity === 'WARN').length,
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
for (const skill of skills) {
|
|
331
|
+
counts.modes[skill.codexMode] = (counts.modes[skill.codexMode] || 0) + 1;
|
|
332
|
+
counts.tiers[skill.documentedTier || 'unclassified'] += 1;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
status: findings.some((f) => f.severity === 'HIGH') ? 'DRIFT' : 'OK',
|
|
337
|
+
root,
|
|
338
|
+
counts,
|
|
339
|
+
agentCards: loadAgentCards(root),
|
|
340
|
+
findings,
|
|
341
|
+
skills,
|
|
342
|
+
agents: agents.map((agent) => ({
|
|
343
|
+
name: agent.name,
|
|
344
|
+
path: agent.path,
|
|
345
|
+
plugin: agent.plugin,
|
|
346
|
+
codexMode: 'adapter-runnable',
|
|
347
|
+
note: 'Agents are runnable via fh-run --agent or a runtime-specific dispatch adapter; auto-dispatch is host-specific.',
|
|
348
|
+
})),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function printText(report) {
|
|
353
|
+
const lines = [];
|
|
354
|
+
lines.push('FH Codex Doctor');
|
|
355
|
+
lines.push(`Status: ${report.status}`);
|
|
356
|
+
lines.push(`Root: ${report.root}`);
|
|
357
|
+
lines.push('');
|
|
358
|
+
lines.push('Summary');
|
|
359
|
+
lines.push(`- Skills scanned: ${report.counts.skills}`);
|
|
360
|
+
lines.push(`- Agents scanned: ${report.counts.agents}`);
|
|
361
|
+
lines.push(`- Documented tiers: M1=${report.counts.tiers.M1} M2=${report.counts.tiers.M2} M3=${report.counts.tiers.M3} unclassified=${report.counts.tiers.unclassified}`);
|
|
362
|
+
lines.push(`- Codex modes: ${Object.keys(report.counts.modes).sort().map((k) => `${k}=${report.counts.modes[k]}`).join(' ')}`);
|
|
363
|
+
if (report.agentCards.present) {
|
|
364
|
+
lines.push(`- Agent cards: ${report.agentCards.count}${report.agentCards.error ? ` (parse error: ${report.agentCards.error})` : ''}`);
|
|
365
|
+
} else {
|
|
366
|
+
lines.push('- Agent cards: missing');
|
|
367
|
+
}
|
|
368
|
+
lines.push('');
|
|
369
|
+
lines.push('Findings');
|
|
370
|
+
if (report.findings.length === 0) {
|
|
371
|
+
lines.push('- none');
|
|
372
|
+
} else {
|
|
373
|
+
for (const finding of report.findings) {
|
|
374
|
+
lines.push(`- ${finding.severity} ${finding.code} ${finding.path} :: ${finding.message}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
lines.push('');
|
|
378
|
+
lines.push('Codex Runtime Contract');
|
|
379
|
+
lines.push('- codex-native: run directly with fh-run/codex exec.');
|
|
380
|
+
lines.push('- adapter-required: core method can run, but Agent/slash steps need adapter substitution.');
|
|
381
|
+
lines.push('- claude-native: do not auto-pass; require Claude Code host or explicit dedicated adapter.');
|
|
382
|
+
lines.push('- unclassified modes are drift signals for future manifest backfill.');
|
|
383
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function main() {
|
|
387
|
+
let args;
|
|
388
|
+
try {
|
|
389
|
+
args = parseArgs(process.argv.slice(2));
|
|
390
|
+
} catch (err) {
|
|
391
|
+
process.stderr.write(`ERROR: ${err.message}\n`);
|
|
392
|
+
usage();
|
|
393
|
+
process.exit(11);
|
|
394
|
+
}
|
|
395
|
+
if (args.help) {
|
|
396
|
+
usage();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const root = args.root;
|
|
400
|
+
if (!exists(path.join(root, 'package.json'))) {
|
|
401
|
+
process.stderr.write(`ERROR: root does not look like a package/repo root: ${root}\n`);
|
|
402
|
+
process.exit(11);
|
|
403
|
+
}
|
|
404
|
+
if (!looksLikeFHRoot(root)) {
|
|
405
|
+
process.stderr.write(`ERROR: root is missing required FH surfaces (AGENTS.md and plugins/): ${root}\n`);
|
|
406
|
+
process.exit(11);
|
|
407
|
+
}
|
|
408
|
+
const report = buildReport(root);
|
|
409
|
+
if (args.json) {
|
|
410
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
411
|
+
} else {
|
|
412
|
+
printText(report);
|
|
413
|
+
}
|
|
414
|
+
if (args.strict && report.counts.findings.HIGH > 0) {
|
|
415
|
+
process.exit(1);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
main();
|
package/docs/codex-compat.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Status: **beta**. This document is beta-removal condition #2 (see `AGENTS.md` → Codex Compatibility → Beta removal conditions). It lists what works, what breaks, and what to expect when applying forge-harness (FH) methodology through OpenAI Codex (`codex exec`) instead of Claude Code.
|
|
4
4
|
|
|
5
|
-
FH is a 2-layer system: a **methodology layer** (`tracks/`, `knowledge/`, `SKILL.md` docs) that is model-agnostic, and an **automation layer** (Claude Code hooks, `.claude/agents/`, `/model`, settings.json) that is Claude-native. Codex users run the methodology layer by reading `SKILL.md` files directly; automation steps either run through runtime adapters (`fh-gate`, `fh-run`) or require manual substitution.
|
|
5
|
+
FH is a 2-layer system: a **methodology layer** (`tracks/`, `knowledge/`, `SKILL.md` docs) that is model-agnostic, and an **automation layer** (Claude Code hooks, plugin-channel agents under `plugins/*/agents/`, field-project overrides under `.claude/agents/`, `/model`, settings.json) that is Claude-native. Codex users run the methodology layer by reading `SKILL.md` files directly; automation steps either run through runtime adapters (`fh-gate`, `fh-run`) or require manual substitution.
|
|
6
6
|
|
|
7
7
|
## Validated invocation pattern
|
|
8
8
|
|
|
@@ -65,6 +65,20 @@ Resolution order:
|
|
|
65
65
|
| `--agent plugin:name` | `plugins/plugin/agents/name.md` first |
|
|
66
66
|
| `--unit path` | explicit file path |
|
|
67
67
|
|
|
68
|
+
### `fh-codex-doctor`
|
|
69
|
+
|
|
70
|
+
`fh-codex-doctor` is the drift detector for the thin Codex adapter boundary. It reads the canonical
|
|
71
|
+
FH skill/agent files plus the documented M1/M2/M3 tier table, then reports which surfaces are
|
|
72
|
+
Codex-native, adapter-required, Claude-native, or unclassified:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx --package @chrono-meta/fh-gate fh-codex-doctor --strict
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Use it before promoting a new Codex automation path. Unknown Claude-native primitives fail closed as
|
|
79
|
+
"manual adaptation required" instead of being treated as compatible by default. When run from an FH
|
|
80
|
+
checkout it scans the current working tree; outside a checkout it scans the installed package.
|
|
81
|
+
|
|
68
82
|
### `fh-goal`
|
|
69
83
|
|
|
70
84
|
Codex has native goal/session features. Use those directly when they fit. `fh-goal` is not a replacement for Codex goal; it is a non-interactive wrapper for "run backend task, then run FH governance on changed files":
|
|
@@ -92,7 +106,7 @@ Both ran end-to-end with no Claude-native dependency. The M1 tier claim holds fo
|
|
|
92
106
|
When `codex exec` runs **inside this repo**, FH's Claude-native git/Stop/PostToolUse hooks attempt to fire and emit `hook: Stop Failed` / `hook: PostToolUse Failed` lines interleaved with output. These are **harmless to the skill result** — the skill's verdict is produced correctly — but they are visible noise. Running from a directory **without** FH's `.claude/settings.json` (the normal Codex-user case) avoids them entirely. Filter with `grep -vE "^hook:"` if needed.
|
|
93
107
|
|
|
94
108
|
### 2. M2 skills need manual agent substitution
|
|
95
|
-
M2 skills (`steel-quench`, `harness-doctor`, `context-doctor`, `sim-conductor`, `harvest-loop`) have a core workflow that runs under Codex, but any step that dispatches `Agent(subagent_type=...)` or a slash command must be replaced by `fh-run` or a direct `codex exec` call reading the sub-agent's `SKILL.md`/agent `.md` — same workflow, different runtime (the "M2 adaptation pattern" in `AGENTS.md`). Example: `steel-quench` Waves 1–3 run; the `quench-challenger` agent step becomes `fh-run --agent fh-commons:quench-challenger`.
|
|
109
|
+
M2 skills (`deliberation`, `steel-quench`, `harness-doctor`, `context-doctor`, `sim-conductor`, `harvest-loop`) have a core workflow that runs under Codex, but any step that dispatches `Agent(subagent_type=...)` or a slash command must be replaced by `fh-run` or a direct `codex exec` call reading the sub-agent's `SKILL.md`/agent `.md` — same workflow, different runtime (the "M2 adaptation pattern" in `AGENTS.md`). Example: `steel-quench` Waves 1–3 run; the `quench-challenger` agent step becomes `fh-run --agent fh-commons:quench-challenger`.
|
|
96
110
|
|
|
97
111
|
### 3. M3 skills do not run automatically under Codex
|
|
98
112
|
M3 skills (`goal-quench` Phase-3 Stop hook, `hub-cc-pr-reviewer` CC session context, `install-wizard` settings.json write) require Claude-Code-native runtime and are **methodology reference only** under Codex unless a dedicated adapter exists. Use Codex's native goal/session features for goal control, and use `fh-gate` after completion for FH quality gating.
|
|
@@ -107,8 +121,8 @@ The sibling pattern for Gemini is `gemini -p "$(cat <skill+artifact>)"`. Outside
|
|
|
107
121
|
|
|
108
122
|
| Tier | Under Codex | Action |
|
|
109
123
|
|---|---|---|
|
|
110
|
-
| **M1** | Runs fully | `cat SKILL.md artifact \| codex exec -m gpt-5.5 -` |
|
|
111
|
-
| **M2** | Core runs; agent/slash steps via adapter | Substitute each dispatch with `fh-run` or a direct `codex exec` on the sub-agent's `.md` |
|
|
124
|
+
| **M1** | Runs fully (`token-budget-gate`, `asset-placement-gate`, `phantom-quench`, `deep-clarify`, `convergence-loop`) | `cat SKILL.md artifact \| codex exec -m gpt-5.5 -` |
|
|
125
|
+
| **M2** | Core runs; agent/slash steps via adapter (`deliberation`, `steel-quench`, `harness-doctor`, `context-doctor`, `sim-conductor`, `harvest-loop`) | Substitute each dispatch with `fh-run` or a direct `codex exec` on the sub-agent's `.md` |
|
|
112
126
|
| **M3** | Does not run automatically | Use native Codex session features where available; otherwise read as methodology reference or use a dedicated adapter |
|
|
113
127
|
|
|
114
128
|
## Beta removal — remaining (external-blocked)
|
|
@@ -33,6 +33,13 @@ markers) — never silently drop a capability.
|
|
|
33
33
|
→ SessionStart hook), the tone salience gap (2026-07-08 → recorded, prompt-layer), the
|
|
34
34
|
card-reconcile blind spot (2026-07-10 → mtime-independent STATUS map in the hook). The doctrine
|
|
35
35
|
is a name for what the fix pattern already was.
|
|
36
|
+
- **The value does not vanish at the top tier — the harness complements the strongest model too**
|
|
37
|
+
(operator observation, 2026-07-10, same-day measured): a Sonnet blind probe caught a SIGPIPE
|
|
38
|
+
silent-death defect in a script the top-tier session had just written (5/5 repro), and the new
|
|
39
|
+
close-chain checker blocked that same top-tier session's card-last violation twice on its first
|
|
40
|
+
day. Structure-enforcing checks are tier-blind by construction — so the harness raises the floor
|
|
41
|
+
for weak models *and* guards the ceiling for strong ones. Weak-model benefit is the larger term
|
|
42
|
+
(H1), top-tier benefit is the existence proof that the harness is not scaffolding-only.
|
|
36
43
|
|
|
37
44
|
## The defect class: tier-gated capability
|
|
38
45
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrono-meta/fh-gate",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.53",
|
|
4
4
|
"description": "FH runtime adapters — run FH governance, skills, and agents via Claude or Codex with machine-parseable gates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
"bin": {
|
|
21
21
|
"fh-gate": "bin/fh-gate.js",
|
|
22
22
|
"fh-run": "bin/fh-run.js",
|
|
23
|
-
"fh-goal": "bin/fh-goal.js"
|
|
23
|
+
"fh-goal": "bin/fh-goal.js",
|
|
24
|
+
"fh-codex-doctor": "bin/fh-codex-doctor.js"
|
|
24
25
|
},
|
|
25
26
|
"scripts": {
|
|
26
|
-
"prepare": "chmod +x bin/fh-gate.js bin/fh-run.js bin/fh-goal.js scripts/fh-gate.sh scripts/fh-run.sh scripts/fh-goal.sh",
|
|
27
|
+
"prepare": "chmod +x bin/fh-gate.js bin/fh-run.js bin/fh-goal.js bin/fh-codex-doctor.js scripts/fh-gate.sh scripts/fh-run.sh scripts/fh-goal.sh",
|
|
27
28
|
"test": "bash scripts/selfcheck.sh",
|
|
28
29
|
"prepublishOnly": "bash scripts/selfcheck.sh && bash scripts/public_surface_scan_files.sh",
|
|
29
30
|
"release": "bash scripts/public_surface_scan_files.sh && npm publish"
|
|
@@ -45,10 +46,13 @@
|
|
|
45
46
|
},
|
|
46
47
|
"files": [
|
|
47
48
|
"AGENTS.md",
|
|
49
|
+
".claude-plugin/marketplace.json",
|
|
48
50
|
"CATALOG.md",
|
|
49
51
|
"CHEATSHEET.md",
|
|
50
52
|
"CLAUDE.md",
|
|
53
|
+
".claude/registry/agent_cards.json",
|
|
51
54
|
"docs/CONTRIBUTING.md",
|
|
55
|
+
"bin/fh-codex-doctor.js",
|
|
52
56
|
"bin/fh-gate.js",
|
|
53
57
|
"bin/fh-run.js",
|
|
54
58
|
"bin/fh-goal.js",
|
|
@@ -57,9 +61,13 @@
|
|
|
57
61
|
"scripts/fh-gate.sh",
|
|
58
62
|
"scripts/fh-run.sh",
|
|
59
63
|
"scripts/fh-goal.sh",
|
|
64
|
+
"scripts/count_check.sh",
|
|
60
65
|
"scripts/selfcheck.sh",
|
|
66
|
+
"templates/local_fh_context.md",
|
|
67
|
+
"plugins/fh-meta/.claude-plugin/plugin.json",
|
|
61
68
|
"plugins/fh-meta/skills",
|
|
62
69
|
"plugins/fh-meta/agents",
|
|
70
|
+
"plugins/fh-commons/.claude-plugin/plugin.json",
|
|
63
71
|
"plugins/fh-commons/skills",
|
|
64
72
|
"plugins/fh-commons/agents",
|
|
65
73
|
"knowledge/shared/harness-core",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fh-commons",
|
|
3
|
+
"version": "1.4.53",
|
|
4
|
+
"engines": {
|
|
5
|
+
"claudeCode": ">=1.0.0"
|
|
6
|
+
},
|
|
7
|
+
"description": "Cross-project utility skill bundle — 4 skills + 1 agent. Domain-agnostic and portable: convergence-loop, deliberation, mcp-circuit-breaker, token-budget-gate + quench-challenger agent.",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "chrono-meta",
|
|
10
|
+
"email": "chrono-meta@users.noreply.github.com"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"commons",
|
|
14
|
+
"convergence-loop",
|
|
15
|
+
"gate-reinforcement",
|
|
16
|
+
"multi-round-validation",
|
|
17
|
+
"deliberation",
|
|
18
|
+
"multi-perspective-synthesis",
|
|
19
|
+
"forge-skill",
|
|
20
|
+
"domain-agnostic",
|
|
21
|
+
"cross-project"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fh-meta",
|
|
3
|
+
"version": "1.4.53",
|
|
4
|
+
"engines": {
|
|
5
|
+
"claudeCode": ">=1.0.0"
|
|
6
|
+
},
|
|
7
|
+
"description": "Hub meta-engineering toolkit — 33 skills + 7 agents. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor gains a command-output axis — routes to a command-output proxy/hook (rtk) to trim verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce environments (lossy filtering, off gate-input paths). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard scaffolds the companion store as a queryable wiki (INDEX + session-start read + Raw/Wiki/Conversation ingest axis). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment, calibration-gated) + video-ingest (capability-routed video ingestion). New in 1.4.37: corpus-grounding-expander + persona-roster-expander (field-harvested verbatim-relay capability skills). New in 1.3.0: public-surface-audit (git-tracked private-token leak scan), field-harvest Mode B session-end auto-trigger, 4-axis gate scope extension (docs/ + AGENTS.md). New in 1.2.0: pipeline-conductor (4-pipeline gated sweep), return-path-gate (chain closure audit), goal-quench (Stop hook + quality gate), steel-quench Wave 5 (multi-model sidecar challenger), 2-layer architecture docs, YAML validation script. Validated cross-CLI: Claude Code, Codex, Gemini.",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "chrono-meta",
|
|
10
|
+
"email": "chrono-meta@users.noreply.github.com"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"hub-meta",
|
|
14
|
+
"fact-check",
|
|
15
|
+
"self-verification",
|
|
16
|
+
"bidirectional-validation",
|
|
17
|
+
"cross-ecosystem-synergy",
|
|
18
|
+
"plugin-recommender",
|
|
19
|
+
"pr-review",
|
|
20
|
+
"harness-engineering",
|
|
21
|
+
"ai-collaboration",
|
|
22
|
+
"token-efficiency",
|
|
23
|
+
"context-doctor",
|
|
24
|
+
"harness-doctor",
|
|
25
|
+
"install-doctor",
|
|
26
|
+
"install-conflict-detection",
|
|
27
|
+
"install-wizard",
|
|
28
|
+
"onboarding-automation",
|
|
29
|
+
"marketplace-gate",
|
|
30
|
+
"marketplace-readiness",
|
|
31
|
+
"meta-prompt-builder",
|
|
32
|
+
"prompt-delegation",
|
|
33
|
+
"circular-validation",
|
|
34
|
+
"2d-adversary"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# count_check.sh — skill/agent count-consistency check (single source).
|
|
3
|
+
# Class: mandatory-pass (harness_6axis_framework.md §Axis 5) — exit 1 on drift.
|
|
4
|
+
#
|
|
5
|
+
# Called by ALL THREE count-consistency boundaries so one logic runs everywhere:
|
|
6
|
+
# - scripts/selfcheck.sh → publish-readiness (prepublishOnly + npm test)
|
|
7
|
+
# - templates/.git-hooks/pre-commit → local commit time, `--staged` (index mode)
|
|
8
|
+
# - .github/workflows/validate.yml → PR/merge boundary (checked-out tree == committed)
|
|
9
|
+
#
|
|
10
|
+
# Origin (fh_signal_2026-06-21): the count check used to live ONLY at the publish boundary.
|
|
11
|
+
# But the actor that breaks it — a commit/merge that adds/removes a skill dir — acts at
|
|
12
|
+
# commit/merge time, so a skill-adding PR (#111) merged with stale counts and they sat
|
|
13
|
+
# undetected on main until the next publish. This is the gate-locality gap (a gate must
|
|
14
|
+
# live where the breaking action happens). One source, three boundaries, no reinvention.
|
|
15
|
+
#
|
|
16
|
+
# Modes:
|
|
17
|
+
# (default) count the WORKING TREE — selfcheck (publish; tree == HEAD) and CI
|
|
18
|
+
# (a checked-out PR IS the committed state). cat/glob the on-disk files.
|
|
19
|
+
# --staged count the INDEX (exactly what THIS commit will contain) — the pre-commit
|
|
20
|
+
# hook. Fixes steel-quench S1 (2026-06-21): a worktree-only count can
|
|
21
|
+
# FALSE-PASS a commit that stages a skill add but leaves the count-file
|
|
22
|
+
# updates unstaged — the gate would verify a different tree than it commits.
|
|
23
|
+
set -u
|
|
24
|
+
cd "$(dirname "${BASH_SOURCE[0]}")/.." || { echo "COUNT-CHECK: FAIL (cannot cd to repo root)"; exit 1; }
|
|
25
|
+
|
|
26
|
+
MODE="worktree"
|
|
27
|
+
[ "${1:-}" = "--staged" ] && MODE="staged"
|
|
28
|
+
fail=0
|
|
29
|
+
|
|
30
|
+
# Read a tracked file's content from the active tree (index in --staged, disk otherwise).
|
|
31
|
+
read_tree() { # read_tree <path>
|
|
32
|
+
if [ "$MODE" = staged ]; then git show ":$1" 2>/dev/null; else cat "$1" 2>/dev/null; fi
|
|
33
|
+
}
|
|
34
|
+
# List a plugin's top-level SKILL.md paths in the active tree.
|
|
35
|
+
list_skills() { # list_skills <plugin>
|
|
36
|
+
if [ "$MODE" = staged ]; then
|
|
37
|
+
git ls-files --cached -- "plugins/$1/skills" 2>/dev/null \
|
|
38
|
+
| grep -E "^plugins/$1/skills/[^/]+/SKILL\.md$"
|
|
39
|
+
else
|
|
40
|
+
local s
|
|
41
|
+
for s in plugins/"$1"/skills/*/SKILL.md; do [ -f "$s" ] && echo "$s"; done
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
# Count a plugin's top-level agent .md files in the active tree.
|
|
45
|
+
count_agents() { # count_agents <plugin>
|
|
46
|
+
if [ "$MODE" = staged ]; then
|
|
47
|
+
git ls-files --cached -- "plugins/$1/agents" 2>/dev/null \
|
|
48
|
+
| grep -cE "^plugins/$1/agents/[^/]+\.md$"
|
|
49
|
+
else
|
|
50
|
+
ls plugins/"$1"/agents/*.md 2>/dev/null | wc -l | tr -d ' '
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
# Active skill = SKILL.md whose head (first 20 lines) carries no deprecation marker
|
|
54
|
+
# (a whole-file grep false-positives on skills that merely mention the word).
|
|
55
|
+
count_active() { # count_active <plugin>
|
|
56
|
+
local n=0 s
|
|
57
|
+
while IFS= read -r s; do
|
|
58
|
+
[ -z "$s" ] && continue
|
|
59
|
+
read_tree "$s" | head -20 | grep -qE 'deprecated: true|DEPRECATED' || n=$((n+1))
|
|
60
|
+
done < <(list_skills "$1")
|
|
61
|
+
echo "$n"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
meta_sk=$(count_active fh-meta); meta_ag=$(count_agents fh-meta)
|
|
65
|
+
com_sk=$(count_active fh-commons); com_ag=$(count_agents fh-commons)
|
|
66
|
+
total_sk=$((meta_sk + com_sk)); total_ag=$((meta_ag + com_ag))
|
|
67
|
+
|
|
68
|
+
# Impossible-zero guard (steel-quench A4 — fail CLOSED): fh-meta always has active skills.
|
|
69
|
+
# A 0 means the tree/glob resolved to nothing (wrong cwd, empty index, sh-as-bash shim) —
|
|
70
|
+
# a gate must never return "consistent" from an empty tree.
|
|
71
|
+
if [ "$meta_sk" -eq 0 ]; then
|
|
72
|
+
echo "COUNT-CHECK: FAIL (0 active fh-meta skills — empty/wrong tree, mode=$MODE)"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
count_check() { # count_check <label> <file> <expected-string>
|
|
77
|
+
if read_tree "$2" | grep -q "$3"; then
|
|
78
|
+
echo "PASS count: $1"
|
|
79
|
+
else
|
|
80
|
+
echo "FAIL count: $1 — expected \"$3\" in $2 (actual: fh-meta ${meta_sk}sk/${meta_ag}ag, fh-commons ${com_sk}sk/${com_ag}ag)"
|
|
81
|
+
fail=1
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
count_check "fh-meta plugin.json" plugins/fh-meta/.claude-plugin/plugin.json "${meta_sk} skills + ${meta_ag} agents"
|
|
85
|
+
count_check "fh-commons plugin.json" plugins/fh-commons/.claude-plugin/plugin.json "${com_sk} skills"
|
|
86
|
+
count_check "marketplace.json fh-meta" .claude-plugin/marketplace.json "${meta_sk} skills + ${meta_ag} agents"
|
|
87
|
+
count_check "README header" README.md "${total_sk} skills · ${total_ag} agents"
|
|
88
|
+
count_check "local_fh_context fh-meta" templates/local_fh_context.md "(fh-meta, ${meta_sk})"
|
|
89
|
+
|
|
90
|
+
if [ "$fail" -ne 0 ]; then
|
|
91
|
+
echo "COUNT-CHECK: FAIL"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
echo "COUNT-CHECK: PASS (mode=$MODE)"
|
|
95
|
+
exit 0
|
package/scripts/selfcheck.sh
CHANGED
|
@@ -25,6 +25,11 @@ for f in bin/*.js; do
|
|
|
25
25
|
check "node --check $f" node --check "$f"
|
|
26
26
|
done
|
|
27
27
|
|
|
28
|
+
# Codex adapter drift: the thin Codex runtime must keep reading canonical FH
|
|
29
|
+
# skill/agent surfaces without silently accepting Claude-native primitives as
|
|
30
|
+
# Codex-native.
|
|
31
|
+
check "fh-codex-doctor --strict" bash -c 'node bin/fh-codex-doctor.js --strict >/dev/null'
|
|
32
|
+
|
|
28
33
|
# Bash surface: npm-shipped scripts + local bin wrappers + gate-chain infra
|
|
29
34
|
for f in scripts/*.sh bin/fh-gate bin/fh-run bin/fh-goal \
|
|
30
35
|
templates/regression_guard.sh templates/temper_check.sh templates/predelete_check.sh templates/.git-hooks/pre-commit; do
|
|
@@ -43,26 +48,28 @@ if ! bash scripts/count_check.sh; then
|
|
|
43
48
|
fail=1
|
|
44
49
|
fi
|
|
45
50
|
|
|
46
|
-
# Referenced-path existence
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
# Referenced-path existence is a source-tree check. The npm package intentionally
|
|
52
|
+
# ships a narrower runtime surface, so package-mode selfcheck skips this section.
|
|
53
|
+
if [ -d ".claude/rules" ]; then
|
|
54
|
+
# Backtick-quoted repo-relative file refs in the always-loaded governance surface
|
|
55
|
+
# (CLAUDE.md + .claude/rules/*.md) must exist. Phantom-reference class recurred
|
|
56
|
+
# N>=3 in the 2026-06-11 audit window — instrument-not-habit.
|
|
57
|
+
while IFS= read -r p; do
|
|
58
|
+
if git check-ignore -q "$p" 2>/dev/null; then
|
|
59
|
+
echo "SKIP ref-path (gitignored): $p"
|
|
60
|
+
elif [ -f "$p" ]; then
|
|
61
|
+
echo "PASS ref-path: $p"
|
|
62
|
+
else
|
|
63
|
+
echo "FAIL ref-path: $p — referenced in CLAUDE.md/.claude/rules but missing"
|
|
64
|
+
fail=1
|
|
65
|
+
fi
|
|
66
|
+
done < <(grep -hoE '\`[^\` ]+\`' CLAUDE.md .claude/rules/*.md 2>/dev/null \
|
|
67
|
+
| sed 's/\`//g' \
|
|
68
|
+
| grep -E '^(knowledge|templates|scripts|docs|plugins|\.claude)/[^*{}<>$]+\.(md|sh|ya?ml|jsonc|json)$' \
|
|
69
|
+
| sort -u)
|
|
70
|
+
else
|
|
71
|
+
echo "SKIP ref-path (package mode: .claude/rules absent)"
|
|
72
|
+
fi
|
|
66
73
|
|
|
67
74
|
if [ "$fail" -ne 0 ]; then
|
|
68
75
|
echo "SELFCHECK: FAIL"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Session Start
|
|
4
|
+
|
|
5
|
+
When a user starts a session with greetings like "hello", "let's start", "resume", "continuing from where we left off", or says "read root memory", **both layers must activate**:
|
|
6
|
+
|
|
7
|
+
### Layer A — Auto read (4 steps required)
|
|
8
|
+
|
|
9
|
+
1. **Read CATALOG.md** — `~/projects/forge-harness/CATALOG.md` (recent work context + latest meta cwd work cross-link)
|
|
10
|
+
2. **Read latest session file** — `~/projects/forge-harness/tracks/{project}/` most recent mtime item (last work on domain + next round reverse-injection intent persistence location / use `ls -lat` or `find -mtime`)
|
|
11
|
+
3. **Check MEMORY.md next-session trigger** — if project memory `MEMORY.md` auto-load is truncated, explicitly Read to supplement the next-session trigger section
|
|
12
|
+
4. **Check todo/plan files if present** — `*todo*`/`*plan*` pattern (supplementary materials)
|
|
13
|
+
5. **Search for duplicate installs in same root** — `ls ../ | grep -iE '(harness|forge)'` to catch sibling assets in parent directory. If found, report to user + delegate branching decision (use existing install / proceed with new / archive then proceed)
|
|
14
|
+
|
|
15
|
+
### Layer B — Proactive initiative (active onboarding 5-skill cascade)
|
|
16
|
+
|
|
17
|
+
After Layer A completes, **when the user enters a task**, activate AI proactive initiative mode:
|
|
18
|
+
|
|
19
|
+
1. **Auto-initiative (1-line question)** — *"What task/project would you like to start? (e.g., 'Spring Boot API development', 'React component refactoring', 'continue existing [X] track')"* (if active track exists: *"Would you like to continue active track [X], or enter a new task?"*)
|
|
20
|
+
2. **5-skill cascade** — `plugin-recommender` (internal GHE → external → built-in candidates) → `cross-ecosystem-synergy-detection` (synergy grade table) → `.claudeignore` standard initiative (`cp templates/.claudeignore`) → model switching guidance (default `/model sonnet` — FH dispatches floored skills/agents at higher tiers itself; pin a stronger model for harness-editing sessions, or when the Field Depth-Escalation Notice below fires — see README §Model setup) → `verify-bidirectional`·`harvest-loop` natural emergence waiting
|
|
21
|
+
3. **User consent → actual setup** — plugin install / skill pre-activation / `.claudeignore` application / model switch
|
|
22
|
+
4. **Project cwd handover guidance** — *"Setup complete. Move to the project cwd and call `claude` to start working."*
|
|
23
|
+
|
|
24
|
+
**Simplification guard**: When an explicit task utterance is made (e.g., "debug X code"), enter task immediately (skip onboarding). Activates once per session.
|
|
25
|
+
|
|
26
|
+
### Field Depth-Escalation Notice (advisory — once per session)
|
|
27
|
+
|
|
28
|
+
The Sonnet default covers routine field work because FH dispatches floored skills/agents at higher
|
|
29
|
+
tiers itself. But when **main-thread development visibly strains the session tier**, surface a
|
|
30
|
+
one-line escalation proposal — do not leave it to recall:
|
|
31
|
+
|
|
32
|
+
**Triggers** (any one): the same problem survives 2–3 correction loops · the work enters
|
|
33
|
+
architecture/design reasoning that cannot be decomposed into a dispatchable unit · the user
|
|
34
|
+
signals being stuck ("keeps failing", "why is this still wrong").
|
|
35
|
+
|
|
36
|
+
**Two-step ladder** (propose the cheaper rung first):
|
|
37
|
+
1. **Opus dispatch (sidecar)** — if the heavy reasoning packages into a unit (a design review, a
|
|
38
|
+
root-cause hunt, an adversarial pass), propose dispatching it to an Opus agent: the session
|
|
39
|
+
stays on Sonnet, cost stays local to the unit.
|
|
40
|
+
2. **Session pin** — if the work is inherently main-thread (iterative dialogue design, repeated
|
|
41
|
+
whole-context reasoning), propose: *"This work demands session-level design depth — pinning
|
|
42
|
+
`/model opus` is recommended. Proceeding as-is also works: dispatches still cover floored units."*
|
|
43
|
+
3. **No higher tier available** — common in metered API routing (a Bedrock-style Sonnet-only
|
|
44
|
+
deployment) or alternative runtimes (Hermes / OpenCode-class) that don't offer higher Claude
|
|
45
|
+
tiers: skip the proposal, proceed at the available tier, and **flag depth-sensitive
|
|
46
|
+
deliverables with an explicit below-floor limitation note** (F2 semantics — tier-floor
|
|
47
|
+
resolution, `multi_model_sidecar_strategy.md §Tier-floor`). Silent proceeding is the failure
|
|
48
|
+
mode this rung exists to prevent; the note makes the deliverable a re-review candidate when a
|
|
49
|
+
floor tier becomes reachable.
|
|
50
|
+
|
|
51
|
+
**Guards** (mirrors the hub's Mode D Model Notice): once per session · advisory only — **never
|
|
52
|
+
switch the session model autonomously** (human override is inviolable) · sessions where nothing
|
|
53
|
+
strains never see it — the Sonnet default stays friction-free.
|
|
54
|
+
|
|
55
|
+
**Basis**: Meta-harness mission *"easy and convenient + no setup burden + token savings"* direct implementation mechanism. Natural hub/action-leader division (single trigger in meta-harness cwd → handover to action-leader cwd).
|
|
56
|
+
|
|
57
|
+
**3 usage modes — "don't block those who come, don't stop those who leave"** (meta-harness operating philosophy):
|
|
58
|
+
- **Mode A (standard)**: meta-harness cwd setup → handover to separate project cwd (4 steps above)
|
|
59
|
+
- **Mode B (resident)**: create **separate project directory** within the forge-harness install environment and work there. Keep the forge-harness directory itself as reference only — use `.gitignore` to block forge-harness assets from mixing into the project
|
|
60
|
+
- **Mode C (plugin/skill only)**: install only plugins/skills without going through forge-harness (available via marketplace without cloning). Skill output accumulates as history within the user's own project. No automatic signals from the forge-harness side expected — indirect contribution depends on user's active communication (issues · PR · channels)
|
|
61
|
+
|
|
62
|
+
If the user explicitly states a mode, immediately guide that mode. Do not force standard mode. Do not accumulate personal work artifacts in the forge-harness directory itself (protect reference asset identity).
|
|
63
|
+
|
|
64
|
+
## Asset Synergy Branching Decision (meta vs. action-leader)
|
|
65
|
+
|
|
66
|
+
When persisting new assets (memory · feedback · patterns · rules) during a session, asset location determination is required:
|
|
67
|
+
|
|
68
|
+
| Location | Nature | Examples |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| **Meta-harness side seed** | Useful as-is when installed in other projects (cross-project synergy) | User baseline propositions, environment common conventions, common action rules for all personas, session operation patterns |
|
|
71
|
+
| **Action-leader project side persistence** | Meaningful only in this project's domain/session context | Domain knowledge, session records, domain-specific validation loop outputs, per-project identity |
|
|
72
|
+
|
|
73
|
+
When the judgment is ambiguous, the AI **states synergy potential first** then delegates the location decision to the user.
|
|
74
|
+
|
|
75
|
+
## Knowledge Hub (forge-harness)
|
|
76
|
+
|
|
77
|
+
Persistent knowledge for this project is stored at `~/projects/forge-harness/`.
|
|
78
|
+
|
|
79
|
+
- **Past work search**: First read `~/projects/forge-harness/CATALOG.md`, identify related files by tags
|
|
80
|
+
- **Learnings/feedback originals**: `~/projects/forge-harness/tracks/{project_name}/`
|
|
81
|
+
- **At session end**: follow the Sync Protocol in `~/projects/forge-harness/CLAUDE.md` to sync
|
|
82
|
+
- **When new patterns are found**: follow the Push Protocol in `~/projects/forge-harness/CLAUDE.md` to feed back
|
|
83
|
+
|
|
84
|
+
<!-- [CUSTOMIZE] Replace {project_name} with the actual project name -->
|
|
85
|
+
<!-- [CUSTOMIZE] If there is a domain knowledge path, add:
|
|
86
|
+
- **Domain knowledge**: `~/projects/forge-harness/knowledge/domain/{domain}/`
|
|
87
|
+
-->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
scope: local-only
|
|
3
|
+
description: forge-harness path and skill list pointer — local only, do not commit to shared repo
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# forge-harness Cross-Context
|
|
7
|
+
|
|
8
|
+
> Install: `cp {FH_ROOT}/templates/local_fh_context.md .claude/rules/local_fh_context.md`
|
|
9
|
+
> Local only: `echo ".claude/rules/local_fh_context.md" >> .git/info/exclude`
|
|
10
|
+
|
|
11
|
+
**forge-harness path**: `~/path/to/forge-harness` (replace with your actual install path)
|
|
12
|
+
**Session records**: `{FH_ROOT}/tracks/_meta/`
|
|
13
|
+
|
|
14
|
+
**Available skills (fh-meta, 33)**: agent-composer · apex-review · asset-placement-gate · auto-decorrelation · context-doctor · contention-layer · corpus-grounding-expander · cross-ecosystem-synergy-detection · deep-clarify · edit-manifest · field-harvest · frontier-digest · goal-quench · harness-doctor · harvest-loop · hub-cc-pr-reviewer · install-doctor · install-wizard · marketplace-gate · memory-hygiene · meta-prompt-builder · persona-roster-expander · phantom-quench · pipeline-conductor · plugin-recommender · prompt-regression · public-surface-audit · return-path-gate · sim-conductor · salience-splitter · steel-quench · verify-bidirectional · video-ingest
|
|
15
|
+
|
|
16
|
+
**Available skills (fh-commons)**: convergence-loop · deliberation · mcp-circuit-breaker · token-budget-gate
|
|
17
|
+
|
|
18
|
+
Skill details available on demand at `{FH_ROOT}/plugins/{plugin}/skills/{skill-name}/SKILL.md`.
|