5-phase-workflow 3.0.0 → 3.1.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 (56) hide show
  1. package/README.md +31 -101
  2. package/bin/install.js +168 -176
  3. package/bin/sync-agents.js +59 -54
  4. package/docs/workflow-guide.md +35 -79
  5. package/package.json +2 -2
  6. package/src/agents/step-executor-agent.md +5 -4
  7. package/src/agents/step-orchestrator-agent.md +12 -12
  8. package/src/agents/verification-agent.md +7 -8
  9. package/src/codex-commands/plan.md +65 -0
  10. package/src/commands/5/address-review-findings.md +43 -52
  11. package/src/commands/5/analyze-feature.md +1 -1
  12. package/src/commands/5/configure.md +75 -179
  13. package/src/commands/5/eject.md +0 -1
  14. package/src/commands/5/implement.md +78 -68
  15. package/src/commands/5/lean-check.md +75 -0
  16. package/src/commands/5/reconfigure.md +48 -129
  17. package/src/commands/5/review.md +42 -14
  18. package/src/commands/5/synchronize-agents.md +1 -1
  19. package/src/commands/5/update.md +2 -2
  20. package/src/hooks/dependency-guard.js +150 -0
  21. package/src/hooks/statusline.js +5 -3
  22. package/src/references/configure-tables.md +0 -33
  23. package/src/settings.json +3 -4
  24. package/src/skills/baseline-conventions/SKILL.md +37 -0
  25. package/src/skills/cognitive-load/SKILL.md +52 -0
  26. package/src/skills/configure-agents-md/SKILL.md +72 -0
  27. package/src/skills/configure-rules/SKILL.md +146 -0
  28. package/src/skills/documentation-style/SKILL.md +32 -0
  29. package/src/skills/fowler-code-smells/SKILL.md +25 -0
  30. package/src/skills/review-style/SKILL.md +142 -0
  31. package/src/templates/AGENTS.md +31 -31
  32. package/src/templates/workflow/REVIEW-FINDINGS.md +2 -9
  33. package/src/workflows/5-implement.js +67 -92
  34. package/docs/findings.md +0 -361
  35. package/docs/progress.md +0 -102
  36. package/src/commands/5/apply-review-findings.md +0 -66
  37. package/src/commands/5/commit.md +0 -43
  38. package/src/commands/5/plan.md +0 -189
  39. package/src/commands/5/reply-pr-comments.md +0 -48
  40. package/src/commands/5/split.md +0 -86
  41. package/src/commands/5/triage-pr-comments.md +0 -70
  42. package/src/hooks/config-guard.js +0 -30
  43. package/src/skills/configure-docs-index/SKILL.md +0 -243
  44. package/src/skills/configure-skills/SKILL.md +0 -311
  45. package/src/skills/generate-readme/EXAMPLES.md +0 -168
  46. package/src/skills/generate-readme/SKILL.md +0 -122
  47. package/src/skills/generate-readme/TEMPLATE.md +0 -141
  48. package/src/skills/use-index/SKILL.md +0 -49
  49. package/src/templates/ARCHITECTURE.md +0 -33
  50. package/src/templates/CONCERNS.md +0 -33
  51. package/src/templates/CONVENTIONS.md +0 -74
  52. package/src/templates/TESTING.md +0 -24
  53. package/src/templates/workflow/FIX-PLAN.md +0 -55
  54. package/src/templates/workflow/PLAN-COMPACT.md +0 -42
  55. package/src/templates/workflow/PLAN.md +0 -76
  56. package/src/templates/workflow/REVIEW-SUMMARY.md +0 -53
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: 5:review
3
- description: Reviews code changes via the built-in code-review skill. Categorizes findings and saves them for /5:address-review-findings.
3
+ description: Reviews code changes for correctness via the built-in code-review skill, for security via security-review when the diff is security-sensitive, and for standards via review-style. Categorizes findings and saves them for /5:address-review-findings.
4
4
  allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion, Agent, Skill, mcp__jetbrains__*
5
- argument-hint: [low|medium|high|max]
5
+ argument-hint: [low|medium|high|max] [since {fixed-point} files: {paths} feature: {name} dirty: {paths}]
6
6
  user-invocable: true
7
7
  model: sonnet
8
8
  ---
@@ -16,7 +16,9 @@ You do NOT apply fixes. Fix application is handled by /5:address-review-findings
16
16
 
17
17
  ## Step 1: Determine Scope
18
18
 
19
- Ask what to review:
19
+ When the arguments say `since {fixed-point} files: {paths} feature: {name} dirty: {paths}` — `/5:implement` passes this — review exactly those files' changes since that commit and skip the question. `/5:implement` runs this before it commits, so the changes are in the working tree. The working tree can also hold changes the user had before the run: in this scope, **drop every finding whose file is not in `{paths}`**, from every reviewer, before saving.
20
+
21
+ Otherwise ask what to review:
20
22
 
