@ikon85/agent-workflow-kit 0.24.0 → 0.26.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.
- package/.agents/skills/setup-workflow/SKILL.md +31 -5
- package/.agents/skills/setup-workflow/safety-guardrails.md +155 -0
- package/.agents/skills/setup-workflow/workflow-advisories.md +28 -6
- package/.claude/hooks/_hook_utils.py +19 -0
- package/.claude/hooks/_safety_guard.py +24 -0
- package/.claude/hooks/block-bg-double-background.py +30 -0
- package/.claude/hooks/block-npm-install-in-pnpm.py +30 -0
- package/.claude/hooks/block-secrets.py +30 -0
- package/.claude/hooks/convention-drift-hint.py +27 -0
- package/.claude/hooks/grep-shim-guard.py +30 -0
- package/.claude/hooks/loc-offender-forewarn.py +56 -0
- package/.claude/hooks/migration-snapshot-reminder.py +24 -0
- package/.claude/hooks/skill-drift-hint.py +9 -45
- package/.claude/skills/setup-workflow/SKILL.md +31 -5
- package/.claude/skills/setup-workflow/safety-guardrails.md +155 -0
- package/.claude/skills/setup-workflow/workflow-advisories.md +28 -6
- package/README.md +31 -0
- package/agent-workflow-kit.package.json +132 -9
- package/package.json +1 -1
- package/scripts/loc_offender_gate.py +24 -0
- package/scripts/safety-guardrails/core.py +221 -0
- package/scripts/safety-guardrails/search.py +92 -0
- package/scripts/security/audit-gate.mjs +122 -0
- package/scripts/security/ensure-gitleaks.mjs +101 -0
- package/scripts/security/gitleaks-profile.json +14 -0
- package/scripts/security/install-git-hooks.mjs +52 -0
- package/scripts/test_skill_publish_audit.py +15 -0
- package/scripts/workflow-advisories/capabilities.json +33 -0
- package/scripts/workflow-advisories/core.py +100 -0
- package/src/lib/bundle.mjs +18 -0
|
@@ -26,7 +26,7 @@ This is a prompt-driven skill, not a deterministic script. Explore, present what
|
|
|
26
26
|
| `## Agent skills` + `## Prod` in CLAUDE.md **and** AGENTS.md | one-line pointers + deploy target (Sections C/G + Write) |
|
|
27
27
|
| `.github/workflows/agent-workflow-kit-update.yml` | optional tested Kit update pull request for GitHub consumers (Section A2) |
|
|
28
28
|
| `docs/agents/census.md` | optional-census choice, paths, state, and safe disable contract seeded from [census.md](./census.md) (Section A3) |
|
|
29
|
-
| `docs/agents/workflow-capabilities.json` + capability assets | consumer-owned Worktree Lifecycle, Memory Lifecycle,
|
|
29
|
+
| `docs/agents/workflow-capabilities.json` + capability assets | consumer-owned Worktree Lifecycle, Memory Lifecycle, Workflow Advisories, and Safety Guardrails choices (Sections A4–A7) |
|
|
30
30
|
|
|
31
31
|
## Idempotency contract — read before writing anything
|
|
32
32
|
|
|
@@ -57,7 +57,7 @@ Read the current state; don't assume. For every target file, read its first line
|
|
|
57
57
|
- `CONTEXT.md`, `CONTEXT-MAP.md`, `docs/adr/` — domain-doc layout.
|
|
58
58
|
- `docs/agents/`, `docs/agents/skills/`, `docs/conventions/` — prior output of this skill.
|
|
59
59
|
- `docs/agents/census.md`, `.census/profile.json`, `.census/active.json` — an existing census choice or consumer-owned census to adopt.
|
|
60
|
-
- `docs/agents/workflow-capabilities.json`, `.claude/settings.json` — existing capability choices/profile plus Worktree Lifecycle
|
|
60
|
+
- `docs/agents/workflow-capabilities.json`, `.claude/settings.json`, `git config --get core.hooksPath` — existing capability choices/profile plus Worktree Lifecycle, Workflow Advisories, and Safety Guardrails wiring to adopt.
|
|
61
61
|
- `.memory/active/`, `.memory/archive/`, and `.memory/receipts/` — consumer-owned Memory Lifecycle policies or recovery evidence to adopt without normalization.
|
|
62
62
|
- `gh auth status` (if GitHub) — is `gh` authenticated, and with which scopes?
|
|
63
63
|
|
|
@@ -218,6 +218,31 @@ repository?"* Offer exactly **Yes**, **Later**, and **No**.
|
|
|
218
218
|
- **Disable** — remove exact kit-owned commands first, then set `enabled:
|
|
219
219
|
false`; preserve every profile value and unknown key.
|
|
220
220
|
|
|
221
|
+
### 2f. Section A7 — Optional Safety Guardrails
|
|
222
|
+
|
|
223
|
+
> Safety Guardrails is a counted group of seven independently selectable
|
|
224
|
+
> protections: four agent-tool guards and three repository-security
|
|
225
|
+
> capabilities. Setup stages and validates the chosen profile plus wiring
|
|
226
|
+
> before activation; disabled rows remain exact no-ops.
|
|
227
|
+
|
|
228
|
+
Read [safety-guardrails.md](./safety-guardrails.md) in full. Reconcile its
|
|
229
|
+
complete `yes / later / no / existing / disable` matrix. If no choice exists,
|
|
230
|
+
ask: *"Should setup configure the portable Safety Guardrails for this
|
|
231
|
+
repository?"* Offer exactly **Yes**, **Later**, and **No**.
|
|
232
|
+
|
|
233
|
+
- **Yes** — ask which of the seven counted rows to enable, then reconcile only
|
|
234
|
+
`safetyGuardrails`, exact selected Agent-hook commands, and the selected
|
|
235
|
+
native Git-hook path. Report `N of 7 enabled`.
|
|
236
|
+
- **Later / No** — record the choice without Agent- or Git-hook wiring.
|
|
237
|
+
- **Existing** — adopt profile and wiring byte-safely; preserve unknown keys
|
|
238
|
+
and consumer-specific policies.
|
|
239
|
+
- **Disable** — remove only exact kit-owned Agent commands and Git wiring
|
|
240
|
+
first, then set `enabled: false`.
|
|
241
|
+
|
|
242
|
+
Testreporter uses the parity-on profile from the seed. Other consumers are
|
|
243
|
+
opt-in/manual: never copy its pnpm, path, shim, surface, or outage decisions
|
|
244
|
+
without repository evidence and user confirmation.
|
|
245
|
+
|
|
221
246
|
### 3. Section B — Triage labels
|
|
222
247
|
|
|
223
248
|
> When `triage` processes an incoming issue it applies labels (or your tracker's equivalent). It needs strings you've actually configured, or it creates duplicates.
|
|
@@ -305,10 +330,11 @@ request changes a recorded choice.
|
|
|
305
330
|
|
|
306
331
|
For `docs/agents/workflow-capabilities.json`, reconcile only each selected
|
|
307
332
|
capability section. Never replace the whole file: Project Release, Memory
|
|
308
|
-
Lifecycle, Worktree Lifecycle, Workflow Advisories, future sections, and
|
|
333
|
+
Lifecycle, Worktree Lifecycle, Workflow Advisories, Safety Guardrails, future sections, and
|
|
309
334
|
unknown consumer keys share this profile. Apply the transition and hook
|
|
310
|
-
ownership rules from [worktree-lifecycle.md](./worktree-lifecycle.md)
|
|
311
|
-
[workflow-advisories.md](./workflow-advisories.md)
|
|
335
|
+
ownership rules from [worktree-lifecycle.md](./worktree-lifecycle.md),
|
|
336
|
+
[workflow-advisories.md](./workflow-advisories.md), and
|
|
337
|
+
[safety-guardrails.md](./safety-guardrails.md) transactionally.
|
|
312
338
|
|
|
313
339
|
For Memory Lifecycle, use only the deterministic setup helper from Section A5.
|
|
314
340
|
Do not copy templates with shell commands or edit the capability profile by
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Safety Guardrails setup contract
|
|
2
|
+
|
|
3
|
+
Safety Guardrails is a counted, opt-in capability group backed by the
|
|
4
|
+
consumer-owned `docs/agents/workflow-capabilities.json` profile. Its seven
|
|
5
|
+
rows are selected independently: four protect agent tool calls and three
|
|
6
|
+
bootstrap repository security. No repository name, package manager, hook
|
|
7
|
+
surface, threshold, path, or outage policy is inferred from the kit.
|
|
8
|
+
|
|
9
|
+
## Choice matrix
|
|
10
|
+
|
|
11
|
+
| State | Setup action |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `missing` | Ask `yes / later / no`; do not infer or write before the answer. |
|
|
14
|
+
| `yes` | Ask which rows to enable, stage profile plus selected wiring, validate, then activate. |
|
|
15
|
+
| `later` | Record the retryable deferral; do not activate any wiring. |
|
|
16
|
+
| `no` | Record the opt-out; do not activate any wiring. |
|
|
17
|
+
| `existing` | Adopt the consumer profile and existing wiring byte-safely. |
|
|
18
|
+
| `disable` | Remove exact kit-owned Agent and Git wiring first, then set `enabled: false`. |
|
|
19
|
+
|
|
20
|
+
```json safety-guardrails-setup-effects
|
|
21
|
+
[
|
|
22
|
+
{"state":"missing","choice":null,"operations":[]},
|
|
23
|
+
{"state":"yes","choice":"yes","operations":["record-choice","stage-enabled-profile","stage-agent-hook-wiring","stage-git-hook-wiring","activate-staged-profile"]},
|
|
24
|
+
{"state":"later","choice":"later","operations":["record-choice"]},
|
|
25
|
+
{"state":"no","choice":"no","operations":["record-choice"]},
|
|
26
|
+
{"state":"existing","choice":"yes","operations":["adopt-existing"]},
|
|
27
|
+
{"state":"disable","choice":"yes","operations":["remove-agent-hook-wiring","remove-git-hook-wiring","update-profile-disabled"]}
|
|
28
|
+
]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Counted capability map
|
|
32
|
+
|
|
33
|
+
Every historical Safety row maps to one profile decision and one shipped
|
|
34
|
+
artifact. Setup reports the result as `N of 7 enabled`, never as one
|
|
35
|
+
all-or-nothing switch.
|
|
36
|
+
|
|
37
|
+
```json safety-guardrails-capabilities
|
|
38
|
+
[
|
|
39
|
+
{"id":"secrets","profilePath":"safetyGuardrails.secrets.enabled","artifact":".claude/hooks/block-secrets.py"},
|
|
40
|
+
{"id":"packageManager","profilePath":"safetyGuardrails.packageManager.enabled","artifact":".claude/hooks/block-npm-install-in-pnpm.py"},
|
|
41
|
+
{"id":"doubleBackground","profilePath":"safetyGuardrails.doubleBackground.enabled","artifact":".claude/hooks/block-bg-double-background.py"},
|
|
42
|
+
{"id":"searchShim","profilePath":"safetyGuardrails.searchShim.enabled","artifact":".claude/hooks/grep-shim-guard.py"},
|
|
43
|
+
{"id":"gitHooks","profilePath":"safetyGuardrails.repositorySecurity.gitHooks.enabled","artifact":"scripts/security/install-git-hooks.mjs"},
|
|
44
|
+
{"id":"gitleaks","profilePath":"safetyGuardrails.repositorySecurity.gitleaks.enabled","artifact":"scripts/security/ensure-gitleaks.mjs"},
|
|
45
|
+
{"id":"dependencyAudit","profilePath":"safetyGuardrails.repositorySecurity.dependencyAudit.enabled","artifact":"scripts/security/audit-gate.mjs"}
|
|
46
|
+
]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Profile shape
|
|
50
|
+
|
|
51
|
+
Reconcile only `safetyGuardrails`; preserve every sibling section, unknown key,
|
|
52
|
+
and consumer-owned value. The following is the Testreporter parity-on example,
|
|
53
|
+
not a universal default. Other consumers choose each `enabled` value and fill
|
|
54
|
+
only facts proven in their repository.
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"safetyGuardrails": {
|
|
59
|
+
"choice": "yes",
|
|
60
|
+
"enabled": true,
|
|
61
|
+
"secrets": {
|
|
62
|
+
"enabled": true,
|
|
63
|
+
"sensitiveNames": [".env", ".npmrc", "credentials.json"],
|
|
64
|
+
"sensitivePathFragments": ["secrets/", ".ssh/"],
|
|
65
|
+
"safeTemplateSuffixes": [".example", ".sample", ".template", ".dist"]
|
|
66
|
+
},
|
|
67
|
+
"packageManager": {
|
|
68
|
+
"enabled": true,
|
|
69
|
+
"lockfiles": {
|
|
70
|
+
"pnpm-lock.yaml": "pnpm",
|
|
71
|
+
"package-lock.json": "npm",
|
|
72
|
+
"yarn.lock": "yarn",
|
|
73
|
+
"bun.lockb": "bun"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"doubleBackground": {"enabled": true, "surfaces": ["claude"]},
|
|
77
|
+
"searchShim": {
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"detected": true,
|
|
80
|
+
"commandNames": ["grep", "rg"]
|
|
81
|
+
},
|
|
82
|
+
"repositorySecurity": {
|
|
83
|
+
"gitHooks": {"enabled": true, "hooksPath": ".githooks"},
|
|
84
|
+
"gitleaks": {"enabled": true, "required": false},
|
|
85
|
+
"dependencyAudit": {
|
|
86
|
+
"enabled": true,
|
|
87
|
+
"packageManager": "pnpm",
|
|
88
|
+
"outagePolicy": "warn",
|
|
89
|
+
"blockSeverities": ["high", "critical"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
An empty or disabled row is an honest no-op. `searchShim.detected` is a
|
|
97
|
+
consumer fact, not an installation request. `gitleaks.required: false` keeps
|
|
98
|
+
the verified optional provisioner non-blocking when the platform or network is
|
|
99
|
+
unsupported. Dependency-audit outage policy must be explicit.
|
|
100
|
+
|
|
101
|
+
## Agent-hook ownership
|
|
102
|
+
|
|
103
|
+
Wire only enabled rows, using the exact kit-owned commands:
|
|
104
|
+
|
|
105
|
+
- `secrets` — `python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/block-secrets.py"`
|
|
106
|
+
- `packageManager` —
|
|
107
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/block-npm-install-in-pnpm.py"`
|
|
108
|
+
- `doubleBackground` —
|
|
109
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/block-bg-double-background.py"`
|
|
110
|
+
- `searchShim` —
|
|
111
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/grep-shim-guard.py"`
|
|
112
|
+
|
|
113
|
+
All four are PreToolUse adapters. Preserve unrelated matchers and commands in
|
|
114
|
+
`.claude/settings.json`. Disable removes only these exact commands.
|
|
115
|
+
|
|
116
|
+
## Repository wiring
|
|
117
|
+
|
|
118
|
+
When `gitHooks.enabled` is true, run:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
node scripts/security/install-git-hooks.mjs <hooksPath>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
only after confirming the configured directory exists and contains the
|
|
125
|
+
consumer's intended hooks. Never create or replace consumer hook bodies.
|
|
126
|
+
|
|
127
|
+
When `gitleaks.enabled` is true, the pinned profile may be provisioned through
|
|
128
|
+
`scripts/security/ensure-gitleaks.mjs`; checksum mismatch, unsupported platform,
|
|
129
|
+
offline state, and unwritable destination remain distinct visible outcomes.
|
|
130
|
+
Never read a secret file to test the provisioner.
|
|
131
|
+
|
|
132
|
+
When `dependencyAudit.enabled` is true, use
|
|
133
|
+
`scripts/security/audit-gate.mjs` with the configured package manager and
|
|
134
|
+
outage policy. High/Critical findings block; Low/Moderate findings pass.
|
|
135
|
+
|
|
136
|
+
## Transaction and failure contract
|
|
137
|
+
|
|
138
|
+
Prepare the next profile and `.claude/settings.json` in same-directory staging
|
|
139
|
+
files. Validate JSON, all selected artifact paths, the seven-row count, the
|
|
140
|
+
configured Git-hook directory, and package-manager facts before mutation.
|
|
141
|
+
Then:
|
|
142
|
+
|
|
143
|
+
1. reconcile selected Agent commands in the staged settings;
|
|
144
|
+
2. remember the prior `core.hooksPath` and apply the selected Git wiring;
|
|
145
|
+
3. atomically rename staged settings and profile into place;
|
|
146
|
+
4. on any failure, restore the prior Git config and leave active files
|
|
147
|
+
byte-for-byte unchanged.
|
|
148
|
+
|
|
149
|
+
Disable reverses the safety order: remove exact Agent commands and restore or
|
|
150
|
+
unset only the kit-owned Git wiring before committing `enabled: false`.
|
|
151
|
+
Repeated activation with the same choices is byte-idempotent.
|
|
152
|
+
|
|
153
|
+
Setup and verification may inspect paths, profile metadata, command exit
|
|
154
|
+
status, advisory counts, and hashes. They must never read secret contents or
|
|
155
|
+
print environment/config values.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Workflow Advisories setup contract
|
|
2
2
|
|
|
3
3
|
Workflow Advisories is one opt-in capability backed by the consumer-owned
|
|
4
|
-
`docs/agents/workflow-capabilities.json` profile. Enabling it activates
|
|
5
|
-
non-blocking large-read, baseline, pre-refactor,
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
`docs/agents/workflow-capabilities.json` profile. Enabling it activates seven
|
|
5
|
+
non-blocking rows: large-read, baseline, pre-refactor, affected-surface Stop,
|
|
6
|
+
convention freshness, migration-artifact reminder, and LoC forewarning. Every
|
|
7
|
+
threshold, glob, branch rule, source map, command, timeout, and output budget
|
|
8
|
+
stays consumer-owned.
|
|
8
9
|
|
|
9
10
|
## Choice matrix
|
|
10
11
|
|
|
@@ -52,7 +53,20 @@ key. Consumer values are never normalized on adoption.
|
|
|
52
53
|
"timeoutSeconds": 15,
|
|
53
54
|
"outputBudget": 1000
|
|
54
55
|
},
|
|
55
|
-
"stopChecks": {"surfaces": [], "timeoutSeconds": 30, "outputBudget": 1000}
|
|
56
|
+
"stopChecks": {"surfaces": [], "timeoutSeconds": 30, "outputBudget": 1000},
|
|
57
|
+
"freshness": {"documents": [], "outputBudget": 1000},
|
|
58
|
+
"migration": {
|
|
59
|
+
"commandMatchers": [],
|
|
60
|
+
"artifact": "",
|
|
61
|
+
"refreshCommand": [],
|
|
62
|
+
"outputBudget": 500
|
|
63
|
+
},
|
|
64
|
+
"locForewarn": {
|
|
65
|
+
"branchRegex": "^(?:feat|fix)/(\\d+)-",
|
|
66
|
+
"issueCommand": ["gh", "issue", "view", "{issue}", "--json", "body", "-q", ".body"],
|
|
67
|
+
"timeoutSeconds": 5,
|
|
68
|
+
"outputBudget": 500
|
|
69
|
+
}
|
|
56
70
|
}
|
|
57
71
|
}
|
|
58
72
|
```
|
|
@@ -70,6 +84,14 @@ project commands from the tools already present, then asks before activating.
|
|
|
70
84
|
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-refactor-sweep.py"`
|
|
71
85
|
- Stop:
|
|
72
86
|
`"$CLAUDE_PROJECT_DIR/.claude/hooks/typecheck-on-stop.sh"`
|
|
87
|
+
- SessionStart convention freshness:
|
|
88
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/convention-drift-hint.py"`
|
|
89
|
+
- PostToolUse on Bash migration commands:
|
|
90
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/migration-snapshot-reminder.py"`
|
|
91
|
+
- SessionStart LoC forewarning:
|
|
92
|
+
`python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/loc-offender-forewarn.py"`
|
|
73
93
|
|
|
74
94
|
All adapters are non-blocking. A failed or timed-out configured command remains
|
|
75
|
-
visibly failed in hook context; it is never reported as green.
|
|
95
|
+
visibly failed in hook context; it is never reported as green. Issue lookup
|
|
96
|
+
failures silence only the LoC forewarning: the existing pre-push gate remains
|
|
97
|
+
the enforcing authority and stays fail-closed.
|
package/README.md
CHANGED
|
@@ -332,6 +332,37 @@ still reference. Flags: `--force` (overwrite pre-existing files on `init`),
|
|
|
332
332
|
|
|
333
333
|
## Release notes
|
|
334
334
|
|
|
335
|
+
### 0.26.0
|
|
336
|
+
|
|
337
|
+
- added: `.agents/skills/setup-workflow/safety-guardrails.md`
|
|
338
|
+
- added: `.claude/hooks/_safety_guard.py`
|
|
339
|
+
- added: `.claude/hooks/block-bg-double-background.py`
|
|
340
|
+
- added: `.claude/hooks/block-npm-install-in-pnpm.py`
|
|
341
|
+
- added: `.claude/hooks/block-secrets.py`
|
|
342
|
+
- added: `.claude/hooks/grep-shim-guard.py`
|
|
343
|
+
- added: `.claude/skills/setup-workflow/safety-guardrails.md`
|
|
344
|
+
- added: `scripts/safety-guardrails/core.py`
|
|
345
|
+
- added: `scripts/safety-guardrails/search.py`
|
|
346
|
+
- added: `scripts/security/audit-gate.mjs`
|
|
347
|
+
- added: `scripts/security/ensure-gitleaks.mjs`
|
|
348
|
+
- added: `scripts/security/gitleaks-profile.json`
|
|
349
|
+
- added: `scripts/security/install-git-hooks.mjs`
|
|
350
|
+
- changed: `.agents/skills/setup-workflow/SKILL.md`
|
|
351
|
+
- changed: `.claude/skills/setup-workflow/SKILL.md`
|
|
352
|
+
|
|
353
|
+
### 0.25.0
|
|
354
|
+
|
|
355
|
+
- added: `.claude/hooks/convention-drift-hint.py`
|
|
356
|
+
- added: `.claude/hooks/loc-offender-forewarn.py`
|
|
357
|
+
- added: `.claude/hooks/migration-snapshot-reminder.py`
|
|
358
|
+
- added: `scripts/workflow-advisories/capabilities.json`
|
|
359
|
+
- changed: `.agents/skills/setup-workflow/workflow-advisories.md`
|
|
360
|
+
- changed: `.claude/hooks/_hook_utils.py`
|
|
361
|
+
- changed: `.claude/hooks/skill-drift-hint.py`
|
|
362
|
+
- changed: `.claude/skills/setup-workflow/workflow-advisories.md`
|
|
363
|
+
- changed: `scripts/loc_offender_gate.py`
|
|
364
|
+
- changed: `scripts/workflow-advisories/core.py`
|
|
365
|
+
|
|
335
366
|
### 0.24.0
|
|
336
367
|
|
|
337
368
|
- added: `.agents/skills/setup-workflow/workflow-advisories.md`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"kitVersion": "0.
|
|
2
|
+
"kitVersion": "0.26.0",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": ".agents/skills/ask-matt/SKILL.md",
|
|
@@ -568,12 +568,21 @@
|
|
|
568
568
|
"mode": 420,
|
|
569
569
|
"origin": "kit"
|
|
570
570
|
},
|
|
571
|
+
{
|
|
572
|
+
"path": ".agents/skills/setup-workflow/safety-guardrails.md",
|
|
573
|
+
"kind": "skill",
|
|
574
|
+
"ownerSkill": "setup-workflow",
|
|
575
|
+
"surface": "codex",
|
|
576
|
+
"sha256": "08793fc7c9164cde9f7e09154e02d5718428272b85fb67d74681d3a415d4d483",
|
|
577
|
+
"mode": 420,
|
|
578
|
+
"origin": "kit"
|
|
579
|
+
},
|
|
571
580
|
{
|
|
572
581
|
"path": ".agents/skills/setup-workflow/SKILL.md",
|
|
573
582
|
"kind": "skill",
|
|
574
583
|
"ownerSkill": "setup-workflow",
|
|
575
584
|
"surface": "codex",
|
|
576
|
-
"sha256": "
|
|
585
|
+
"sha256": "b012c477612944d276e7012461f3ec38ecc25b5d92966b667150e1fb547b20cb",
|
|
577
586
|
"mode": 420,
|
|
578
587
|
"origin": "kit"
|
|
579
588
|
},
|
|
@@ -618,7 +627,7 @@
|
|
|
618
627
|
"kind": "skill",
|
|
619
628
|
"ownerSkill": "setup-workflow",
|
|
620
629
|
"surface": "codex",
|
|
621
|
-
"sha256": "
|
|
630
|
+
"sha256": "81ce0f5573d5f062adbc87149172e74ab322315bf348025c0ff2c27f8d8ec67b",
|
|
622
631
|
"mode": 420,
|
|
623
632
|
"origin": "kit"
|
|
624
633
|
},
|
|
@@ -886,7 +895,14 @@
|
|
|
886
895
|
{
|
|
887
896
|
"path": ".claude/hooks/_hook_utils.py",
|
|
888
897
|
"kind": "hook",
|
|
889
|
-
"sha256": "
|
|
898
|
+
"sha256": "9ad70fa80a57c7712df78718c578b58295f446c13a0f1863c69680f3889dd387",
|
|
899
|
+
"mode": 420,
|
|
900
|
+
"origin": "kit"
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
"path": ".claude/hooks/_safety_guard.py",
|
|
904
|
+
"kind": "hook",
|
|
905
|
+
"sha256": "1f5c387b11731c7b1cd027fc58acd4c1e45c64799975dc50eeff72469df0deb0",
|
|
890
906
|
"mode": 420,
|
|
891
907
|
"origin": "kit"
|
|
892
908
|
},
|
|
@@ -897,6 +913,27 @@
|
|
|
897
913
|
"mode": 493,
|
|
898
914
|
"origin": "kit"
|
|
899
915
|
},
|
|
916
|
+
{
|
|
917
|
+
"path": ".claude/hooks/block-bg-double-background.py",
|
|
918
|
+
"kind": "hook",
|
|
919
|
+
"sha256": "ad0c763e3afbb25685f91eea2c39fc3ee58c765536a961810a49bd0c7bbd47b8",
|
|
920
|
+
"mode": 493,
|
|
921
|
+
"origin": "kit"
|
|
922
|
+
},
|
|
923
|
+
{
|
|
924
|
+
"path": ".claude/hooks/block-npm-install-in-pnpm.py",
|
|
925
|
+
"kind": "hook",
|
|
926
|
+
"sha256": "54da075f8e63e5e927cb752c26c47880da49eb1f730f078558f3f5eec9377c82",
|
|
927
|
+
"mode": 493,
|
|
928
|
+
"origin": "kit"
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"path": ".claude/hooks/block-secrets.py",
|
|
932
|
+
"kind": "hook",
|
|
933
|
+
"sha256": "962c4f7f035c5cb4c322ee7c76b707a148526000427f4ebd49bfcac50af003b4",
|
|
934
|
+
"mode": 493,
|
|
935
|
+
"origin": "kit"
|
|
936
|
+
},
|
|
900
937
|
{
|
|
901
938
|
"path": ".claude/hooks/branch-context.py",
|
|
902
939
|
"kind": "hook",
|
|
@@ -911,6 +948,13 @@
|
|
|
911
948
|
"mode": 493,
|
|
912
949
|
"origin": "kit"
|
|
913
950
|
},
|
|
951
|
+
{
|
|
952
|
+
"path": ".claude/hooks/convention-drift-hint.py",
|
|
953
|
+
"kind": "hook",
|
|
954
|
+
"sha256": "f89fc3f3f9d9b7508e3cdeeedd0e522af11ae10e638457da3910bfe4e43579f2",
|
|
955
|
+
"mode": 493,
|
|
956
|
+
"origin": "kit"
|
|
957
|
+
},
|
|
914
958
|
{
|
|
915
959
|
"path": ".claude/hooks/drift-guard.py",
|
|
916
960
|
"kind": "hook",
|
|
@@ -939,6 +983,27 @@
|
|
|
939
983
|
"mode": 493,
|
|
940
984
|
"origin": "kit"
|
|
941
985
|
},
|
|
986
|
+
{
|
|
987
|
+
"path": ".claude/hooks/grep-shim-guard.py",
|
|
988
|
+
"kind": "hook",
|
|
989
|
+
"sha256": "9f69541c60c795bd5ec2a4f5d155f6fd3ced4f2ac6a28ed0c55c9a57772dd0d2",
|
|
990
|
+
"mode": 493,
|
|
991
|
+
"origin": "kit"
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
"path": ".claude/hooks/loc-offender-forewarn.py",
|
|
995
|
+
"kind": "hook",
|
|
996
|
+
"sha256": "28ba5edb1898345fd852d1f420bb64c5a2e0dfd66aa8d2b752899fc28a6f80dd",
|
|
997
|
+
"mode": 493,
|
|
998
|
+
"origin": "kit"
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
"path": ".claude/hooks/migration-snapshot-reminder.py",
|
|
1002
|
+
"kind": "hook",
|
|
1003
|
+
"sha256": "693227fae1aa3e782ed5b61a9e8c3fc8c1880a617efd14cb86ca7f38d9a8f204",
|
|
1004
|
+
"mode": 493,
|
|
1005
|
+
"origin": "kit"
|
|
1006
|
+
},
|
|
942
1007
|
{
|
|
943
1008
|
"path": ".claude/hooks/pre-refactor-sweep.py",
|
|
944
1009
|
"kind": "hook",
|
|
@@ -956,7 +1021,7 @@
|
|
|
956
1021
|
{
|
|
957
1022
|
"path": ".claude/hooks/skill-drift-hint.py",
|
|
958
1023
|
"kind": "hook",
|
|
959
|
-
"sha256": "
|
|
1024
|
+
"sha256": "2ce5c8cfc85dc76cf93abf1cd061440b8030109231a45a0920e36a5f1c06694a",
|
|
960
1025
|
"mode": 493,
|
|
961
1026
|
"origin": "kit"
|
|
962
1027
|
},
|
|
@@ -1681,12 +1746,21 @@
|
|
|
1681
1746
|
"mode": 420,
|
|
1682
1747
|
"origin": "kit"
|
|
1683
1748
|
},
|
|
1749
|
+
{
|
|
1750
|
+
"path": ".claude/skills/setup-workflow/safety-guardrails.md",
|
|
1751
|
+
"kind": "skill",
|
|
1752
|
+
"ownerSkill": "setup-workflow",
|
|
1753
|
+
"surface": "claude",
|
|
1754
|
+
"sha256": "08793fc7c9164cde9f7e09154e02d5718428272b85fb67d74681d3a415d4d483",
|
|
1755
|
+
"mode": 420,
|
|
1756
|
+
"origin": "kit"
|
|
1757
|
+
},
|
|
1684
1758
|
{
|
|
1685
1759
|
"path": ".claude/skills/setup-workflow/SKILL.md",
|
|
1686
1760
|
"kind": "skill",
|
|
1687
1761
|
"ownerSkill": "setup-workflow",
|
|
1688
1762
|
"surface": "claude",
|
|
1689
|
-
"sha256": "
|
|
1763
|
+
"sha256": "b012c477612944d276e7012461f3ec38ecc25b5d92966b667150e1fb547b20cb",
|
|
1690
1764
|
"mode": 420,
|
|
1691
1765
|
"origin": "kit"
|
|
1692
1766
|
},
|
|
@@ -1731,7 +1805,7 @@
|
|
|
1731
1805
|
"kind": "skill",
|
|
1732
1806
|
"ownerSkill": "setup-workflow",
|
|
1733
1807
|
"surface": "claude",
|
|
1734
|
-
"sha256": "
|
|
1808
|
+
"sha256": "81ce0f5573d5f062adbc87149172e74ab322315bf348025c0ff2c27f8d8ec67b",
|
|
1735
1809
|
"mode": 420,
|
|
1736
1810
|
"origin": "kit"
|
|
1737
1811
|
},
|
|
@@ -2159,7 +2233,7 @@
|
|
|
2159
2233
|
{
|
|
2160
2234
|
"path": "scripts/loc_offender_gate.py",
|
|
2161
2235
|
"kind": "script",
|
|
2162
|
-
"sha256": "
|
|
2236
|
+
"sha256": "a66650b3b194a00ecc3ba37acae4bbb1aeeb57762d27fb2dfd3bb1fc2734a8a5",
|
|
2163
2237
|
"mode": 493,
|
|
2164
2238
|
"origin": "kit"
|
|
2165
2239
|
},
|
|
@@ -2247,10 +2321,59 @@
|
|
|
2247
2321
|
"mode": 420,
|
|
2248
2322
|
"origin": "kit"
|
|
2249
2323
|
},
|
|
2324
|
+
{
|
|
2325
|
+
"path": "scripts/safety-guardrails/core.py",
|
|
2326
|
+
"kind": "script",
|
|
2327
|
+
"sha256": "c69c9d4e1b17efca51de12454b119e9ee6758aa6c8d73fe64e4bafd76c804f4e",
|
|
2328
|
+
"mode": 420,
|
|
2329
|
+
"origin": "kit"
|
|
2330
|
+
},
|
|
2331
|
+
{
|
|
2332
|
+
"path": "scripts/safety-guardrails/search.py",
|
|
2333
|
+
"kind": "script",
|
|
2334
|
+
"sha256": "345b1456f1a00320b6ad3e4fad1b050d8dd21a16b51b5e5cfdaf6a579530eac1",
|
|
2335
|
+
"mode": 420,
|
|
2336
|
+
"origin": "kit"
|
|
2337
|
+
},
|
|
2338
|
+
{
|
|
2339
|
+
"path": "scripts/security/audit-gate.mjs",
|
|
2340
|
+
"kind": "script",
|
|
2341
|
+
"sha256": "c6129e77f58e80f5880ebd6d2d235e27e9e31a20ee3cd967ce64815738e61e54",
|
|
2342
|
+
"mode": 493,
|
|
2343
|
+
"origin": "kit"
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
"path": "scripts/security/ensure-gitleaks.mjs",
|
|
2347
|
+
"kind": "script",
|
|
2348
|
+
"sha256": "5591f31d88362aa0df75f7b6bb7f22c094822b4bd00c5f6bf9ccff6a2313ed56",
|
|
2349
|
+
"mode": 493,
|
|
2350
|
+
"origin": "kit"
|
|
2351
|
+
},
|
|
2352
|
+
{
|
|
2353
|
+
"path": "scripts/security/gitleaks-profile.json",
|
|
2354
|
+
"kind": "doc",
|
|
2355
|
+
"sha256": "2480f7b4656d28cea1ede895970275d7b97f58d396341ee5e36b3df12575c1b6",
|
|
2356
|
+
"mode": 420,
|
|
2357
|
+
"origin": "kit"
|
|
2358
|
+
},
|
|
2359
|
+
{
|
|
2360
|
+
"path": "scripts/security/install-git-hooks.mjs",
|
|
2361
|
+
"kind": "script",
|
|
2362
|
+
"sha256": "8cf43120ea485fae7dc6aae38a14a3e703dbd18422ef13a199aedb3ec66b0184",
|
|
2363
|
+
"mode": 493,
|
|
2364
|
+
"origin": "kit"
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
"path": "scripts/workflow-advisories/capabilities.json",
|
|
2368
|
+
"kind": "doc",
|
|
2369
|
+
"sha256": "04c731394fa458c141870fb89f2432092b3749955eccbda9b9b8db09636526c9",
|
|
2370
|
+
"mode": 420,
|
|
2371
|
+
"origin": "kit"
|
|
2372
|
+
},
|
|
2250
2373
|
{
|
|
2251
2374
|
"path": "scripts/workflow-advisories/core.py",
|
|
2252
2375
|
"kind": "script",
|
|
2253
|
-
"sha256": "
|
|
2376
|
+
"sha256": "dc47bc20ed1107d230f45ff7158e4fd81d6473be515e03cbd52274f3e87d840d",
|
|
2254
2377
|
"mode": 420,
|
|
2255
2378
|
"origin": "kit"
|
|
2256
2379
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ikon85/agent-workflow-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Portable AI-agent workflow skills (plan → execute → land → learn) for Claude Code & Codex — grilling, TDD, diagnosis, two-axis code review, cross-model Codex review, design & domain-modeling, plus a skill router (ask-matt). npx init/update/diff/uninstall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import argparse
|
|
12
12
|
import json
|
|
13
|
+
import re
|
|
13
14
|
import subprocess
|
|
14
15
|
import sys
|
|
15
16
|
from pathlib import Path
|
|
@@ -25,6 +26,29 @@ class GateError(RuntimeError):
|
|
|
25
26
|
"""A condition the gate cannot evaluate → fail-closed (exit 1)."""
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
_ISSUE_MARKER_RE = re.compile(r"<!--\s*loc-offender:\s*([^>]+?)\s*-->")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse_issue_marker(body: str) -> list[str]:
|
|
33
|
+
"""Read the machine marker planted by board-sync at buildability transition."""
|
|
34
|
+
match = _ISSUE_MARKER_RE.search(body or "")
|
|
35
|
+
return [
|
|
36
|
+
path.strip() for path in match.group(1).split(",") if path.strip()
|
|
37
|
+
] if match else []
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def forewarning_context(body: str, max_lines: int, offenders: set[str]) -> str | None:
|
|
41
|
+
"""Render a non-blocking SessionStart warning from the gate-owned contracts."""
|
|
42
|
+
hits = sorted(set(parse_issue_marker(body)) & offenders)
|
|
43
|
+
if not hits:
|
|
44
|
+
return None
|
|
45
|
+
paths = ", ".join(hits)
|
|
46
|
+
return (
|
|
47
|
+
f"LoC offender advisory: {paths} is named by the issue marker and remains "
|
|
48
|
+
f"above the gate threshold ({max_lines} lines). The pre-push gate stays authoritative."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
28
52
|
def _git(args, cwd=None) -> str:
|
|
29
53
|
r = subprocess.run(["git", *args], cwd=cwd, capture_output=True, text=True)
|
|
30
54
|
if r.returncode != 0:
|