create-issflow 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/cli.js +51 -3
- package/package.json +1 -1
- package/template/.claude/commands/qa-audit.md +53 -0
- package/template/.claude/commands/runbook.md +38 -0
- package/template/.claude/commands/security-audit.md +56 -0
- package/template/.claude/commands/ui-audit.md +54 -0
- package/template/.claude/hooks/context-guard.js +101 -0
- package/template/.claude/hooks/lib/ctx.js +82 -0
- package/template/.claude/istartsoft-flow/METHODOLOGY.md +30 -1
- package/template/.claude/skills/ux-design/SKILL.md +4 -0
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Flags:
|
|
|
25
25
|
The portable kit (every tool) in `<project>/.claude/`:
|
|
26
26
|
|
|
27
27
|
- `agents/` — planner · researcher · implementer · test-author · debugger · e2e-runner · synthesizer
|
|
28
|
-
- `commands/` — `/overview` `/propose` `/phase` `/change-request` `/replan` `/quick` `/synthesize` `/store-wisdom` `/log-issue` `/log-decision` `/unstuck`
|
|
28
|
+
- `commands/` — `/overview` `/propose` `/phase` `/ui-audit` `/qa-audit` `/security-audit` `/change-request` `/replan` `/quick` `/synthesize` `/store-wisdom` `/log-issue` `/log-decision` `/unstuck`
|
|
29
29
|
- `skills/` — caveman · grill-me · karpathy-guidelines · ux-design
|
|
30
30
|
- `hooks/` — session-start · pre-compact · subagent-stop
|
|
31
31
|
- `istartsoft-flow/METHODOLOGY.md` — the full methodology (single source of truth)
|
package/bin/cli.js
CHANGED
|
@@ -107,8 +107,21 @@ function copyTemplateCommands(destDir) {
|
|
|
107
107
|
// ---- adapters (keep the methodology single-source — these POINT at it) ------
|
|
108
108
|
|
|
109
109
|
function adapterClaude() {
|
|
110
|
+
// Claude Code auto-loads CLAUDE.md only — NOT AGENTS.md. Without a CLAUDE.md
|
|
111
|
+
// the methodology never enters context on its own (the SessionStart hook still
|
|
112
|
+
// injects the per-session summary, but the full single-source doc would not
|
|
113
|
+
// load). A one-line `@AGENTS.md` import gives Claude Code the full baseline
|
|
114
|
+
// while keeping ONE source of truth — no rule is restated here (anti-drift).
|
|
115
|
+
const c0 = conflicts;
|
|
116
|
+
writeFile('CLAUDE.md', claudeMd());
|
|
117
|
+
if (conflicts > c0) warnings.push('claude: you already keep a CLAUDE.md — ours was written as CLAUDE.md.issflow-new. Add a line `@AGENTS.md` to your CLAUDE.md so the methodology auto-loads.');
|
|
118
|
+
// Context-budget watchdog config (consumed by .claude/hooks/context-guard.js).
|
|
119
|
+
// Shipped default window:0 = auto-detect; flow-config.json lives at .claude root,
|
|
120
|
+
// outside build.js's copied DIRS, so the installer writes it here.
|
|
121
|
+
writeFile('.claude/flow-config.json', flowConfig());
|
|
110
122
|
const HOOKS = {
|
|
111
123
|
SessionStart: [{ matcher: 'startup|clear|compact', hooks: [{ type: 'command', command: 'node .claude/hooks/session-start.js' }] }],
|
|
124
|
+
PreToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: 'node .claude/hooks/context-guard.js' }] }],
|
|
112
125
|
PreCompact: [{ matcher: 'auto|manual', hooks: [{ type: 'command', command: 'node .claude/hooks/pre-compact.js' }] }],
|
|
113
126
|
SubagentStop: [{ hooks: [{ type: 'command', command: 'node .claude/hooks/subagent-stop.js' }] }],
|
|
114
127
|
};
|
|
@@ -176,7 +189,7 @@ function adapterAider() {
|
|
|
176
189
|
const ADAPTERS = { claude: adapterClaude, codex: adapterCodex, cursor: adapterCursor, gemini: adapterGemini, aider: adapterAider };
|
|
177
190
|
|
|
178
191
|
const NEXT_STEPS = {
|
|
179
|
-
claude: 'Open Claude Code — the SessionStart hook fires automatically. Run /overview to bootstrap.',
|
|
192
|
+
claude: 'Open Claude Code — CLAUDE.md (@AGENTS.md) loads the methodology and the SessionStart hook fires automatically. Run /overview to bootstrap.',
|
|
180
193
|
codex: 'Open Codex CLI — it reads AGENTS.md. Start by running the /overview procedure (.claude/commands/overview.md).',
|
|
181
194
|
cursor: 'Open Cursor — the rule applies automatically. Run the /overview command to bootstrap.',
|
|
182
195
|
gemini: 'Open Gemini CLI — it reads GEMINI.md. Run the SESSION-OPEN ritual, then the overview procedure.',
|
|
@@ -198,8 +211,9 @@ function agentsMd() {
|
|
|
198
211
|
'## Roles — `.claude/agents/`', '',
|
|
199
212
|
'planner · researcher · implementer · test-author · debugger · e2e-runner · synthesizer', '',
|
|
200
213
|
'## Procedures — `.claude/commands/` (run as `/name`)', '',
|
|
201
|
-
'/overview · /propose · /phase · /
|
|
202
|
-
'/
|
|
214
|
+
'/overview · /propose · /phase · /ui-audit · /qa-audit · /security-audit ·',
|
|
215
|
+
'/change-request · /replan · /quick · /synthesize · /runbook · /store-wisdom · /log-issue ·',
|
|
216
|
+
'/log-decision · /unstuck', '',
|
|
203
217
|
'## Skills — `.claude/skills/` (loaded on demand)', '',
|
|
204
218
|
'caveman · grill-me · karpathy-guidelines · ux-design · security (Secure SDLC) · code-standards', '',
|
|
205
219
|
'## Autonomy', '',
|
|
@@ -224,6 +238,40 @@ function agentsMd() {
|
|
|
224
238
|
].join('\n');
|
|
225
239
|
}
|
|
226
240
|
|
|
241
|
+
function claudeMd() {
|
|
242
|
+
return [
|
|
243
|
+
'# CLAUDE.md — iStartSoftFlow (Claude Code entry)', '',
|
|
244
|
+
'@AGENTS.md', '',
|
|
245
|
+
'The import above is the single source of truth — it points to',
|
|
246
|
+
'`.claude/istartsoft-flow/METHODOLOGY.md` (read on demand). Do NOT restate any',
|
|
247
|
+
'rule here; this file only wires Claude-native mechanisms (anti-drift invariant).', '',
|
|
248
|
+
'## Claude-native wiring (automatic — see `.claude/settings.json`)', '',
|
|
249
|
+
'- **SessionStart** hook injects git state + `docs/STATE.md` + open `docs/ISSUES.md`',
|
|
250
|
+
' + the rule summary each session — read those first.',
|
|
251
|
+
'- **PreCompact** + **SubagentStop** hooks run their rituals automatically.',
|
|
252
|
+
'- Commands in `.claude/commands/` run as `/name`; agents in `.claude/agents/` are',
|
|
253
|
+
' native subagents.', '',
|
|
254
|
+
].join('\n');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function flowConfig() {
|
|
258
|
+
return JSON.stringify({
|
|
259
|
+
context: {
|
|
260
|
+
window: 0,
|
|
261
|
+
warnPct: 60,
|
|
262
|
+
gatePct: 78,
|
|
263
|
+
_note: 'Context-budget watchdog (.claude/hooks/context-guard.js, PreToolUse hook). '
|
|
264
|
+
+ 'window 0 = auto-detect from the model id (200000 for standard models). '
|
|
265
|
+
+ 'Some 1M-context models report their id WITHOUT a [1m] tag, so auto-detect '
|
|
266
|
+
+ 'assumes 200000 and may false-gate around 156k — if you run a 1M model, set '
|
|
267
|
+
+ 'window:1000000 here by hand. warnPct = soft non-blocking nudge; gatePct = hard '
|
|
268
|
+
+ 'block on NEW build work (Edit/Write-to-source/feature Task). Checkpoint paths '
|
|
269
|
+
+ '(docs/**, STATE/ISSUES/snapshots), the synthesizer subagent, and all Bash are '
|
|
270
|
+
+ 'never blocked.',
|
|
271
|
+
},
|
|
272
|
+
}, null, 2) + '\n';
|
|
273
|
+
}
|
|
274
|
+
|
|
227
275
|
// ---- main -------------------------------------------------------------------
|
|
228
276
|
|
|
229
277
|
function main() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-issflow",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Scaffold the iStartSoftFlow AI-coding workflow into a project. Stack-agnostic, tool-agnostic (Claude Code, Codex, Cursor, Gemini, Aider), non-destructive.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-issflow": "bin/cli.js"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Holistic QA audit — sweep the WHOLE product's functional quality (test-coverage gaps, regression health, flaky tests, critical-flow e2e, error/edge handling), score it, and produce a prioritized findings report. On-demand or before a release. NOT the per-phase gate — the phase gate runs one phase's real suite; this audits the entire test estate + behaviour.
|
|
3
|
+
argument-hint: [optional scope]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Caveman ULTRA mode. You are the ORCHESTRATOR.
|
|
7
|
+
|
|
8
|
+
Purpose: a whole-product FUNCTIONAL QA audit — the QA counterpart of `/ui-audit`.
|
|
9
|
+
The per-phase gate (rule 5) proves ONE phase's real suite is green; this audit checks
|
|
10
|
+
the health + coverage of the ENTIRE test estate and the product's behaviour, end to
|
|
11
|
+
end. Run before a release, after big changes, or on request.
|
|
12
|
+
|
|
13
|
+
QA = "does it WORK right?" — a DIFFERENT axis from UI audit ("does it LOOK / meet
|
|
14
|
+
standards right?"). Passing one never implies the other.
|
|
15
|
+
|
|
16
|
+
## PRE-FLIGHT
|
|
17
|
+
Read `docs/ENDPOINTS.md` (the surface), `docs/PLAN.md` (acceptance specs), and the
|
|
18
|
+
`tests/` + `e2e/` suites. The acceptance criteria + ENDPOINTS are the rubric.
|
|
19
|
+
|
|
20
|
+
## STEP 1 — INVENTORY
|
|
21
|
+
List the public surface (endpoints, exported functions, CLI, message contracts) and
|
|
22
|
+
the critical user flows (from OVERVIEW). These are what MUST be covered.
|
|
23
|
+
|
|
24
|
+
## STEP 2 — SWEEP (dispatch a worker to keep context lean)
|
|
25
|
+
- **Coverage** — every ENDPOINTS entry + acceptance criterion has a real-API
|
|
26
|
+
regression test? List gaps. Untested branches / error paths?
|
|
27
|
+
- **Critical flows** — does e2e cover the must-work journeys (auth, the core slice,
|
|
28
|
+
payments / data)?
|
|
29
|
+
- **Regression health** — run the full REAL corpus (`scripts/regression.sh --real`).
|
|
30
|
+
Any reds?
|
|
31
|
+
- **Flakiness** — tests that pass only on rerun (timing) — flag; don't hide.
|
|
32
|
+
- **Negative / edge** — are abuse cases + edge inputs asserted, not just the happy path?
|
|
33
|
+
- **Contract drift** — do the mock suites still match the real API?
|
|
34
|
+
- **Test integrity** — tests written BLIND from the spec (no overfit)? None edited to pass?
|
|
35
|
+
|
|
36
|
+
## STEP 3 — SCORE + FINDINGS
|
|
37
|
+
Rate each dimension PASS / WARN / FAIL. Per finding:
|
|
38
|
+
- **severity**: BLOCKER (red real test · uncovered critical flow) · MAJOR (coverage
|
|
39
|
+
gap · flaky) · MINOR (polish)
|
|
40
|
+
- **location**: suite + case (or the uncovered surface)
|
|
41
|
+
- **issue** + **fix**: the concrete change
|
|
42
|
+
|
|
43
|
+
## STEP 4 — REPORT
|
|
44
|
+
Write `docs/qa-audit-<YYYY-MM-DD>.md`: coverage map · per-dimension scoreboard ·
|
|
45
|
+
findings sorted by severity · prioritized fix list. Log BLOCKER / MAJOR to
|
|
46
|
+
`docs/ISSUES.md`.
|
|
47
|
+
**VERDICT: SHIP | FIX-FIRST** — never ship with a red real test or an uncovered
|
|
48
|
+
critical flow.
|
|
49
|
+
|
|
50
|
+
## STEP 5 — REMEDIATE
|
|
51
|
+
AUTO: dispatch `test-author` (BLIND) to fill coverage gaps, `debugger` for reds
|
|
52
|
+
(budget 3), then re-run. Park what's blocked + report. Tests are written by
|
|
53
|
+
`test-author` for impartiality — never weaken a test to make it pass.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Capture an operational/incident scenario in docs/RUNBOOK.md — one grep-able markdown so prod-debug knowledge isn't re-derived under pressure.
|
|
3
|
+
argument-hint: [scenario, or "from the incident we just solved"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Caveman ULTRA mode.
|
|
7
|
+
|
|
8
|
+
Distill an operational scenario into docs/RUNBOOK.md. Scenario: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
This is the runbook pattern Anthropic's Security + Data-Infra teams converged on
|
|
11
|
+
independently: consolidate stack traces, dashboard signals, and the exact
|
|
12
|
+
remediation commands into ONE searchable file so the next incident is a lookup,
|
|
13
|
+
not a re-investigation.
|
|
14
|
+
|
|
15
|
+
If $ARGUMENTS says "from the incident we just solved" (or similar), distill the
|
|
16
|
+
debugging session in context — symptom, the REAL root cause, the commands that
|
|
17
|
+
fixed it — instead of asking the user to re-type it.
|
|
18
|
+
|
|
19
|
+
Append an entry to docs/RUNBOOK.md (create the file if missing). Canonical format:
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### <scenario title — searchable, literal symptom keywords>
|
|
23
|
+
|
|
24
|
+
- trigger: <what you observe first — alert, error string, dashboard signal>
|
|
25
|
+
- diagnose: <steps/commands to confirm the real root cause>
|
|
26
|
+
- remediate: <the exact commands/actions that fix it>
|
|
27
|
+
- verify: <how to confirm recovery — what "healthy" looks like>
|
|
28
|
+
- refs: <dashboard URLs, docs, related docs/ISSUES.md titles>
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Rules:
|
|
32
|
+
- title carries literal symptom keywords -> grep finds it mid-incident.
|
|
33
|
+
- remediate must be runnable as-is; no "investigate further".
|
|
34
|
+
- mark any step that is irreversible / PROD-writing with ⚠ so it's never run blind.
|
|
35
|
+
- cross-link the matching docs/ISSUES.md entry instead of duplicating root-cause prose.
|
|
36
|
+
- newest scenario at the TOP.
|
|
37
|
+
|
|
38
|
+
Confirm the entry back in 2 lines.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Holistic security audit — sweep the WHOLE product against the security cookbook (OWASP Top 10 / ASVS / WSTG / secrets / SCA / SAST / supply chain), score it, and produce a prioritized findings report. On-demand or before a release. NOT the per-phase gate — rule 11 checks one phase while coding; this audits the whole attack surface.
|
|
3
|
+
argument-hint: [optional scope]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Caveman ULTRA mode. You are the ORCHESTRATOR.
|
|
7
|
+
|
|
8
|
+
Purpose: a whole-product SECURITY audit — the security counterpart of `/ui-audit`
|
|
9
|
+
and `/qa-audit`. The per-phase gate (rule 11) checks secrets/SCA/SAST + secure coding
|
|
10
|
+
on ONE phase; this audit sweeps the ENTIRE attack surface and the product's security
|
|
11
|
+
posture. Run before a release, after auth/data changes, or on request — and before
|
|
12
|
+
the pre-deploy pentest, not instead of it.
|
|
13
|
+
|
|
14
|
+
Security = "is it SAFE?" — a different axis from QA ("does it work?") and UI
|
|
15
|
+
("does it look right?"). Passing those never implies this.
|
|
16
|
+
|
|
17
|
+
## PRE-FLIGHT
|
|
18
|
+
Read the rubric: `.claude/skills/security/SKILL.md` (the Secure SDLC cookbook) and
|
|
19
|
+
its `references/` (OWASP Top 10 / ASVS / WSTG / ISO 27001 / SLSA). The cookbook IS the
|
|
20
|
+
checklist — audit against it; don't invent criteria.
|
|
21
|
+
|
|
22
|
+
## STEP 1 — INVENTORY (attack surface)
|
|
23
|
+
Map it from `docs/ENDPOINTS.md` + the code: entry points (routes, inputs, file
|
|
24
|
+
uploads, webhooks), trust boundaries, auth/session, data stores + PII, secrets,
|
|
25
|
+
third-party deps, and outbound calls.
|
|
26
|
+
|
|
27
|
+
## STEP 2 — SWEEP (dispatch a worker to keep context lean)
|
|
28
|
+
- **OWASP Top 10** — broken access control, crypto failures, injection (SQLi/XSS/
|
|
29
|
+
cmd), insecure design, misconfiguration, vulnerable components, auth failures,
|
|
30
|
+
integrity failures, logging/monitoring gaps, SSRF.
|
|
31
|
+
- **AuthN / AuthZ** — every protected route enforces it; no IDOR; least privilege.
|
|
32
|
+
- **Secrets** — none in code/history/config/prompts (run gitleaks/trufflehog if present).
|
|
33
|
+
- **Dependencies (SCA)** — known CVEs (run `npm audit` / `pip-audit` / `osv-scanner`).
|
|
34
|
+
- **SAST** — run semgrep / CodeQL if present; review hotspots otherwise.
|
|
35
|
+
- **Input validation + output encoding** at every boundary; safe file handling.
|
|
36
|
+
- **Crypto** — strong algorithms, no hardcoded keys, secrets at rest/in transit.
|
|
37
|
+
- **Supply chain (SLSA)** — pinned deps, build integrity, no untrusted scripts.
|
|
38
|
+
- **Logging / monitoring** — security events logged; no sensitive data in logs.
|
|
39
|
+
- **Threat-model coverage** — were the design-stage abuse cases actually tested?
|
|
40
|
+
|
|
41
|
+
## STEP 3 — SCORE + FINDINGS
|
|
42
|
+
Rate each area PASS / WARN / FAIL. Per finding:
|
|
43
|
+
- **severity**: CRITICAL · HIGH · MEDIUM · LOW (map to CVSS where it helps)
|
|
44
|
+
- **location**: endpoint / file / dependency
|
|
45
|
+
- **issue** + the OWASP/ASVS reference it breaks + **fix**
|
|
46
|
+
|
|
47
|
+
## STEP 4 — REPORT
|
|
48
|
+
Write `docs/security-audit-<YYYY-MM-DD>.md`: attack-surface map · per-area scoreboard ·
|
|
49
|
+
findings sorted by severity · prioritized remediation. Log HIGH/CRITICAL to
|
|
50
|
+
`docs/ISSUES.md`.
|
|
51
|
+
**VERDICT: SHIP | FIX-FIRST** — never ship with an open HIGH or CRITICAL.
|
|
52
|
+
|
|
53
|
+
## STEP 5 — REMEDIATE
|
|
54
|
+
A security fix is security-sensitive (autonomy hard-stop): in AUTO, fix and re-audit
|
|
55
|
+
but SURFACE the change for human sign-off before it lands. Park what's blocked +
|
|
56
|
+
report. A clean `/security-audit` is a precondition for the pre-deploy pentest gate.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Holistic UI audit — sweep the WHOLE product's UI against the ux-design cookbook (+ a11y / responsive / consistency), score it, and produce a prioritized findings report. On-demand or before a release. This is NOT the per-phase gate — the `ux-design` gate checks one screen at phase close (pass/block); this audit sweeps every screen and reports accumulated drift.
|
|
3
|
+
argument-hint: [optional scope — a route, or "all"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Caveman ULTRA mode. You are the ORCHESTRATOR.
|
|
7
|
+
|
|
8
|
+
Purpose: a periodic, WHOLE-PRODUCT UI audit — distinct from the inline `ux-design`
|
|
9
|
+
gate. The gate validates ONE screen at phase close; this AUDIT sweeps EVERY screen,
|
|
10
|
+
scores the product, and surfaces drift that accumulated across changes. Run before a
|
|
11
|
+
release, after big UI work, or on request.
|
|
12
|
+
|
|
13
|
+
## PRE-FLIGHT
|
|
14
|
+
Read the rubric: `.claude/skills/ux-design/SKILL.md` (the cookbook) and
|
|
15
|
+
`references/wireframe-template.md` (the frame). The cookbook IS the checklist —
|
|
16
|
+
do not invent new criteria; audit against it.
|
|
17
|
+
|
|
18
|
+
## STEP 1 — INVENTORY
|
|
19
|
+
List every screen / route / major component to audit (from the router, the
|
|
20
|
+
wireframe baseline, or `$ARGUMENTS`). Audit shared components once.
|
|
21
|
+
|
|
22
|
+
## STEP 2 — SWEEP (dispatch a worker per area to keep context lean)
|
|
23
|
+
Score each screen against the cookbook dimensions:
|
|
24
|
+
- design tokens · 8-pt spacing · type scale (no raw hex/px)
|
|
25
|
+
- iconography — a real SVG set, **NEVER emoji**
|
|
26
|
+
- accessibility (WCAG 2.1 AA): contrast ≥ 4.5:1, visible focus, keyboard reach,
|
|
27
|
+
semantic HTML, labels / alt / aria, 44×44 targets, `prefers-reduced-motion`
|
|
28
|
+
- state matrix: default · hover · focus · active · disabled · loading · empty · error
|
|
29
|
+
- responsive breakpoints (no overflow / break)
|
|
30
|
+
- content & i18n (no hardcoded strings; growth-safe)
|
|
31
|
+
- consistency / wireframe conformance (no drift BETWEEN screens)
|
|
32
|
+
Run automated tools if the project has them (axe-core / Lighthouse / pa11y) and fold
|
|
33
|
+
their output in; otherwise do the manual cookbook sweep.
|
|
34
|
+
|
|
35
|
+
## STEP 3 — SCORE + FINDINGS
|
|
36
|
+
Rate each dimension PASS / WARN / FAIL. For every finding record:
|
|
37
|
+
- **severity**: BLOCKER (a11y / contrast / unusable) · MAJOR (drift / missing state)
|
|
38
|
+
· MINOR (polish)
|
|
39
|
+
- **location**: screen + element
|
|
40
|
+
- **issue** + the cookbook rule it breaks
|
|
41
|
+
- **fix**: the concrete change
|
|
42
|
+
|
|
43
|
+
## STEP 4 — REPORT
|
|
44
|
+
Write `docs/ui-audit-<YYYY-MM-DD>.md`:
|
|
45
|
+
- coverage (screens audited) · a per-dimension scoreboard · the findings table sorted
|
|
46
|
+
by severity · a prioritized fix list.
|
|
47
|
+
- Log BLOCKER / MAJOR findings to `docs/ISSUES.md`.
|
|
48
|
+
- **VERDICT: SHIP | FIX-FIRST** — a release must not ship with open BLOCKERs.
|
|
49
|
+
|
|
50
|
+
## STEP 5 — REMEDIATE
|
|
51
|
+
AUTO: fix MINOR / MAJOR that don't change the visual direction, re-audit them, log.
|
|
52
|
+
A new visual direction or a design-token change → confirm with the user first
|
|
53
|
+
(hard rule 9 — UI conforms to the frame; new direction is a human call).
|
|
54
|
+
Hand back the report + what was fixed vs parked.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// PreToolUse context watchdog (iStartSoftFlow). Two tiers, one hook:
|
|
4
|
+
// warnPct -> non-blocking nudge (additionalContext) once per climb into the band
|
|
5
|
+
// gatePct -> HARD block of NEW build work (Edit/Write-to-source/feature Task)
|
|
6
|
+
// Reads REAL token usage from the transcript. Fail-OPEN: any error -> allow,
|
|
7
|
+
// never wedge the tool loop on a hook bug.
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const silent = () => process.exit(0);
|
|
12
|
+
const out = (obj) => { process.stdout.write(JSON.stringify(obj)); process.exit(0); };
|
|
13
|
+
|
|
14
|
+
let input = '';
|
|
15
|
+
process.stdin.setEncoding('utf8');
|
|
16
|
+
process.stdin.on('data', (d) => (input += d));
|
|
17
|
+
process.stdin.on('end', () => {
|
|
18
|
+
let evt;
|
|
19
|
+
try { evt = JSON.parse(input); } catch (_) { return silent(); }
|
|
20
|
+
try { run(evt); } catch (_) { silent(); }
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
function run(evt) {
|
|
24
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR || evt.cwd || '.';
|
|
25
|
+
let ctx;
|
|
26
|
+
try { ctx = require(path.join(projectDir, '.claude/hooks/lib/ctx.js')); } catch (_) { return silent(); }
|
|
27
|
+
const cfg = ctx.loadConfig(projectDir);
|
|
28
|
+
const warn = cfg.warnPct || 60;
|
|
29
|
+
const gate = cfg.gatePct || 78;
|
|
30
|
+
|
|
31
|
+
const u = ctx.contextUsage(evt.transcript_path, cfg);
|
|
32
|
+
if (!u) return silent();
|
|
33
|
+
|
|
34
|
+
const tool = evt.tool_name || '';
|
|
35
|
+
const ti = evt.tool_input || {};
|
|
36
|
+
const band = u.pct >= gate ? 'gate' : u.pct >= warn ? 'warn' : 'ok';
|
|
37
|
+
const BLOCKABLE = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit', 'Task']);
|
|
38
|
+
|
|
39
|
+
// HARD GATE — block new build mutations; reason is fed to the model.
|
|
40
|
+
if (band === 'gate' && BLOCKABLE.has(tool) && !isEscape(tool, ti)) {
|
|
41
|
+
return out({
|
|
42
|
+
hookSpecificOutput: {
|
|
43
|
+
hookEventName: 'PreToolUse',
|
|
44
|
+
permissionDecision: 'deny',
|
|
45
|
+
permissionDecisionReason: gateReason(u, gate),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// NON-BLOCKING WARN — emit once each time we climb into a higher band.
|
|
51
|
+
const bandFile = path.join(projectDir, 'docs/.snapshots/.ctx-band');
|
|
52
|
+
const rank = (b) => (b === 'gate' ? 2 : b === 'warn' ? 1 : 0);
|
|
53
|
+
let prev = 'ok';
|
|
54
|
+
try { prev = (fs.readFileSync(bandFile, 'utf8').trim() || 'ok'); } catch (_) {}
|
|
55
|
+
|
|
56
|
+
if (rank(band) !== rank(prev)) {
|
|
57
|
+
try { fs.mkdirSync(path.dirname(bandFile), { recursive: true }); fs.writeFileSync(bandFile, band); } catch (_) {}
|
|
58
|
+
}
|
|
59
|
+
if (rank(band) > rank(prev) && band !== 'ok') {
|
|
60
|
+
return out({
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: 'PreToolUse',
|
|
63
|
+
additionalContext: band === 'gate' ? gateReason(u, gate) : warnReason(u, warn, gate),
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return silent();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Checkpoint/logging writes + the synthesizer ritual are never blocked, so the
|
|
71
|
+
// model always has an escape path out of the gate.
|
|
72
|
+
function isEscape(tool, ti) {
|
|
73
|
+
if (tool === 'Edit' || tool === 'Write' || tool === 'MultiEdit' || tool === 'NotebookEdit') {
|
|
74
|
+
const fp = ti.file_path || ti.path || ti.notebook_path || '';
|
|
75
|
+
return /(^|\/)docs\//.test(fp) || /STATE\.md|ISSUES\.md|\.snapshots\//.test(fp);
|
|
76
|
+
}
|
|
77
|
+
if (tool === 'Task') return (ti.subagent_type || '').toLowerCase() === 'synthesizer';
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const fmt = (n) => (n >= 1000 ? Math.round(n / 1000) + 'k' : String(n));
|
|
82
|
+
|
|
83
|
+
function gateReason(u, gate) {
|
|
84
|
+
return [
|
|
85
|
+
`⛔ CONTEXT GATE — ${u.pct}% (${fmt(u.tokens)}/${fmt(u.window)} tok), เกิน ${gate}% = หยุดเปิดงาน build ใหม่.`,
|
|
86
|
+
'ทำก่อนไปต่อ:',
|
|
87
|
+
' 1) ปิด/commit งานค้างให้จบ (Bash/git ไม่ถูก block)',
|
|
88
|
+
' 2) /synthesize (อัด handoff docs — subagent นี้ไม่ถูก block)',
|
|
89
|
+
' 3) /clear (session ใหม่ บางลง)',
|
|
90
|
+
'build ต่อหลัง clear. กลาง irreversible op? ใช้ Bash ปิดให้จบก่อน clear.',
|
|
91
|
+
'ปลดล็อกชั่วคราว: เพิ่ม gatePct ใน .claude/flow-config.json.',
|
|
92
|
+
].join('\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function warnReason(u, warn, gate) {
|
|
96
|
+
return [
|
|
97
|
+
`⚠️ CONTEXT ${u.pct}% (${fmt(u.tokens)}/${fmt(u.window)} tok) — แตะ warn band ${warn}%.`,
|
|
98
|
+
`วางแผนปิด phase: ทยอย /synthesize → /clear ก่อนถึง gate ${gate}% (เลยจุดนั้น hook block งาน build ใหม่).`,
|
|
99
|
+
'Delegate งาน noisy ให้ subagent เพื่อกัน context โต.',
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Shared context-budget math for iStartSoftFlow watchdog hooks.
|
|
3
|
+
// Reads the live Claude Code transcript (JSONL) and reports how full the
|
|
4
|
+
// model's context window currently is — from the REAL token usage the API
|
|
5
|
+
// reported, not a heuristic. Pure Node, cross-platform.
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
// Known context windows by model-id substring. First match wins. The 1M
|
|
9
|
+
// Opus/Sonnet variants advertise "[1m]" in the model id.
|
|
10
|
+
const WINDOWS = [
|
|
11
|
+
[/\[1m\]|-1m\b|:1m\b|1m-/i, 1000000],
|
|
12
|
+
[/opus|sonnet|haiku|claude/i, 200000],
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
function inferWindow(model) {
|
|
16
|
+
if (!model) return 200000;
|
|
17
|
+
for (const [re, w] of WINDOWS) if (re.test(model)) return w;
|
|
18
|
+
return 200000;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Read project flow config; returns the `context` block or {}.
|
|
22
|
+
function loadConfig(projectDir) {
|
|
23
|
+
try {
|
|
24
|
+
const cfg = JSON.parse(fs.readFileSync(projectDir + '/.claude/flow-config.json', 'utf8'));
|
|
25
|
+
return (cfg && cfg.context) || {};
|
|
26
|
+
} catch (_) { return {}; }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Read only the last `bytes` of a file (the recent assistant turns live at the
|
|
30
|
+
// tail of the JSONL — no need to load a multi-MB transcript on every tool).
|
|
31
|
+
function readTail(p, bytes) {
|
|
32
|
+
const fd = fs.openSync(p, 'r');
|
|
33
|
+
try {
|
|
34
|
+
const size = fs.fstatSync(fd).size;
|
|
35
|
+
const start = Math.max(0, size - bytes);
|
|
36
|
+
const len = size - start;
|
|
37
|
+
const buf = Buffer.alloc(len);
|
|
38
|
+
fs.readSync(fd, buf, 0, len, start);
|
|
39
|
+
return { text: buf.toString('utf8'), partial: start > 0 };
|
|
40
|
+
} finally { fs.closeSync(fd); }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Scan lines (newest first) for the most recent assistant usage block.
|
|
44
|
+
// input_tokens + cache_read + cache_creation == the full prompt size actually
|
|
45
|
+
// sent == current context occupancy.
|
|
46
|
+
function scanUsage(text, dropFirst) {
|
|
47
|
+
const lines = text.split('\n');
|
|
48
|
+
const lo = dropFirst ? 1 : 0; // first line may be a truncated tail fragment
|
|
49
|
+
for (let i = lines.length - 1; i >= lo; i--) {
|
|
50
|
+
const ln = lines[i].trim();
|
|
51
|
+
if (!ln) continue;
|
|
52
|
+
let obj;
|
|
53
|
+
try { obj = JSON.parse(ln); } catch (_) { continue; }
|
|
54
|
+
const m = obj && obj.message;
|
|
55
|
+
if (m && m.role === 'assistant' && m.usage && typeof m.usage.input_tokens === 'number') {
|
|
56
|
+
return { usage: m.usage, model: m.model || obj.model || null };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function contextUsage(transcriptPath, cfg) {
|
|
63
|
+
if (!transcriptPath) return null;
|
|
64
|
+
let hit;
|
|
65
|
+
try {
|
|
66
|
+
const tail = readTail(transcriptPath, 512 * 1024);
|
|
67
|
+
hit = scanUsage(tail.text, tail.partial);
|
|
68
|
+
if (!hit && tail.partial) {
|
|
69
|
+
// usage not in the tail window — fall back to a full read (rare).
|
|
70
|
+
hit = scanUsage(fs.readFileSync(transcriptPath, 'utf8'), false);
|
|
71
|
+
}
|
|
72
|
+
} catch (_) { return null; }
|
|
73
|
+
if (!hit) return null;
|
|
74
|
+
const u = hit.usage;
|
|
75
|
+
const tokens = (u.input_tokens || 0)
|
|
76
|
+
+ (u.cache_read_input_tokens || 0)
|
|
77
|
+
+ (u.cache_creation_input_tokens || 0);
|
|
78
|
+
const window = (cfg && cfg.window) ? cfg.window : inferWindow(hit.model);
|
|
79
|
+
return { tokens, window, model: hit.model, pct: Math.round((tokens / window) * 100) };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = { contextUsage, inferWindow, loadConfig, readTail, scanUsage };
|
|
@@ -174,6 +174,15 @@ Named procedures, each with a canonical body in `.claude/commands/<name>.md`.
|
|
|
174
174
|
coverage gate.
|
|
175
175
|
- **quick [change]** — small, obvious, non-phase change; no agent chain. Stays
|
|
176
176
|
non-TDD. Runs the mock regression corpus after the change.
|
|
177
|
+
- **ui-audit** — whole-product UI audit against the `ux-design` cookbook (a11y /
|
|
178
|
+
responsive / consistency); scored findings report. Periodic / pre-release. Distinct
|
|
179
|
+
from the per-phase ux-design gate (one screen) — this sweeps every screen.
|
|
180
|
+
- **qa-audit** — whole-product FUNCTIONAL QA audit (coverage gaps, regression health,
|
|
181
|
+
flaky tests, critical-flow e2e, edge/error handling); scored report. The QA
|
|
182
|
+
counterpart of `ui-audit`. Distinct from the per-phase real-suite gate.
|
|
183
|
+
- **security-audit** — whole-product SECURITY audit against the `security` cookbook
|
|
184
|
+
(OWASP/ASVS/WSTG/secrets/SCA/SAST/supply-chain); scored report. On-demand; a
|
|
185
|
+
precondition for the pre-deploy pentest. Distinct from the per-phase rule-11 gate.
|
|
177
186
|
- **unstuck** — deep re-research after a circuit breaker (auto-run once in AUTO on
|
|
178
187
|
first stuck; human-triggered in GUIDED).
|
|
179
188
|
- **synthesize** — compress STATE.md, dedup ISSUES.md, prune snapshots. Run
|
|
@@ -332,6 +341,26 @@ development run that follows the spec and logs every problem so it never recurs.
|
|
|
332
341
|
|
|
333
342
|
-----
|
|
334
343
|
|
|
344
|
+
## Quality model (orthogonal axes — each audited)
|
|
345
|
+
|
|
346
|
+
Quality is checked on independent axes. Passing one NEVER implies another. Each has a
|
|
347
|
+
STANDARD, an inline GATE (per phase), and — for the user-facing ones — a holistic
|
|
348
|
+
AUDIT (whole product, pre-release):
|
|
349
|
+
|
|
350
|
+
| Axis | Question | Standard | Inline gate (per phase) | Whole-product audit |
|
|
351
|
+
|------|----------|----------|-------------------------|---------------------|
|
|
352
|
+
| **Functional / QA** | does it WORK? | blind TDD, RED-first (rules 5–6) | real suite green + regression corpus | full REAL corpus (final phase) · `/qa-audit` |
|
|
353
|
+
| **UI / UX** | is it usable + on-brand? | `ux-design` cookbook | the ux-design check (rule 9) | `/ui-audit` |
|
|
354
|
+
| **Security** | is it safe? | `security` cookbook (OWASP/ASVS/ISO) | secrets/SCA/SAST + secure coding (rule 11) | `/security-audit` · pentest + review before deploy |
|
|
355
|
+
| **Code** | is it consistent? | `code-standards` (naming/architecture) | lint/format + idiom (rule 12) | — |
|
|
356
|
+
|
|
357
|
+
**QA is the test discipline**, not a single agent: `test-author` (blind tests) +
|
|
358
|
+
`e2e-runner` (functional E2E) + the phase gate + the regression corpus + `debugger`.
|
|
359
|
+
UI audit checks *presentation*; QA checks *behaviour* — a button can pass one and
|
|
360
|
+
fail the other.
|
|
361
|
+
|
|
362
|
+
-----
|
|
363
|
+
|
|
335
364
|
## Shared KB (optional)
|
|
336
365
|
|
|
337
366
|
If `.claude/kb-config.json` exists, the SESSION-OPEN ritual pulls the KB and loads
|
|
@@ -392,7 +421,7 @@ the same everywhere — only the *wiring* differs.
|
|
|
392
421
|
|
|
393
422
|
| Host | Entry file | Commands | Subagents | Lifecycle hooks | Shared KB |
|
|
394
423
|
|------|-----------|----------|-----------|-----------------|-----------|
|
|
395
|
-
| **Claude Code** (reference) | `AGENTS.md` + `.claude/` | `.claude/commands/` | native | SessionStart · PreCompact · SubagentStop
|
|
424
|
+
| **Claude Code** (reference) | `CLAUDE.md` (`@AGENTS.md`) + `.claude/` | `.claude/commands/` | native | SessionStart · PreToolUse (context-budget watchdog) · PreCompact · SubagentStop | yes |
|
|
396
425
|
| **Codex CLI** | `AGENTS.md` (native) | `.claude/commands/` (read as prompts) | read as reference | model-run | yes |
|
|
397
426
|
| **Cursor** | `.cursor/rules/` + `AGENTS.md` | `.cursor/commands/` | reads `.claude/agents/` | `.cursor/hooks.json` (sessionStart · subagentStop) | yes |
|
|
398
427
|
| **Gemini CLI** | `GEMINI.md` + `AGENTS.md` | `.claude/commands/` (read as prompts) | read as reference | model-run | yes |
|
|
@@ -31,6 +31,10 @@ confirmed with the user before building — design is where human taste matters.
|
|
|
31
31
|
- Reviewing a UI diff (the "ตรวจ" pass).
|
|
32
32
|
- CLOSE gate of any frontend phase — the cookbook check MUST pass.
|
|
33
33
|
|
|
34
|
+
This skill is the STANDARD + the inline GATE (one screen, at phase close). For a
|
|
35
|
+
WHOLE-PRODUCT sweep against this same cookbook — periodic or before a release — run
|
|
36
|
+
`/ui-audit` (same rubric, broader scope, a scored report).
|
|
37
|
+
|
|
34
38
|
Order: **wireframe first** (does the layout match the baseline frame?) ->
|
|
35
39
|
**cookbook** (do the details obey the system?). Never invent layout the
|
|
36
40
|
wireframe does not have. If the design truly needs a frame the wireframe lacks,
|