21
23
  1. Staged changes (`git diff --cached`)
22
24
  2. Unstaged changes (`git diff`)
@@ -36,7 +38,23 @@ Never pass `--fix` or `--comment`. This command only records findings; applying
36
38
  Skill(skill: "code-review", args: "{target} {effort}")
37
39
  ```
38
40
 
39
- Derive `{target}` from the scope answer: options 1-3 review the current working-tree diff (no target argument needed); option 4 passes the branch. Use the findings it reports.
41
+ Derive `{target}` from the scope answer: options 1-3 and the `since … files:` scope review the current working-tree diff (no target argument needed); option 4 passes the branch. Use the findings it reports.
42
+
43
+ **Security review** — when the diff touches authentication, authorization, user input handling, secrets, cryptography, or SQL/shell/path construction, and the built-in `security-review` skill is available, invoke it on the same scope:
44
+
45
+ ```text
46
+ Skill(skill: "security-review")
47
+ ```
48
+
49
+ Use the vulnerabilities it reports. Skip it for diffs that touch none of these areas.
50
+
51
+ **Standards review** — then invoke `review-style` in report-only mode. It checks the same changes against the repository's own standards and the style skills it lists, and repository standards win:
52
+
53
+ ```text
54
+ Skill(skill: "review-style", args: "{mode} report only")
55
+ ```
56
+
57
+ Derive `{mode}` from the scope answer: option 1 passes `staged`, option 2 `unstaged`, option 3 `uncommitted`, option 4 `{base-branch} committed only`, and the `since … files:` scope `{fixed-point} files: {paths}`.
40
58
 
41
59
  **Fallback path** — on Codex, or when the `code-review` skill is unavailable, spawn one review agent instead:
42
60
 
@@ -61,9 +79,11 @@ Manual Review:
61
79
  - file: {path}, line: {N}, description: {what}, severity: {level}
62
80
  ```
63
81
 
82
+ On Codex, or when the `review-style` skill cannot be invoked, read `.claude/skills/review-style/SKILL.md` and follow it with the same arguments.
83
+
64
84
  ## Step 3: Save Findings
65
85
 
66
- Determine feature name from the most recent `.5/features/*/state.json`, or ask the user.
86
+ Use the `feature:` argument when given. Otherwise use the feature of the most recently modified plan in `.5/planning/` — its `feature` frontmatter field, or its file name without `.md` — or ask the user.
67
87
 
68
88
  Write `.5/features/{feature-name}/review-findings-{YYYYMMDD-HHmmss}.md` using `.claude/templates/workflow/REVIEW-FINDINGS.md`.
69
89
 
@@ -81,9 +101,22 @@ When the findings come from the `code-review` skill, map its reported fields ont
81
101
  | the concrete fix, else `short_summary` | **Suggested Fix:** |
82
102
  | `failure_scenario` | **Original Reviewer Message:** |
83
103
 
104
+ Findings from `security-review` map to **Category:** `Fixable` when the fix is local, otherwise `Manual`, always with **Severity:** `error`; its explanation of the exploit goes into **Original Reviewer Message:**.
105
+
84
106
  Findings from the fallback path map directly: Fixable Issues, Questions, and Manual Review become their matching categories.
85
107
 
86
- Do not ask the user to edit action markers in the findings file. The findings file is the review record; `/5:address-review-findings` will present each finding interactively and record decisions separately.
108
+ Findings from `review-style` map like this. Leave out its Suppressed findings; a repository standard overrides them.
109
+
110
+ | Reported finding | Template field |
111
+ |---|---|
112
+ | ⛔️ hard breach of a repository standard | **Category:** `Fixable`, **Severity:** `error` |
113
+ | ⚠️ judgement call | **Category:** `Fixable`, **Severity:** `suggestion` |
114
+ | `path:line` | **File:**, **Line:** |
115
+ | ID, title, and what is wrong | **Description:** |
116
+ | the `→` fix | **Suggested Fix:** |
117
+ | the cited standards and rules | **Original Reviewer Message:** |
118
+
119
+ Do not ask the user to edit action markers in the findings file. The findings file is the review record; `/5:address-review-findings` decides on the findings and records the decisions separately.
87
120
 
88
121
  ## Step 4: Report and Hand Off
89
122
 
@@ -101,12 +134,7 @@ Findings saved at `.5/features/{feature-name}/review-findings-{timestamp}.md`
101
134
 
102
135
  If there are no findings, stop here.
103
136
 
