@chrono-meta/fh-gate 1.1.0 → 1.2.0

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 (69) hide show
  1. package/.claude/agents/challenger.md +169 -0
  2. package/AGENTS.md +160 -0
  3. package/CATALOG.md +256 -0
  4. package/CHEATSHEET.md +367 -0
  5. package/CLAUDE.md +331 -0
  6. package/CONTRIBUTING.md +198 -0
  7. package/LICENSE +21 -0
  8. package/README.md +60 -7
  9. package/bin/fh-goal.js +9 -0
  10. package/bin/fh-run.js +9 -0
  11. package/docs/banner.png +0 -0
  12. package/docs/codex-compat.md +123 -0
  13. package/docs/pillars.svg +70 -0
  14. package/knowledge/shared/harness-core/fh_integration_contract.md +45 -28
  15. package/package.json +31 -6
  16. package/plugins/fh-commons/README.md +37 -0
  17. package/plugins/fh-commons/agents/quench-challenger.md +373 -0
  18. package/plugins/fh-commons/skills/convergence-loop/SKILL.md +155 -0
  19. package/plugins/fh-commons/skills/deliberation/SKILL.md +288 -0
  20. package/plugins/fh-commons/skills/mcp-circuit-breaker/SKILL.md +196 -0
  21. package/plugins/fh-commons/skills/token-budget-gate/SKILL.md +175 -0
  22. package/plugins/fh-meta/agents/fact-checker.md +121 -0
  23. package/plugins/fh-meta/agents/hub-persona-auditor.md +109 -0
  24. package/plugins/fh-meta/agents/persona-innovator.md +195 -0
  25. package/plugins/fh-meta/skills/agent-composer/SKILL.md +461 -0
  26. package/plugins/fh-meta/skills/agent-composer/SKILL_detail.md +464 -0
  27. package/plugins/fh-meta/skills/apex-review/SKILL.md +185 -0
  28. package/plugins/fh-meta/skills/asset-placement-gate/SKILL.md +135 -0
  29. package/plugins/fh-meta/skills/contention-layer/SKILL.md +127 -0
  30. package/plugins/fh-meta/skills/context-bridge-dispatch/SKILL.md +30 -0
  31. package/plugins/fh-meta/skills/context-bridge-dispatch/SKILL_detail.md +144 -0
  32. package/plugins/fh-meta/skills/context-doctor/SKILL.md +341 -0
  33. package/plugins/fh-meta/skills/cross-ecosystem-synergy-detection/SKILL.md +202 -0
  34. package/plugins/fh-meta/skills/deep-clarify/SKILL.md +144 -0
  35. package/plugins/fh-meta/skills/edit-manifest/SKILL.md +210 -0
  36. package/plugins/fh-meta/skills/field-harvest/SKILL.md +384 -0
  37. package/plugins/fh-meta/skills/frontier-digest/SKILL.md +272 -0
  38. package/plugins/fh-meta/skills/goal-quench/SKILL.md +509 -0
  39. package/plugins/fh-meta/skills/harness-doctor/SKILL.md +277 -0
  40. package/plugins/fh-meta/skills/harness-doctor/SKILL_detail.md +484 -0
  41. package/plugins/fh-meta/skills/harvest-loop/SKILL.md +231 -0
  42. package/plugins/fh-meta/skills/harvest-loop/SKILL_detail.md +201 -0
  43. package/plugins/fh-meta/skills/hub-cc-pr-reviewer/SKILL.md +129 -0
  44. package/plugins/fh-meta/skills/hub-cc-pr-reviewer/SKILL_detail.md +158 -0
  45. package/plugins/fh-meta/skills/install-doctor/SKILL.md +207 -0
  46. package/plugins/fh-meta/skills/install-wizard/SKILL.md +613 -0
  47. package/plugins/fh-meta/skills/marketplace-gate/SKILL.md +193 -0
  48. package/plugins/fh-meta/skills/memory-hygiene/SKILL.md +143 -0
  49. package/plugins/fh-meta/skills/meta-prompt-builder/SKILL.md +167 -0
  50. package/plugins/fh-meta/skills/meta-prompt-builder/SKILL_detail.md +37 -0
  51. package/plugins/fh-meta/skills/pipeline-conductor/SKILL.md +430 -0
  52. package/plugins/fh-meta/skills/plugin-recommender/SKILL.md +221 -0
  53. package/plugins/fh-meta/skills/plugin-recommender/SKILL_detail.md +220 -0
  54. package/plugins/fh-meta/skills/prompt-regression/SKILL.md +178 -0
  55. package/plugins/fh-meta/skills/public-surface-audit/SKILL.md +224 -0
  56. package/plugins/fh-meta/skills/return-path-gate/SKILL.md +257 -0
  57. package/plugins/fh-meta/skills/self-marketing-lint/SKILL.md +129 -0
  58. package/plugins/fh-meta/skills/sim-conductor/SKILL.md +364 -0
  59. package/plugins/fh-meta/skills/sim-conductor/SKILL_detail.md +337 -0
  60. package/plugins/fh-meta/skills/skill-splitter/SKILL.md +126 -0
  61. package/plugins/fh-meta/skills/skill-splitter/SKILL_detail.md +185 -0
  62. package/plugins/fh-meta/skills/source-grounding-audit/SKILL.md +230 -0
  63. package/plugins/fh-meta/skills/source-grounding-audit/SKILL_detail.md +182 -0
  64. package/plugins/fh-meta/skills/steel-quench/SKILL.md +226 -0
  65. package/plugins/fh-meta/skills/steel-quench/SKILL_detail.md +453 -0
  66. package/plugins/fh-meta/skills/verify-bidirectional/SKILL.md +238 -0
  67. package/scripts/fh-gate.sh +175 -40
  68. package/scripts/fh-goal.sh +182 -0
  69. package/scripts/fh-run.sh +269 -0