104
- Otherwise ask the user directly whether to continue:
105
-
106
- - "Address these findings now?"
107
- - Options:
108
- 1. "Yes, run `/5:address-review-findings {feature-name}`" — decide on each finding interactively, then apply approved fixes
109
- 2. "No, stop here" — findings stay on disk for later
137
+ Otherwise hand off to `/5:address-review-findings {feature-name}`. It fixes the clear findings on its own, asks the user one question at a time only about real decisions, and then runs build, test, and lint.
110
138
 
111
- - If the user chooses yes: invoke `/5:address-review-findings {feature-name}`.
112
- - If the user chooses no: tell them to run `/5:address-review-findings {feature-name}` when they are ready, and stop.
139
+ - **Called by `/5:implement`** (the `since … files:` scope): run `/5:address-review-findings {feature-name} dirty: {dirty-paths}` right away. The user approved the plan, and these are the run's own files — except the dirty ones, which also hold the user's earlier work.
140
+ - **Started on its own:** the reviewed code may come from someone else's branch, and the fixes are followed by the project's build and test commands. Ask once: "Fix the clear findings on my own and then run build, test, and lint?" On yes, run it. On no, stop and tell the user they can run `/5:address-review-findings {feature-name}` (or `--interactive`) later.
@@ -13,7 +13,7 @@ You do NOT modify files manually. After reporting, you are DONE.
13
13
 
14
14
  # Synchronize Agent Runtimes
15
15
 
16
- Synchronizes user-generated content (skills, commands, agents, rules) between the Claude Code (`.claude/`) and Codex (`.codex/`) runtimes.
16
+ Synchronizes user-generated content (skills, commands, agents, rules) between the Claude Code (`.claude/`) and Codex (`.codex/`) runtimes. Codex reads only `AGENTS.md`, so Claude rules and agent references go into the foifi block there.
17
17
 
18
18
  ## Step 1: Locate the Sync Script
19
19
 
@@ -42,7 +42,7 @@ Read `.5/version.json` again. Compare the new `installedVersion` to the previous
42
42
 
43
43
  Run `git status` to show the files modified by the upgrade. Summarize the changes for the user using the correct runtime paths:
44
44
  - Claude Code installs typically update files in `.claude/commands/5/`, `.claude/skills/`, `.claude/hooks/`, `.claude/templates/`, `.claude/settings.json`, and `.5/version.json`
45
- - Codex installs typically update files in `.codex/skills/`, `.codex/templates/`, `.codex/references/`, `.codex/instructions.md`, and `.5/version.json`
45
+ - Codex installs typically update files in `.codex/skills/`, `.codex/templates/`, `.codex/references/`, and `.5/version.json`
46
46
 
47
47
  ## Step 5: Ask to Commit
48
48
 
@@ -67,7 +67,7 @@ Build the commit message by applying the pattern:
67
67
  Stage **only** the workflow-managed files shown in `git status`.
68
68
 
69
69
  - For Claude Code installs, this usually means files inside `.claude/commands/5/`, `.claude/skills/`, `.claude/hooks/`, `.claude/templates/`, `.claude/settings.json`, and `.5/version.json`
70
- - For Codex installs, this usually means files inside `.codex/skills/`, `.codex/templates/`, `.codex/references/`, `.codex/instructions.md`, and `.5/version.json`
70
+ - For Codex installs, this usually means files inside `.codex/skills/`, `.codex/templates/`, `.codex/references/`, and `.5/version.json`
71
71
 
72
72
  Never use `git add .` or `git add -A`.
73
73
 
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+ // Stop hook: when the uncommitted diff adds a dependency, make Claude justify it once
3
+ // before finishing. New dependencies are the most reliable, heuristic-free drift signal.
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { execFileSync } = require('child_process');
7
+
8
+ // Each extractor returns the dependency identities a manifest declares. The hook compares
9
+ // those sets with HEAD, so config edits and version bumps of existing packages never count.
10
+ const pep508Name = spec => (spec.trim().match(/^([A-Za-z0-9][A-Za-z0-9._-]*)/) || [])[1];
11
+ const normalizePy = name => name && name.toLowerCase().replace(/[_.]+/g, '-');
12
+ const jsonKeys = sections => text => { const json = JSON.parse(text); return sections.flatMap(s => Object.keys(json[s] || {})); };
13
+ const matchAll = (text, re, pick) => [...text.matchAll(re)].map(pick);
14
+
15
+ function requirementsDeps(text) {
16
+ return text.split('\n')
17
+ .map(l => l.replace(/#.*/, '').trim())
18
+ .filter(l => l && !l.startsWith('-'))
19
+ .map(l => normalizePy(pep508Name(l)))
20
+ .filter(Boolean);
21
+ }
22
+
23
+ // Minimal TOML walk for Cargo.toml, Pipfile, and pyproject.toml (PEP 621, PEP 735, Poetry).
24
+ function tomlDeps(text) {
25
+ const deps = [];
26
+ let section = '';
27
+ let inArray = false;
28
+ // Collects quoted specs; returns true once the array closes (a `]` outside quotes, not in "pkg[extra]").
29
+ const arrayLine = line => {
30
+ matchAll(line, /"([^"]+)"|'([^']+)'/g, m => normalizePy(pep508Name(m[1] || m[2]))).forEach(d => d && deps.push(d));
31
+ return line.replace(/"[^"]*"|'[^']*'/g, '').includes(']');
32
+ };
33
+
34
+ for (const raw of text.split('\n')) {
35
+ const line = raw.replace(/\s#.*$/, '').trim();
36
+ if (inArray) { inArray = !arrayLine(line); continue; }
37
+ const header = line.match(/^\[\[?([^\]]+)\]\]?$/);
38
+ if (header) {
39
+ section = header[1].trim();
40
+ const dotted = section.match(/(?:^|\.)(?:dependencies|dev-dependencies|build-dependencies)\.([^.]+)$/);
41
+ if (dotted) deps.push(dotted[1]); // Cargo: [dependencies.serde]
42
+ continue;
43
+ }
44
+ const key = (line.match(/^"?([A-Za-z0-9_.-]+)"?\s*=/) || [])[1];
45
+ if (!key) continue;
46
+ const arrayOfSpecs = (section === 'project' && key === 'dependencies') ||
47
+ section === 'project.optional-dependencies' || section === 'dependency-groups';
48
+ if (arrayOfSpecs && line.includes('[')) {
49
+ inArray = !arrayLine(line.slice(line.indexOf('[') + 1));
50
+ } else if (/(?:^|\.)(?:dependencies|dev-dependencies|build-dependencies|packages|dev-packages)$/.test(section) && key !== 'python') {
51
+ deps.push(key);
52
+ }
53
+ }
54
+ return deps;
55
+ }
56
+
57
+ function goModDeps(text) {
58
+ const deps = [];
59
+ let inBlock = false;
60
+ for (const raw of text.split('\n')) {
61
+ const line = raw.trim();
62
+ if (/^require\s*\($/.test(line)) { inBlock = true; continue; }
63
+ if (inBlock && line === ')') { inBlock = false; continue; }
64
+ if (line.includes('// indirect')) continue; // pulled in by tooling, not chosen
65
+ const spec = inBlock ? line : (line.match(/^require\s+(.+)$/) || [])[1];
66
+ const mod = spec && spec.split(/\s+/)[0];
67
+ if (mod && !mod.startsWith('//')) deps.push(mod);
68
+ }
69
+ return deps;
70
+ }
71
+
72
+ const EXTRACTORS = [
73
+ [/^package\.json$/, jsonKeys(['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'])],
74
+ [/^composer\.json$/, jsonKeys(['require', 'require-dev'])],
75
+ [/^requirements.*\.txt$/, requirementsDeps],
76
+ [/^(pyproject\.toml|Pipfile|Cargo\.toml)$/, tomlDeps],
77
+ [/^go\.mod$/, goModDeps],
78
+ [/^Gemfile$/, text => matchAll(text, /^\s*gem\s+['"]([^'"]+)['"]/gm, m => m[1])],
79
+ [/^pom\.xml$/, text => matchAll(text, /<dependency>([\s\S]*?)<\/dependency>/g, m =>
80
+ [/<groupId>([^<]+)</, /<artifactId>([^<]+)</].map(re => (m[1].match(re) || [])[1] || '?').join(':'))],
81
+ [/^build\.gradle(\.kts)?$/, text => matchAll(text,
82
+ /^\s*(?:implementation|api|compileOnly|runtimeOnly|testImplementation|testRuntimeOnly|annotationProcessor|kapt|ksp|classpath)\s*\(?\s*(?:['"]([^'":]+:[^'":]+)|(libs\.[\w.]+))/gm,
83
+ m => m[1] || m[2])],
84
+ [/\.csproj$/, text => matchAll(text, /<PackageReference\s+Include="([^"]+)"/gi, m => m[1])]
85
+ ];
86
+
87
+ function git(cwd, args) {
88
+ return execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
89
+ }
90
+
91
+ function headVersion(root, file) {
92
+ try { return git(root, ['show', `HEAD:${file}`]); } catch (e) { return null; }
93
+ }
94
+
95
+ function addedDependencies(root) {
96
+ const changed = git(root, ['diff', 'HEAD', '--name-only']).split('\n').filter(Boolean);
97
+ const untracked = git(root, ['ls-files', '--others', '--exclude-standard']).split('\n').filter(Boolean);
98
+ const found = [];
99
+
100
+ for (const file of new Set([...changed, ...untracked])) {
101
+ const extract = (EXTRACTORS.find(([re]) => re.test(path.basename(file))) || [])[1];
102
+ const abs = path.join(root, file);
103
+ if (!extract || !fs.existsSync(abs)) continue;
104
+ try {
105
+ const before = headVersion(root, file);
106
+ const old = new Set(before ? extract(before) : []);
107
+ extract(fs.readFileSync(abs, 'utf8'))
108
+ .filter(d => !old.has(d))
109
+ .forEach(d => found.push(`${d} (${file})`));
110
+ } catch (e) {
111
+ // Unparseable manifest (e.g. mid-edit JSON): skip this file, keep checking the others.
112
+ }
113
+ }
114
+ return [...new Set(found)];
115
+ }
116
+
117
+ let input = '';
118
+ process.stdin.setEncoding('utf8');
119
+ process.stdin.on('data', chunk => input += chunk);
120
+ process.stdin.on('end', () => {
121
+ try {
122
+ const data = JSON.parse(input);
123
+ if (data.stop_hook_active) process.exit(0); // Claude is already continuing because of a Stop hook
124
+
125
+ const root = git(data.cwd || process.cwd(), ['rev-parse', '--show-toplevel']).trim(); // git paths are root-relative
126
+ const deps = addedDependencies(root);
127
+ if (!deps.length) process.exit(0);
128
+
129
+ // Ask once per session and dependency set, so an accepted dependency doesn't nag on every stop.
130
+ const stateFile = path.join(root, '.5', '.dependency-guard.json');
131
+ const signature = `${data.session_id || ''}:${deps.slice().sort().join('|')}`;
132
+ let seen = [];
133
+ try { seen = JSON.parse(fs.readFileSync(stateFile, 'utf8')).signatures || []; } catch (e) { /* first run */ }
134
+ if (seen.includes(signature)) process.exit(0);
135
+ if (fs.existsSync(path.dirname(stateFile))) {
136
+ fs.writeFileSync(stateFile, JSON.stringify({ signatures: [...seen, signature].slice(-20) })); // concurrent sessions
137
+ }
138
+
139
+ process.stdout.write(JSON.stringify({
140
+ decision: 'block',
141
+ reason: `Uncommitted changes add dependencies:\n${deps.map(d => `- ${d}`).join('\n')}\n\n` +
142
+ 'For each one: if the user asked for it or added it themselves, keep it and name it in your reply. ' +
143
+ 'Otherwise remove it with the package manager (never edit a lockfile by hand) and use existing code, ' +
144
+ 'the standard library, a native platform feature, or an installed dependency instead.'
145
+ }));
146
+ process.exit(0);
147
+ } catch (e) {
148
+ process.exit(0); // Never block on errors (not a git repo, no HEAD, unparseable manifest)
149
+ }
150
+ });
@@ -103,9 +103,11 @@ process.stdin.on('end', () => {
103
103
  parts.push(`\x1b[35m↻ /5:reconfigure\x1b[0m`);
104
104
  }
105
105
 
106
- const migrationFlag = path.join(dir, '.5', '.migration-v2');
107
- if (fs.existsSync(migrationFlag)) {
108
- parts.push(`\x1b[31m⚠ v1→v2: /5:reconfigure\x1b[0m`);
106
+ // The installer writes .migration-v{major} after a major upgrade
107
+ const migrationFlag = fs.readdirSync(path.join(dir, '.5')).find(f => /^\.migration-v\d+$/.test(f));
108
+ if (migrationFlag) {
109
+ const major = migrationFlag.slice('.migration-'.length);
110
+ parts.push(`\x1b[31m⚠ ${major}: /5:reconfigure\x1b[0m`);
109
111
  }
110
112
  } catch (e) {}
111
113
 
@@ -37,33 +37,6 @@ Check files in this order (first match wins):
37
37
  | rust | `cargo build` | `cargo test` |
38
38
  | go | `go build ./...` | `go test ./...` |
39
39
 
40
- ## Codebase Pattern Categories to Scan
41
-
42
- Use Glob to scan for architectural patterns. For each, check both suffix-based (`*{Pattern}.{ts,js,java,py,rb}`) and directory-based (`{patterns}/**`) globs.
43
-
44
- - **Core:** Controllers, Services, Repositories, Models/Entities, Handlers
45
- - **Data Transfer:** DTOs, Requests, Responses, Mappers, Validators, Schemas
46
- - **Frontend:** Components, Hooks, Contexts, Stores, Pages, Layouts
47
- - **API/Routes:** API Routes, Middleware, Guards, Interceptors, Filters
48
- - **Testing:** Tests/Specs, Fixtures, Factories, Mocks
49
- - **Utilities:** Utils, Helpers, Constants, Types/Interfaces, Config
50
- - **Framework-Specific:** Modules, Pipes, Decorators, Blueprints, Views, Serializers
51
- - **Background/Async:** Jobs, Workers, Events, Listeners, Commands
52
- - **Database:** Migrations, Seeds
53
- - **Error Handling:** Exceptions, Errors
54
-
55
- For each pattern found: count matching files, identify primary location, sample 1 filename.
56
-
57
- ## Runnable Command Categories
58
-
59
- Scan config files (`package.json` scripts, `Makefile` targets, `pyproject.toml` scripts, `Cargo.toml`, `build.gradle` tasks, `composer.json` scripts, `Rakefile` tasks) for commands in these categories:
60
-
61
- Build, Test, Lint, Format, Type Check, Dev Server, Database (migrate/seed), Docker, Deploy, Clean, Generate
62
-
63
- Skill naming: `run-{category}` (e.g., `run-build`, `run-tests`, `run-lint`).
64
-
65
- For each command found: record exact syntax, note variants (e.g., `test:unit`, `test:e2e`), and environment requirements. Only include commands that are actually detected.
66
-
67
40
  ## Config Schema
68
41
 
69
42
  ```json
@@ -91,9 +64,6 @@ For each command found: record exact syntax, note variants (e.g., `test:unit`, `
91
64
  },
92
65
  "context7": {
93
66
  "available": false
94
- },
95
- "skillCreator": {
96
- "available": false
97
67
  }
98
68
  },
99
69
  "git": {
@@ -107,9 +77,6 @@ For each command found: record exact syntax, note variants (e.g., `test:unit`, `
107
77
  },
108
78
  "rules": {
109
79
  "generate": true
110
- },
111
- "conventions": {
112
- "generate": true
113
80
  }
114
81
  }
115
82
  ```
package/src/settings.json CHANGED
@@ -26,14 +26,13 @@
26
26
  ]
27
27
  }
28
28
  ],