@@ -0,0 +1,220 @@
1
+ ---
2
+ name: plugin-recommender-detail
3
+ description: Detail reference for plugin-recommender — bash discovery scripts, install procedures, recommendation examples. Load when executing specific steps.
4
+ load: on-demand
5
+ ---
6
+
7
+ # plugin-recommender — Detail Reference
8
+
9
+ ## §Discovery-Bash
10
+
11
+ ### Step 0 — GitHub Auth Check Commands
12
+
13
+ **Check command (run before Step 2 search):**
14
+ ```bash
15
+ gh auth status
16
+ ```
17
+
18
+ **Internal GHE unauthenticated — PAT setup:**
19
+ ```bash
20
+ # 1. Generate PAT at https://<your-ghe-url>/settings/tokens
21
+ # Scopes: repo, read:org (minimum)
22
+
23
+ # 2. Save to gh CLI
24
+ gh auth login --hostname <your-ghe-url>
25
+ # Prompt: Select HTTPS → Paste an authentication token → enter token
26
+
27
+ # 3. Verify
28
+ GH_HOST=<your-ghe-url> gh api /user --jq '.login'
29
+ ```
30
+
31
+ **External GitHub unauthenticated — PAT setup:**
32
+ ```bash
33
+ # 1. Generate PAT at https://github.com/settings/tokens
34
+ # Scopes: repo, read:org
35
+
36
+ # 2. Save to gh CLI
37
+ gh auth login --hostname github.com
38
+ # (or default: gh auth login)
39
+ ```
40
+
41
+ **Search call host branching:**
42
+ ```bash
43
+ # Internal GHE search
44
+ GH_HOST=<your-ghe-url> gh api ...
45
+ # or
46
+ gh search repos --owner <your-ghe-org> --hostname <your-ghe-url> [keywords]
47
+
48
+ # External GitHub search
49
+ gh search repos [keywords] # default host
50
+ ```
51
+
52
+ **External user Step 0 skip branch:**
53
+ ```bash
54
+ # External user Step 0 replacement (no internal GHE access)
55
+ gh auth status # default host (github.com) only
56
+ # Authenticated → proceed to Step 1 immediately
57
+ # Unauthenticated → guide github.com PAT generation above
58
+ ```
59
+
60
+ **Claude Code marketplace search:**
61
+ ```bash
62
+ claude mcp search [capability-keyword]
63
+ ```
64
+
65
+ **Codex marketplace search:**
66
+ ```bash
67
+ npx @openai/codex list-agents [capability-keyword]
68
+ ```
69
+
70
+ **npm ecosystem search (scoped packages):**
71
+ ```bash
72
+ npm search @chrono-meta [keyword]
73
+ npm search @anthropic [keyword]
74
+ ```
75
+
76
+ ---
77
+
78
+ ## §Install-Procedure
79
+
80
+ ### Step 5 — Full Install and Configuration Details
81
+
82
+ #### 5-0. Pre-install Duplicate Detection
83
+
84
+ ```bash
85
+ claude plugin list
86
+ ```
87
+
88
+ Three things to verify:
89
+ - **Manual install status**: If target plugin name exists in output → reinstall unnecessary
90
+ - **Repo-level activation**: If plugin is in `.claude/settings.json` `enabledPlugins` → already active
91
+ - **Same-name different-function conflict**: Same name but different origin/function → conflict handling below
92
+
93
+ **Same-name Conflict Handling procedure:**
94
+
95
+ 1. Compare existing skill description vs recommended skill description
96
+ 2. **Feature match** → report "Equivalent feature already installed" + skip reinstall
97
+ 3. **Feature mismatch** → issue conflict warning:
98
+ ```
99
+ ⚠️ Name conflict: `<skill-name>` is already installed but has different functionality.
100
+
101
+ Currently installed: <summary of existing skill description>
102
+ Recommendation target: <summary of new skill description>
103
+
104
+ Options:
105
+ A. Keep existing (skip install)
106
+ B. Install with namespace qualifier — e.g., `fh-<skill-name>`
107
+ C. Remove existing and install new (⚠️ existing skill will be removed)
108
+ ```
109
+ 4. If user selects Option B: guide adding prefix to `name` field in plugin.json + present modification path
110
+
111
+ If either duplicate condition met → skip install → report "Already active" → proceed to Step 5-3 config only.
112
+
113
+ #### 5-1 through 5-3. Install Steps
114
+
115
+ 1. Confirm intent: "Would you like to install the `[plugin-name]` plugin?"
116
+ 2. On agreement:
117
+ ```bash
118
+ claude plugin marketplace add [plugin-name]
119
+ claude plugin install [plugin-name]
120
+ ```
121
+ 3. Post-install initial configuration guidance:
122
+ - **API token input**: Guide token generation path for external service APIs (Jira/Confluence/Slack — specify each service's token page URL + env var or plugin config storage location)
123
+ - **MCP connection**: If plugin uses MCP server, guide auto-update of `.mcp.json` or `claude mcp add` command
124
+ - **Verify**: `claude plugin list` or `/plugin` UI + recommend first-call dry-run
125
+
126
+ #### 5-B. External Asset Migration Path (when non-plugin asset is found)
127
+
128
+ Activation condition: Step 3 found a promising external asset lacking `plugin.json` or `claude plugin install` support — install not possible but pattern has value.
129
+
130
+ **5-B-1. Migration Suitability Assessment (quick 3-criteria check):**
131
+
132
+ | Criteria | OK | NG |
133
+ |---|---|---|
134
+ | **Single purpose** | Clearly performs 1 task | Complex framework/SDK level |
135
+ | **Dependency complexity** | Standard CLI tools only (bash, gh, grep etc.) | Requires custom runtime/database |
136
+ | **FH gap coverage** | No similar skill currently in FH | Existing skill covers 95%+ |
137
+
138
+ All 3 OK → recommend migration. Any NG → report "Recommend referencing rather than installing" then guide Step 2 [Priority 2.5] contribution path.
139
+
140
+ **5-B-2. SKILL.md Conversion Template:**
141
+
142
+ ```markdown
143
+ ---
144
+ name: {1-3 words for the external asset's core action}
145
+ description: {one sentence, plain text only — first line is the core spec}
146
+ user-invocable: true
147
+ allowed-tools: ["Read", "Bash", "Grep"] # only actually needed tools
148
+ model: sonnet
149
+ ---
150
+
151
+ # {name} — {one-line description}
152
+
153
+ ## Activation Triggers
154
+ - When user says "{core action}"
155
+
156
+ ## Execution Steps
157
+
158
+ ### Step 1. ...
159
+ ### Step 2. ...
160
+ ```
161
+
162
+ Conversion checklist:
163
+ - [ ] description first line = core spec (no marketing language)
164
+ - [ ] allowed-tools = only actually called tools (no over-declaration)
165
+ - [ ] External asset original URL → explicitly stated in `## Source` section (license check mandatory)
166
+
167
+ **5-B-3. Migration Location Guidance:**
168
+
169
+ | Purpose | Path | Notes |
170
+ |---|---|---|
171
+ | FH official skill (org-wide distribution) | `plugins/fh-meta/skills/{name}/SKILL.md` | PR mandatory — must pass team review |
172
+ | Local experiment (own environment only) | `.claude/rules/{name}.md` | No plugin install needed |
173
+ | Mode D standalone deployment | `.claude/agents/{name}.md` | Only when operating as agent form |
174
+
175
+ > FH official skill inclusion criteria: recommend PR after confirming 2+ actual uses (simplification guard — immediate inclusion after 1 experiment is prohibited).
176
+
177
+ ---
178
+
179
+ ## §Examples
180
+
181
+ ### Recommendation Table — Output Example
182
+
183
+ Full format with Tier + Platform columns:
184
+
185
+ | Rank | Plugin Name | Tier | Platform | Recommendation Reason | Key Features | Synergy Effect |
186
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
187
+ | **1** | `jira-automator` | Tier 1 | CC marketplace | Fully satisfies Jira ticket create/modify/query. Production usage evidence (5k+ installs). | Ticket creation, status change, comment addition | ★★★ (auto-links docs when used with `confluence-linker`) |
188
+ | **2** | `agile-sprint-board` | Tier 2 | GHE | Specialized for Jira-integrated sprint board visualization. Marketplace-listed, no benchmark data. | Sprint visualization, burndown chart | ★ (standalone use) |
189
+ | **3** | `issue-tracker-cli` | Tier 3 | GitHub only | Repo-only tool, no marketplace listing. Covers edge case not in Tier 1/2 options. | Bulk status updates via CLI | ★ (standalone use) |
190
+
191
+ ### Persona Discovery (sim-conductor chain) — Return Example
192
+
193
+ ```
194
+ plugin-recommender result to sim-conductor:
195
+ Searched: CC marketplace, Codex marketplace, FH native
196
+ Found:
197
+ - deep-insight (Tier 1, CC marketplace) — adversarial reviewer persona
198
+ - persona-devil-advocate (Tier 1, FH native, already installed)
199
+ Installed: deep-insight
200
+ Available personas: [devil-advocate, innovator, deep-insight, conservative-critic]
201
+ → Return control to sim-conductor
202
+ ```
203
+
204
+ ### Quality Tier Assignment — Walk-through Example
205
+
206
+ Candidate: `@anthropic/code-review-agent`
207
+ - Published benchmark: accuracy 94% on HumanEval — **High** signal present
208
+ - GitHub stars: 2,400 — **Medium** signal present
209
+ - CC marketplace listing confirmed — **Medium** signal present
210
+ - Not FH-reviewed — no High signal from community
211
+
212
+ Result: 1 High + 2 Medium → **Tier 1**
213
+
214
+ Candidate: `random-org/bash-linter-plugin`
215
+ - No benchmark data
216
+ - GitHub stars: 45 (below 100 threshold)
217
+ - Not on any marketplace
218
+ - Unknown author
219
+
220
+ Result: no signals → **Tier 3** (source-available, GitHub only)
@@ -0,0 +1,178 @@
1
+ ---
2
+ name: prompt-regression
3
+ description: Detects harness regressions by running standard prompt probes after rule/skill changes and comparing outputs against saved baselines. Triggers on "prompt regression", "did my changes break anything", "regression check", "test harness changes".
4
+ user-invocable: true
5
+ allowed-tools: ["Read", "Bash", "Glob", "Grep"]
6
+ model: sonnet
7
+ complexity_routing:
8
+ base: sonnet
9
+ high: opus
10
+ escalate_when:
11
+ - full_suite
12
+ - cross_skill_impact
13
+ ---
14
+
15
+ # prompt-regression — Harness Regression Detection
16
+
17
+ After CLAUDE.md edits, rule changes, or new skill additions, harness behavior can silently regress. This skill runs a lightweight probe suite against the changed assets and compares outputs against saved baselines to surface regressions before they reach production.
18
+
19
+ > **Scope distinction**
20
+ > - harness-doctor: structural completeness (files, links, drift)
21
+ > - prompt-regression: **behavioral correctness** — did the change alter expected AI response patterns?
22
+
23
+ ---
24
+
25
+ ## Triggers
26
+
27
+ - `/prompt-regression`
28
+ - "prompt regression", "regression check", "regression test"
29
+ - "did my rule change break anything", "test harness changes", "verify harness behavior", "make sure my edit didn't change behavior"
30
+ - After significant CLAUDE.md edits or new skill commits
31
+
32
+ ---
33
+
34
+ ## Execution Steps
35
+
36
+ ### Step 1. Identify Changed Assets
37
+
38
+ ```bash
39
+ # What changed since last commit (or last N commits)
40
+ git diff HEAD~1 --name-only -- CLAUDE.md .claude/ plugins/
41
+ ```
42
+
43
+ Classify each changed file:
44
+ - `CLAUDE.md` → **core behavior** (high impact)
45
+ - `.claude/rules/*.md` → **rule layer** (medium impact)
46
+ - `plugins/*/skills/*/SKILL.md` → **skill behavior** (scoped impact)
47
+ - `plugins/*/skills/*/SKILL.md` (trigger phrases changed) → **trigger routing** (high impact)
48
+
49
+ If no changes detected: report "No harness changes since last commit — regression check skipped."
50
+
51
+ ---
52
+
53
+ ### Step 2. Load Probe Suite
54
+
55
+ Check for custom probes:
56
+ ```bash
57
+ ls .claude/regression/probes.md 2>/dev/null || echo "NO_CUSTOM_PROBES"
58
+ ```
59
+
60
+ **If custom probes exist**: load and use them.
61
+
62
+ **If no custom probes**: use the default probe matrix below.
63
+
64
+ #### Default Probe Matrix
65
+
66
+ | Probe ID | Input Pattern | Expected Behavior | Scope |
67
+ |---|---|---|---|
68
+ | `P-GREET-01` | `hi` / `hello` | Active onboarding protocol triggered | CLAUDE.md §Onboarding |
69
+ | `P-TRIGGER-01` | `recommend a plugin` | plugin-recommender proposed | CLAUDE.md §Autonomous |
70
+ | `P-TRIGGER-02` | `context is getting long` | context-doctor proposed | CLAUDE.md §Autonomous |
71
+ | `P-TRIGGER-03` | `harness is complex` | harness-doctor proposed | CLAUDE.md §Autonomous |
72
+ | `P-CHAIN-01` | `/field-harvest` | harvest-loop close-chain referenced (wrap-up deferred to CLAUDE.md session-close chain — field-harvest has no inline sim-conductor gate) | field-harvest SKILL.md |
73
+ | `P-CHAIN-02` | `/apex-review` | Conditional verdict present (apex-review vocabulary: "Conditional" / "Conditionally passed") | apex-review SKILL.md |
74
+ | `P-GATE-01` | new skill commit | New Skill Pre-Commit Gate (5 items) invoked | CLAUDE.md §Gate |
75
+ | `P-CLOSE-01` | `wrap up` / `good work` | Session close chain (4-step) triggered | CLAUDE.md §Wrap-up |
76
+
77
+ ---
78
+
79
+ ### Step 3. Map Changes → Affected Probes
80
+
81
+ | Changed File | Affected Probes |
82
+ |---|---|
83
+ | `CLAUDE.md` §Onboarding | P-GREET-01 |
84
+ | `CLAUDE.md` §Autonomous Initiative | P-TRIGGER-* |
85
+ | `CLAUDE.md` §Wrap-up | P-CLOSE-01 |
86
+ | `CLAUDE.md` §New Skill Gate | P-GATE-01 |
87
+ | `plugins/fh-meta/skills/*/SKILL.md` | P-CHAIN-* matching skill |
88
+
89
+ If change scope is `CLAUDE.md` core (10+ lines changed): run **full suite** (all probes).
90
+
91
+ ---
92
+
93
+ ### Step 4. Run Affected Probes
94
+
95
+ For each affected probe, evaluate:
96
+
97
+ **4-a. Trigger routing check** — Does the trigger phrase still map to the expected skill/behavior?
98
+ - Read the changed file
99
+ - Locate trigger section
100
+ - Confirm the probe's input pattern still appears in the trigger list
101
+
102
+ **4-b. Chain integrity check** — Are mandatory chains still present?
103
+ - For skill chains: confirm `→ chain:` or `Mandatory:` gate lines exist
104
+ - For session close chain: confirm all 4 steps in CLAUDE.md §Wrap-up
105
+
106
+ **4-c. Gate presence check** — Are gate conditions still enforced?
107
+ - Pre-commit gate: confirm all 5 items present in CLAUDE.md
108
+ - Conditional-pass gate: confirm `CONDITIONAL_PASS` logic in affected SKILL.md
109
+
110
+ Output per probe:
111
+ ```
112
+ [PASS] P-TRIGGER-01 — plugin-recommender trigger phrase found in CLAUDE.md
113
+ [FAIL] P-CHAIN-01 — field-harvest SKILL.md no longer references the harvest-loop close chain after edit
114
+ [SKIP] P-GREET-01 — §Onboarding not in changed files
115
+ ```
116
+
117
+ ---
118
+
119
+ ### Step 5. Regression Report
120
+
121
+ ```
122
+ ## Prompt-Regression Report — YYYY-MM-DD
123
+
124
+ ### Changed Assets
125
+ - CLAUDE.md (§Autonomous Initiative — 3 trigger phrases modified)
126
+ - plugins/fh-meta/skills/field-harvest/SKILL.md
127
+
128
+ ### Probes Run: 4 | Pass: 3 | Fail: 1 | Skip: 4
129
+
130
+ ### FAIL Details
131
+ | Probe | Location | Finding | Fix |
132
+ |---|---|---|---|
133
+ | P-CHAIN-01 | field-harvest SKILL.md | harvest-loop close-chain reference removed by edit | Restore the harvest-loop chain reference |
134
+
135
+ ### Verdict
136
+ ⚠️ REGRESSION DETECTED — 1 probe failed. Fix required before merge.
137
+ ```
138
+
139
+ If all probes pass:
140
+ ```
141
+ ✅ NO REGRESSION — All N probes passed. Safe to merge.
142
+ ```
143
+
144
+ ---
145
+
146
+ ### Step 6. Baseline Update (on explicit user approval)
147
+
148
+ After a deliberate behavior change (not a regression — an intentional improvement), update the baseline:
149
+
150
+ ```bash
151
+ # Baseline stored as markdown in .claude/regression/
152
+ mkdir -p .claude/regression
153
+ # Write updated probe expectations
154
+ ```
155
+
156
+ Prompt user: *"Probe P-CHAIN-01 now expects the new gate format. Update baseline? (y/n)"*
157
+
158
+ Only update on explicit `y` — never auto-update.
159
+
160
+ ---
161
+
162
+ ## Done When
163
+
164
+ - All affected probes are evaluated (PASS / FAIL / SKIP)
165
+ - Regression report is output with clear PASS/FAIL verdict
166
+ - If FAIL: specific file + line fix is recommended
167
+ - Baseline updated only on explicit user approval
168
+
169
+ ---
170
+
171
+ ## Chains
172
+
173
+ **Upstream** (runs before this skill):
174
+ - Automatically triggered after significant harness commits (Step 1 detects via git diff)
175
+
176
+ **Downstream** (runs after FAIL verdict):
177
+ - → `harness-doctor` for structural fixes if L1/L2 issues found
178
+ - → `verify-bidirectional` to confirm fix resolved the regression
@@ -0,0 +1,224 @@
1
+ ---
2
+ name: public-surface-audit
3
+ description: >-
4
+ Scans git-tracked (public) files for operator-private tokens that should live only in gitignored files — real usernames, absolute home paths, companion-store names, company asset names. Reports file:line + matched token + severity, so a public/private split stays clean before publish. Triggered by "public surface audit", "did I leak anything", "check tracked files for private tokens", "private token scan", "public-surface-audit".
5
+ user-invocable: true
6
+ allowed-tools: ["Read", "Bash", "Grep", "Glob"]
7
+ model: sonnet
8
+ category: Composability Gate
9
+ ---
10
+
11
+ # public-surface-audit — Operator-Private Token Leak Scan
12
+
13
+ Scans the git-tracked file set (the public surface) for operator-private tokens that were supposed
14
+ to stay in gitignored files (e.g. `CLAUDE.local.md`, companion store). After a public/private split,
15
+ a front-door fix is not enough — a leaked username or absolute home path anywhere in the tracked set
16
+ breaks the "public repo = model-agnostic methodology only" invariant.
17
+
18
+ > While `marketplace-gate` Check 5 answers "is this repo broadly safe to publish?" (API keys, internal
19
+ > domains, license), `public-surface-audit` answers a narrower question: "did any operator-private
20
+ > token survive the public/private split into a tracked file?" It scans `git ls-files` only — gitignored
21
+ > files like `CLAUDE.local.md` are intentionally out of scope (they are the *correct* home for these tokens).
22
+
23
+ ## Triggers
24
+
25
+ - `/public-surface-audit`
26
+ - `/public-surface-audit --target <repo path>`
27
+ - "Did I leak anything into the public repo?", "public surface audit", "private token scan"
28
+ - "Check tracked files for private tokens", "is my public/private split clean?"
29
+ - "Did any operator-private token survive into a tracked file?", "scan before publish"
30
+
31
+ ---
32
+
33
+ ## Scope — Tracked Files Only
34
+
35
+ This skill scans **only `git ls-files`** (committed/staged tracked files). Gitignored files are
36
+ deliberately excluded — `CLAUDE.local.md`, the companion store, and local session data are the
37
+ *correct* home for operator-private tokens, so finding them there is not a leak.
38
+
39
+ ```bash
40
+ REPO_PATH="${ARGUMENTS#--target }"
41
+ REPO_PATH="${REPO_PATH:-$(pwd)}"
42
+ git -C "$REPO_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
43
+ || { echo "Not a git repo — public-surface-audit scans git-tracked files only. Aborting."; exit 1; }
44
+ echo "Target: $REPO_PATH"
45
+ git -C "$REPO_PATH" ls-files | wc -l | xargs echo "Tracked files:"
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Step 1. Pattern List (configurable)
51
+
52
+ The patterns **are themselves operator-private** — your real username and employer name must not be
53
+ hardcoded *here*, on the public surface, or this skill would leak exactly what it hunts. So the literal
54
+ values live in a **gitignored source you supply** (`.claude/rules/.public-surface-patterns`, or a
55
+ section of `CLAUDE.local.md`) — one `severity<TAB>regex` per line. This SKILL.md carries only
56
+ placeholders; the scan reads the gitignored file, never literals from this table. The skill dogfoods
57
+ its own rule.
58
+
59
+ | # | Token class | Severity | Placeholder (real value goes in the gitignored source) | Why private |
60
+ |:-:|---|:-:|---|---|
61
+ | 1 | Real username | HIGH | `<your-unix-username>` | Personal identity — must not appear on public surface |
62
+ | 2 | Company / employer asset name | HIGH | `<company-asset>` (alternation OK) | Company-confidential, leak-forbidden |
63
+ | 3 | Operator absolute home path | MED | `/Users/[a-z0-9_-]+/` (generic — carries no literal name) | Machine-bound, leaks username + local layout |
64
+ | 4 | Companion-store name | LOW | `<companion-store-name>` | Private companion store — methodology should not name it |
65
+ | 5 | Operator-private script / handoff name | LOW | `<private-script>`, `<private-dir>/` | Operator-specific wiring, belongs in `CLAUDE.local.md` |
66
+
67
+ **Severity meaning**:
68
+ - **HIGH** — real name or company asset. A leak is a confidentiality / identity exposure. Block publish.
69
+ - **MED** — absolute home path. Leaks username + local filesystem layout; also a portability bug.
70
+ - **LOW** — companion-store / private-wiring name. Methodology should be model-agnostic; naming a private
71
+ store is drift, not a confidentiality breach.
72
+
73
+ > **Setup**: put your real values in the gitignored pattern source (one `severity<TAB>regex` per line);
74
+ > the scan reads that file, never literals from this SKILL.md. If the source is **absent**, the scan
75
+ > reports **NOT CONFIGURED** — *not* CLEAN. A missing pattern file must never masquerade as a clean bill
76
+ > of health (that would be a silent failure: "nothing scanned" misread as "nothing leaked"). To declare
77
+ > "I genuinely have no private tokens", create the file **empty** — an empty file is an explicit CLEAN,
78
+ > an absent file is unconfigured.
79
+
80
+ ---
81
+
82
+ ## Step 2. Allowlist (legitimate references)
83
+
84
+ Some tracked files legitimately reference otherwise-private tokens — the scan must not flag these as
85
+ leaks. Maintain an allowlist of `file path :: token` pairs. A match is suppressed only when **both**
86
+ the file and the token are on the allowlist row.
87
+
88
+ | Tracked file | Allowed tokens | Reason |
89
+ |---|---|---|
90
+ | `.gitignore` | companion-store name, sync-script name | Must name what it ignores |
91
+ | your sync script (e.g. `scripts/<sync-script>`) | companion-store name, operator-dir names, home path | The sync script's whole job is the companion store |
92
+ | an install-template rules file | home path, companion-store name | Install template — the install path is its content |
93
+ | a doc describing the companion-store *pattern* | the `*-be` pattern (no literal store name) | Documents the pattern generically |
94
+
95
+ **Allowlist rule**: a hit on file F matching token T is **suppressed** iff a row exists with file == F
96
+ and T in that row's allowed tokens. Everything else is reported. Keep the allowlist tight — when in
97
+ doubt, report and let the user confirm. Genuinely model-agnostic mentions (the `*-be` companion
98
+ *pattern* without the literal store name) should not require allowlisting because they do not match a
99
+ literal private token.
100
+
101
+ ---
102
+
103
+ ## Step 3. Scan
104
+
105
+ For each pattern in Step 1, grep the tracked set, then drop allowlisted hits.
106
+
107
+ ```bash
108
+ cd "$REPO_PATH" || exit 1
109
+ # Build the tracked-file list once.
110
+ git ls-files > /tmp/_psa_tracked.txt
111
+
112
+ # Load your real patterns from the gitignored source (one "severity<TAB>regex" per line).
113
+ PATTERN_SRC="${PSA_PATTERNS:-.claude/rules/.public-surface-patterns}"
114
+ # Absent file ≠ CLEAN. An absent file is unconfigured (silent-failure risk); an EMPTY file is an
115
+ # explicit "no tokens to protect" → CLEAN. Distinguish the two.
116
+ [ -e "$PATTERN_SRC" ] || { echo "⚪ NOT CONFIGURED: no pattern source at $PATTERN_SRC. Create it (empty = explicit CLEAN) before trusting any verdict. Not scanning."; exit 2; }
117
+
118
+ # One grep pass per pattern row; the regex comes from the file, never hardcoded here.
119
+ while IFS=$'\t' read -r severity regex; do
120
+ [ -z "$regex" ] && continue
121
+ grep -nIE "$regex" $(cat /tmp/_psa_tracked.txt) 2>/dev/null | sed "s/^/[$severity] /"
122
+ done < "$PATTERN_SRC"
123
+ ```
124
+
125
+ For each pattern, run `grep -nIE "<regex>" $(git ls-files)`:
126
+ - `-n` → line numbers (required for `file:line` output)
127
+ - `-I` → skip binary files
128
+ - `-E` → extended regex (alternation in the pattern table)
129
+
130
+ Then remove any hit whose `file` + matched `token` is on the Step 2 allowlist. Do this for **every**
131
+ pattern row before producing the report — do not stop at the first HIT.
132
+
133
+ **Binary / generated carve-out**: `-I` already skips binaries. Additionally note (do not auto-suppress)
134
+ hits inside generated artifacts (e.g. `paper/*.html` exported from a private source) — these are real
135
+ leaks on the public surface and must be reported, but the fix is "regenerate from a sanitized source",
136
+ not "edit the HTML by hand". Flag them with a `(generated artifact)` note.
137
+
138
+ ---
139
+
140
+ ## Step 4. Report
141
+
142
+ ```
143
+ public-surface-audit — Operator-Private Token Scan
144
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
145
+ Target: {REPO_PATH} | Tracked files scanned: {N}
146
+
147
+ 🔴 HIGH ({count})
148
+ {file}:{line} → {matched token} [class: username | company asset]
149
+ 🟠 MED ({count})
150
+ {file}:{line} → {matched token} [class: absolute home path]
151
+ 🟡 LOW ({count})
152
+ {file}:{line} → {matched token} [class: companion-store | private wiring]
153
+
154
+ Allowlist-suppressed: {count} hit(s) (legitimate references — not leaks)
155
+
156
+ Verdict:
157
+ ⚪ NOT CONFIGURED — pattern source absent (nothing scanned — NOT a clean result; set up first)
158
+ 🟢 CLEAN — pattern source present (incl. empty), 0 HIGH + 0 MED + 0 LOW (after allowlist)
159
+ 🟡 REVIEW — 0 HIGH + 0 MED, LOW-only (drift, not a breach)
160
+ 🔴 LEAK — 1+ HIGH or 1+ MED (block publish / fix before commit)
161
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
162
+ ```
163
+
164
+ Per HIGH/MED hit, append a one-line prescription:
165
+ - **HIGH (username/company)** — move the line to `CLAUDE.local.md` (or regenerate the artifact from a
166
+ sanitized source); never edit-in-place if it is a generated file.
167
+ - **MED (absolute path)** — replace with a relative path, a `~`-anchored path, or a `{project}`
168
+ placeholder; absolute home paths are also a portability bug for external clones.
169
+ - **LOW (companion-store/wiring)** — rephrase to the model-agnostic *pattern* (e.g. "a private companion
170
+ store" / "the `*-be` companion pattern") instead of the literal name, unless the file is the
171
+ `.gitignore` / sync script that must name it (allowlist those).
172
+
173
+ **Simplification guard**: 🟢 CLEAN → collapse the report to one line: "public surface clean — 0 private
174
+ tokens in {N} tracked files (X allowlist-suppressed)." Do not print empty severity buckets.
175
+
176
+ ---
177
+
178
+ ## Connected Skills
179
+
180
+ | Situation | Connected skill |
181
+ |---|---|
182
+ | Broader pre-publish repo readiness (README, license, API keys) | `/marketplace-gate` (Check 5 Public Safety is the wide net; this skill is the private-token detail) |
183
+ | A leak is a recurring process gap, not a one-off | log via `field-harvest` → candidate `#rule-candidate` |
184
+ | Where should the leaked content actually live? | `/asset-placement-gate` (hub vs project vs CLAUDE.local.md) |
185
+ | Phantom refs / stale links on the same surface | `/source-grounding-audit` (forward axis — orthogonal to this leak axis) |
186
+
187
+ ---
188
+
189
+ ## External User Environment Adaptation
190
+
191
+ Usable standalone — no hub clone required.
192
+ - **No companion store / no operator-private tokens** → create the pattern source **empty** to declare
193
+ this explicitly; the scan then reports CLEAN. Leaving the file *absent* instead yields NOT CONFIGURED
194
+ (a deliberate distinction — absence is "unknown", not "clean"). The skill is only useful once you have
195
+ a public/private split to protect.
196
+ - **No `.gitignore` allowlist needs** → Step 2 allowlist may be empty; every hit is then reported.
197
+
198
+ ---
199
+
200
+ ## Done When
201
+
202
+ ```
203
+ Step 1 pattern list confirmed (defaults shown / user-adapted)
204
+ + Step 2 allowlist applied
205
+ + Step 3 scan run for every pattern over git ls-files (tracked only — gitignored excluded)
206
+ + Step 4 report output: per-hit file:line + token + severity, plus overall verdict
207
+ + "public-surface-audit Complete" declaration output
208
+ ```
209
+
210
+ Verdict: **CLEAN** (0 tokens after allowlist) | **REVIEW** (LOW-only — drift, prescriptions noted) |
211
+ **LEAK** (1+ HIGH or 1+ MED — block publish, prescriptions attached).
212
+
213
+ ---
214
+
215
+ ## Operating Notes
216
+
217
+ - **Tracked-only is the point**: never scan gitignored files. A token in `CLAUDE.local.md` is correct
218
+ placement, not a leak — scanning it would produce false LEAK verdicts and erode trust in the skill.
219
+ - **Patterns are data, not code**: the Step 1 table is the configurable surface. A user with a different
220
+ username/employer/companion-store edits the table; the scan logic is unchanged.
221
+ - **Generated artifacts are real leaks**: an exported HTML/PDF carrying a username is still a public-surface
222
+ leak even though hand-editing it is wrong — report it, prescribe "regenerate from sanitized source".
223
+ - **Allowlist tight, not loose**: when unsure whether a reference is legitimate, report it. A false LEAK
224
+ the user dismisses is cheaper than a real leak suppressed by an over-broad allowlist.