29
- "PreToolUse": [
29
+ "Stop": [
30
30
  {
31
- "matcher": "Task|Agent",
32
31
  "hooks": [
33
32
  {
34
33
  "type": "command",
35
- "command": "node .claude/hooks/config-guard.js",
36
- "timeout": 5
34
+ "command": "node .claude/hooks/dependency-guard.js",
35
+ "timeout": 10
37
36
  }
38
37
  ]
39
38
  }
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: baseline-conventions
3
+ description: Baseline rules for errors, types, names and tests. They keep a codebase clean when the repository documents no rules of its own. Use when writing, refactoring or reviewing code.
4
+ ---
5
+
6
+ # Baseline conventions
7
+
8
+ These rules fill the gaps a repository leaves open. A repository standard always wins over them. Each rule reads
9
+ _what it is_ → _how to fix_:
10
+
11
+ ## Errors
12
+
13
+ - **Swallowed error**: an empty catch, or a catch that ignores the error. → Log it, rethrow it, or turn it into a typed result.
14
+ - **Unhandled async failure**: a promise or future whose failure path nobody handles. → Handle the failure where it is awaited, or pass it on to the caller.
15
+ - **Bare error message**: an error that carries only a string. → Use a typed error that carries the context a reader needs.
16
+ - **Errors as control flow**: an exception thrown for an expected case. → Check the case up front, or return a result.
17
+
18
+ ## Types and names
19
+
20
+ - **Untyped boundary**: a public function, exported type or data shape without an explicit type, where the language supports one. → Declare the type.
21
+ - **Escape hatch**: `any`, a non-null assertion or an unchecked cast. → Narrow the type. When it can't be avoided, say why in a comment.
22
+ - **Magic value**: a literal number or string whose meaning the reader must guess. → Give it a named constant.
23
+ - **Unclear boolean**: a boolean whose name doesn't read as a question. → Prefix it with `is`, `has`, `can` or `should`.
24
+
25
+ ## Tests
26
+
27
+ - **Mixed test**: one test that checks several behaviours. → Split it, so each test checks one behaviour.
28
+ - **Method-named test**: a test named after the method it calls. → Name it after the behaviour, such as `returns 404 when the user is missing`.
29
+ - **Weak assertion**: an assertion that only checks a value exists, or that can't fail. → Assert the actual value or outcome.
30
+ - **Tangled test**: setup, action and checks are mixed together. → Order them as arrange, act, assert.
31
+ - **Internal mock**: a mock of an internal module or a pure function. → Mock only at system boundaries such as network, database, filesystem and clock. Test the rest directly.
32
+ - **Silent skip**: a disabled test with no reason. → Fix it, delete it, or link the issue that tracks it.
33
+ - **Unprotected bug fix**: a fix that no test guards. → Add a regression test that fails without the fix, when practical.
34
+
35
+ ## Leftovers
36
+
37
+ - **Commented-out code**: code kept alive in a comment. → Delete it. Version control keeps the history.
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: cognitive-load
3
+ description: Rules for keeping the cognitive load of code low. Use when writing, refactoring or reviewing code.
4
+ ---
5
+
6
+ # Cognitive load
7
+
8
+ Cognitive load is how much a reader must hold in mind to understand the code. Working memory holds about
9
+ **four chunks**: a variable's value, a branch taken, a call to chase, a mapping to remember. Past four, the
10
+ reader loses the thread.
11
+
12
+ _Intrinsic_ load comes from the problem itself and stays. _Extraneous_ load comes from how the code is
13
+ written. The rules below cut extraneous load.
14
+
15
+ ## Rules
16
+
17
+ - **Named conditions.** Give the parts of a compound condition intermediate variables named after what they
18
+ mean. The `if` then reads as one chunk:
19
+ ```java
20
+ var isFresh = price.timestamp().isAfter(cutoff);
21
+ var isKnownVendor = vendors.contains(price.vendor());
22
+ if (isFresh && isKnownVendor) { ... }
23
+ ```
24
+ - **Early returns.** Handle invalid cases with guard clauses at the top. The happy path then runs
25
+ unindented. Nesting makes the reader carry every outer condition along.
26
+ - **Composition over inheritance.** Deep inheritance chains make the reader trace behaviour across levels.
27
+ A change in a parent can silently break a child.
28
+ - **Deep modules.** A module earns its place with a simple interface over substantial behaviour. Many
29
+ shallow modules whose interface is as complex as their body are tiring to navigate. Merge them.
30
+ - **Important logic can be large.** Keep the crux of a feature in one substantial function. Splitting it
31
+ into many tiny hops hides it.
32
+ - **One stakeholder per module.** A module answers to one user or one concern. "Does one thing" is too vague
33
+ to judge.
34
+ - **Plain language subset.** Use constructs any developer of the language reads fluently. A clever feature
35
+ makes the reader learn the feature before the code.
36
+ - **Self-describing values.** Prefer names, enums and descriptive strings over codes that need a lookup
37
+ table. Return `"jwt_has_expired"` rather than relying on HTTP status `401` vs `403`. Keep business meaning
38
+ out of transport details.
39
+ - **Plain terms.** Name things with the plainest accurate words, in the problem's own language. Reuse terms
40
+ already in the codebase.
41
+ - **Duplication over coupling.** A few copied lines beat a premature shared abstraction that couples
42
+ unrelated code. Every dependency is code the reader may have to debug.
43
+ - **Framework at the edge.** Core logic uses the framework like a library. It stays readable to someone who
44
+ doesn't know the framework's magic.
45
+ - **Layers only where they hide something.** Add an abstraction only at a real extension point. A layer that
46
+ only forwards calls is pure indirection.
47
+ - **Boring over clever.** Pick the straightforward solution. Debugging is twice as hard as writing the code.
48
+ - **Familiar is not simple.** Code feels simple to its author. Judge it as a newcomer would. If a newcomer
49
+ stays confused for about 40 minutes, the code needs work.
50
+
51
+ Source: Artem Zakirullin, [Cognitive load is what matters](https://github.com/zakirullin/cognitive-load),
52
+ CC BY 4.0. Condensed and adapted.
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: configure-agents-md
3
+ description: Writes the workflow rules into AGENTS.md as one marked block, links the repository's own standards, and makes CLAUDE.md include AGENTS.md. Never changes content outside the block. Used during /5:implement CONFIGURE and /5:reconfigure.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ model: sonnet
6
+ user-invocable: false
7
+ ---
8
+
9
+ # Configure AGENTS.md Skill
10
+
11
+ ## Overview
12
+
13
+ This skill writes the workflow rules into `AGENTS.md` as one block between `<!-- foifi:start` and `<!-- foifi:end -->`. Everything outside that block belongs to the repository. The skill never rewrites, moves, or deletes it, in `AGENTS.md` or in `CLAUDE.md`.
14
+
15
+ A step executor calls it for the CONFIGURE feature. `/5:reconfigure` calls it in refresh mode. Both modes run the same steps:
16
+
17
+ - **Full mode (default):** input is the plan at `.5/planning/CONFIGURE.md`.
18
+ - **Refresh mode:** the prompt includes "REFRESH MODE" and points at `.5/reconfigure-manifest.json`.
19
+
20
+ It generates no architecture, testing, concerns, or conventions docs and no codebase index. Agents explore the code themselves.
21
+
22
+ ## 1. Collect Inputs
23
+
24
+ - **Build and run commands:** from `.5/config.json`, plus other detected scripts worth running. Skip commands that `AGENTS.md` or `CLAUDE.md` already document outside the block.
25
+ - **Commit message rule:** the repository's own commit convention when one is documented, such as in `CONTRIBUTING.md`. Then write `Follow the commit convention in {path}.` Otherwise use `git.commitMessage.pattern` from `.5/config.json` and write `Write commit messages as \`{pattern}\`. Take {ticket-id} from the branch name when it matches \`ticket.pattern\`; drop it otherwise.` Without a pattern, remove the `## Commit Messages` section.
26
+ - **Repository standards:** the files `.claude/skills/review-style/SKILL.md` step 2 counts as repository standards. Use the list in the CONFIGURE plan or the refresh manifest when it has one. Do not count workflow-generated files.
27
+ - **Existing project docs:** `.5/ARCHITECTURE.md`, `.5/TESTING.md`, `.5/CONCERNS.md`, and `.5/CONVENTIONS.md`, when they exist. Link them; never rewrite or delete them.
28
+
29
+ ## 2. Fill the Template
30
+
31
+ Use `.claude/templates/AGENTS.md` as the block. Keep its marker comments and static sections exactly as written; `review-style` reads the markers to tell workflow rules apart from repository standards.
32
+
33
+ - `{BUILD_RUN_COMMANDS}` → the build, test, and other commands. Remove the section when there are none left.
34
+ - `{COMMIT_MESSAGE_RULE}` → the commit message rule.
35
+ - `{REPO_STANDARDS_LINKS}` → one bullet per repository standard, as `- [path](path)`. When there are none, write `- None documented yet. The style skills below set the baseline.`
36
+ - `{PROJECT_DOCUMENTATION_LINKS}` → one link per existing `.5/*.md` doc. When there are none, remove the whole `## Project Documentation` section.
37
+
38
+ ## 3. Write AGENTS.md
39
+
40
+ - **No `AGENTS.md`:** create it with only the block.
41
+ - **`AGENTS.md` with a foifi block:** replace the text from the `<!-- foifi:start` line through the `<!-- foifi:end -->` line. Keep any `<!-- 5-sync:rules-start -->` … `<!-- 5-sync:rules-end -->` and `<!-- 5-sync:agents-start -->` … `<!-- 5-sync:agents-end -->` sections inside the old block unchanged, just before the new `<!-- foifi:end -->`: `configure-rules` and `/5:synchronize-agents` own them. Leave every other byte unchanged.
42
+ - **`AGENTS.md` without a block:** append a blank line and the block at the end. Leave the existing content unchanged.
43
+ - **Legacy file** (its first line starts with `<!-- Generated from the foifi AGENTS.md template`): an earlier version generated the whole file. Keep only what the user wrote: the content under its `## Custom Documentation` heading, unchanged. Write that content, then a blank line, then the block. Drop the rest; the block replaces it.
44
+
45
+ ## 4. Include AGENTS.md from CLAUDE.md (Claude Code only)
46
+
47
+ Claude Code reads `CLAUDE.md`, and `@AGENTS.md` pulls in the full `AGENTS.md`.
48
+
49
+ - **No `CLAUDE.md`:** create it with only `@AGENTS.md`.
50
+ - **`CLAUDE.md` without an `@AGENTS.md` line:** append a blank line and `@AGENTS.md`. Leave the existing content unchanged.
51
+ - **`CLAUDE.md` with an `@AGENTS.md` line:** leave it as it is.
52
+
53
+ ## Output Contract
54
+
55
+ ```
56
+ Component A (AGENTS.md): SUCCESS - Wrote the foifi block in AGENTS.md
57
+ - AGENTS.md (block replaced | appended | created, 3 repository standards linked)
58
+ - CLAUDE.md (unchanged | @AGENTS.md appended | created)
59
+ ```
60
+
61
+ Or on failure:
62
+
63
+ ```
64
+ Component A (AGENTS.md): FAILED - Unable to read the AGENTS.md template
65
+ ```
66
+
67
+ ## DO NOT
68
+
69
+ - DO NOT change, move, or delete anything outside the foifi block, in `AGENTS.md` or `CLAUDE.md`.
70
+ - DO NOT generate architecture, testing, concerns, or conventions docs, index files, or rebuild scripts.
71
+ - DO NOT rewrite or delete existing `.5/*.md` docs.
72
+ - DO NOT restate repository standards in the block. Link them.