@phuc1403/musketeer 0.5.0 → 0.7.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/INSTALLATION.md +52 -32
- package/bin/musketeer.js +168 -79
- package/manifest.json +9 -9
- package/package.json +48 -46
- package/src/dotnet-scaffold-copier.js +79 -72
- package/src/provisioner/detect.js +93 -93
- package/src/self-update.js +77 -73
- package/template/.claude/hooks/block-unsafe-adr-title.cjs +85 -70
- package/template/.claude/hooks/init-adr-dir.cjs +173 -110
- package/template/.claude/hooks/inject-adr-flags.cjs +94 -0
- package/template/.claude/hooks/lib/adr/command-scan.cjs +115 -0
- package/template/.claude/hooks/sync-adr-toc.cjs +146 -111
- package/template/.claude/skills/adr-writer/SKILL.md +48 -46
- package/template/.claude/hooks/inject-adr-env.cjs +0 -82
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/__SolutionName__.Api.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/__SolutionName__.Api.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/__SolutionName__.Api.GeneratedMSBuildEditorConfig.editorconfig +0 -23
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/__SolutionName__.Api.GlobalUsings.g.cs +0 -17
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/Debug/net10.0/__SolutionName__.Api.assets.cache +0 -0
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/__SolutionName__.Api.csproj.nuget.dgspec.json +0 -1536
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/__SolutionName__.Api.csproj.nuget.g.props +0 -16
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/__SolutionName__.Api.csproj.nuget.g.targets +0 -2
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/project.assets.json +0 -559
- package/template/dotnet-scaffold/src/__SolutionName__.Api/obj/project.nuget.cache +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/__SolutionName__.Application.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/__SolutionName__.Application.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/__SolutionName__.Application.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/__SolutionName__.Application.GlobalUsings.g.cs +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/Debug/net10.0/__SolutionName__.Application.assets.cache +0 -0
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/__SolutionName__.Application.csproj.nuget.dgspec.json +0 -690
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/__SolutionName__.Application.csproj.nuget.g.props +0 -16
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/__SolutionName__.Application.csproj.nuget.g.targets +0 -2
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/project.assets.json +0 -376
- package/template/dotnet-scaffold/src/__SolutionName__.Application/obj/project.nuget.cache +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/__SolutionName__.Domain.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/__SolutionName__.Domain.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/__SolutionName__.Domain.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/__SolutionName__.Domain.GlobalUsings.g.cs +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/Debug/net10.0/__SolutionName__.Domain.assets.cache +0 -0
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/__SolutionName__.Domain.csproj.nuget.dgspec.json +0 -347
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/__SolutionName__.Domain.csproj.nuget.g.props +0 -16
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/__SolutionName__.Domain.csproj.nuget.g.targets +0 -2
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/project.assets.json +0 -353
- package/template/dotnet-scaffold/src/__SolutionName__.Domain/obj/project.nuget.cache +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.GlobalUsings.g.cs +0 -8
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.assets.cache +0 -0
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/Debug/net10.0/__SolutionName__.Infrastructure.csproj.AssemblyReference.cache +0 -0
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/__SolutionName__.Infrastructure.csproj.nuget.dgspec.json +0 -1047
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/__SolutionName__.Infrastructure.csproj.nuget.g.props +0 -16
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/__SolutionName__.Infrastructure.csproj.nuget.g.targets +0 -7
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/project.assets.json +0 -858
- package/template/dotnet-scaffold/src/__SolutionName__.Infrastructure/obj/project.nuget.cache +0 -17
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/bin/Debug/net10.0/.msCoverageSourceRootsMapping___SolutionName__.Api.Tests +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.GlobalUsings.g.cs +0 -9
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.assets.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/Debug/net10.0/__SolutionName__.Api.Tests.csproj.AssemblyReference.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/__SolutionName__.Api.Tests.csproj.nuget.dgspec.json +0 -1908
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/__SolutionName__.Api.Tests.csproj.nuget.g.props +0 -27
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/__SolutionName__.Api.Tests.csproj.nuget.g.targets +0 -16
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/project.assets.json +0 -3283
- package/template/dotnet-scaffold/tests/__SolutionName__.Api.Tests/obj/project.nuget.cache +0 -60
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/bin/Debug/net10.0/.msCoverageSourceRootsMapping___SolutionName__.Application.Tests +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.GlobalUsings.g.cs +0 -9
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.assets.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/Debug/net10.0/__SolutionName__.Application.Tests.csproj.AssemblyReference.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/__SolutionName__.Application.Tests.csproj.nuget.dgspec.json +0 -1055
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/__SolutionName__.Application.Tests.csproj.nuget.g.props +0 -26
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/__SolutionName__.Application.Tests.csproj.nuget.g.targets +0 -11
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/project.assets.json +0 -1662
- package/template/dotnet-scaffold/tests/__SolutionName__.Application.Tests/obj/project.nuget.cache +0 -30
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/bin/Debug/net10.0/.msCoverageSourceRootsMapping___SolutionName__.Domain.Tests +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.GlobalUsings.g.cs +0 -9
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.assets.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/Debug/net10.0/__SolutionName__.Domain.Tests.csproj.AssemblyReference.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/__SolutionName__.Domain.Tests.csproj.nuget.dgspec.json +0 -712
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/__SolutionName__.Domain.Tests.csproj.nuget.g.props +0 -26
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/__SolutionName__.Domain.Tests.csproj.nuget.g.targets +0 -11
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/project.assets.json +0 -1644
- package/template/dotnet-scaffold/tests/__SolutionName__.Domain.Tests/obj/project.nuget.cache +0 -30
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/bin/Debug/net10.0/.msCoverageSourceRootsMapping___SolutionName__.Infrastructure.Tests +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs +0 -4
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.AssemblyInfo.cs +0 -22
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.AssemblyInfoInputs.cache +0 -1
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.GeneratedMSBuildEditorConfig.editorconfig +0 -17
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.GlobalUsings.g.cs +0 -9
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.assets.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/Debug/net10.0/__SolutionName__.Infrastructure.Tests.csproj.AssemblyReference.cache +0 -0
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/__SolutionName__.Infrastructure.Tests.csproj.nuget.dgspec.json +0 -1412
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/__SolutionName__.Infrastructure.Tests.csproj.nuget.g.props +0 -26
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/__SolutionName__.Infrastructure.Tests.csproj.nuget.g.targets +0 -13
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/project.assets.json +0 -2130
- package/template/dotnet-scaffold/tests/__SolutionName__.Infrastructure.Tests/obj/project.nuget.cache +0 -38
|
@@ -1,111 +1,146 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// PostToolUse hook: after any `adr` command, rebuild docs/adr/README.md from the
|
|
3
|
-
// ADR files themselves — one row per ADR with its title and current status.
|
|
4
|
-
//
|
|
5
|
-
// The index is fully derived, so it can never drift: every run re-reads the
|
|
6
|
-
// source. That is why there is no need to be clever about which adr subcommand
|
|
7
|
-
// ran, or to protect the file from being rewritten.
|
|
8
|
-
//
|
|
9
|
-
// Also
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'
|
|
71
|
-
''
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'',
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// PostToolUse hook: after any `adr` command, rebuild docs/adr/README.md from the
|
|
3
|
+
// ADR files themselves — one row per ADR with its title and current status.
|
|
4
|
+
//
|
|
5
|
+
// The index is fully derived, so it can never drift: every run re-reads the
|
|
6
|
+
// source. That is why there is no need to be clever about which adr subcommand
|
|
7
|
+
// ran, or to protect the file from being rewritten.
|
|
8
|
+
//
|
|
9
|
+
// Also deletes the tool's own `decisions.md`. Every `adr new` regenerates that
|
|
10
|
+
// file unconditionally (not just on `adr generate toc`), which would leave two
|
|
11
|
+
// competing indexes side by side in the same directory. README.md is the richer
|
|
12
|
+
// one — it carries a status column — so it is the one kept.
|
|
13
|
+
//
|
|
14
|
+
// Also runnable directly: node sync-adr-toc.cjs --write
|
|
15
|
+
//
|
|
16
|
+
// Fails open at exit 0 on any problem — a hook must never block a session.
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
22
|
+
const ADR_FILE = /^\d+-.*\.md$/;
|
|
23
|
+
|
|
24
|
+
// The tool reads its directory from a committed `.adr-dir` (default `doc/adr`).
|
|
25
|
+
function adrDir() {
|
|
26
|
+
try {
|
|
27
|
+
return fs.readFileSync(path.join(root, '.adr-dir'), 'utf8').trim() || 'doc/adr';
|
|
28
|
+
} catch {
|
|
29
|
+
return 'doc/adr';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Was this Bash call an adr command? (`adr new -q …` counts; a hyphenated name
|
|
34
|
+
// such as `adr-new` does not, hence the required whitespace.)
|
|
35
|
+
function isAdrCommand() {
|
|
36
|
+
try {
|
|
37
|
+
const payload = JSON.parse(fs.readFileSync(0, 'utf8'));
|
|
38
|
+
return /\badr\s/.test(payload?.tool_input?.command || '');
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// First line, minus the leading "# " and the tool's own number prefix — the
|
|
45
|
+
// template renders "# 12: Use X over Y" for 0012-….md. Dropping the unpadded 12
|
|
46
|
+
// keeps the padded
|
|
47
|
+
// stem in the ADR column the only number in the file, so nothing here can be
|
|
48
|
+
// mistaken for the stem `adr new -s` expects.
|
|
49
|
+
function title(body, fallback) {
|
|
50
|
+
const first = body.split(/\r?\n/)[0] || '';
|
|
51
|
+
return first.replace(/^#\s*(\d+\s*[:.]\s*)?/, '').trim() || fallback;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// First non-empty line of the `## Status` section. The tool maintains this:
|
|
55
|
+
// "Accepted", or "Superseded by [4: …](0004-….md)" after `adr new -s`.
|
|
56
|
+
function status(body) {
|
|
57
|
+
const lines = body.split(/\r?\n/);
|
|
58
|
+
const start = lines.findIndex((l) => /^##\s+Status\s*$/i.test(l));
|
|
59
|
+
if (start === -1) return 'Unknown';
|
|
60
|
+
for (const line of lines.slice(start + 1)) {
|
|
61
|
+
if (/^##\s/.test(line)) break;
|
|
62
|
+
if (line.trim()) return line.trim();
|
|
63
|
+
}
|
|
64
|
+
return 'Unknown';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function render(dir, files) {
|
|
68
|
+
const rows = files.map((name) => {
|
|
69
|
+
const body = fs.readFileSync(path.join(root, dir, name), 'utf8');
|
|
70
|
+
const stem = name.replace(/\.md$/, ''); // padded — what `adr new -s` needs
|
|
71
|
+
const cell = (s) => s.replace(/\|/g, '\\|'); // never break the table
|
|
72
|
+
return `| [${stem}](./${name}) | ${cell(title(body, stem))} | ${cell(status(body))} |`;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
'# Architecture Decision Records',
|
|
77
|
+
'',
|
|
78
|
+
'Generated from the ADR files by the `sync-adr-toc` hook — do not hand-edit.',
|
|
79
|
+
'',
|
|
80
|
+
'| ADR | Title | Status |',
|
|
81
|
+
'|-----|-------|--------|',
|
|
82
|
+
...rows,
|
|
83
|
+
'',
|
|
84
|
+
].join('\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// The tool writes its own table of contents to `<adr-dir>/decisions.md` on every
|
|
88
|
+
// `adr new`. README.md supersedes it, so drop it rather than commit two indexes
|
|
89
|
+
// that have to agree with each other.
|
|
90
|
+
//
|
|
91
|
+
// Only ever deletes a file that is recognisably that generated index: the exact
|
|
92
|
+
// heading it writes, followed by nothing but link lines. `decisions.md` is an
|
|
93
|
+
// ordinary name for a hand-written decision log, and deleting one of those on
|
|
94
|
+
// the next `adr new` would destroy work no backup covers.
|
|
95
|
+
const GENERATED_TOC = /^# Table of Contents\r?\n\r?\n(?:- \[[^\]]*\]\([^)]*\)\r?\n?)*$/;
|
|
96
|
+
|
|
97
|
+
function removeRedundantToc(dir) {
|
|
98
|
+
const stale = path.join(root, dir, 'decisions.md');
|
|
99
|
+
try {
|
|
100
|
+
if (!fs.existsSync(stale)) return;
|
|
101
|
+
if (!GENERATED_TOC.test(fs.readFileSync(stale, 'utf8'))) {
|
|
102
|
+
process.stdout.write(
|
|
103
|
+
`Left ${dir}/decisions.md alone — it is not the generated index. ` +
|
|
104
|
+
'README.md is the one this hook maintains.\n'
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
fs.unlinkSync(stale);
|
|
109
|
+
process.stdout.write(`Removed ${dir}/decisions.md (README.md is the index).\n`);
|
|
110
|
+
} catch {
|
|
111
|
+
/* not worth failing the hook over */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function main() {
|
|
116
|
+
if (!process.argv.includes('--write') && !isAdrCommand()) return;
|
|
117
|
+
|
|
118
|
+
const dir = adrDir();
|
|
119
|
+
removeRedundantToc(dir);
|
|
120
|
+
const files = fs
|
|
121
|
+
.readdirSync(path.join(root, dir))
|
|
122
|
+
.filter((f) => ADR_FILE.test(f))
|
|
123
|
+
.sort();
|
|
124
|
+
if (files.length === 0) return;
|
|
125
|
+
|
|
126
|
+
const target = path.join(root, dir, 'README.md');
|
|
127
|
+
const next = render(dir, files);
|
|
128
|
+
|
|
129
|
+
let current = null;
|
|
130
|
+
try {
|
|
131
|
+
current = fs.readFileSync(target, 'utf8');
|
|
132
|
+
} catch {
|
|
133
|
+
/* no index yet */
|
|
134
|
+
}
|
|
135
|
+
if (current === next) return; // already in sync
|
|
136
|
+
|
|
137
|
+
fs.writeFileSync(target, next);
|
|
138
|
+
process.stdout.write(`Regenerated ${dir}/README.md (${files.length} ADRs).\n`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
main();
|
|
143
|
+
} catch {
|
|
144
|
+
/* fail open */
|
|
145
|
+
}
|
|
146
|
+
process.exit(0);
|
|
@@ -1,46 +1,48 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: adr-writer
|
|
3
|
-
description: Write and manage Architecture Decision Records (ADRs) following structured methodology with proper numbering, status tracking, governance, and conversational writing style.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ADR Writer
|
|
7
|
-
|
|
8
|
-
Write Architecture Decision Records — the log of "architecturally significant" decisions affecting structure, non-functional characteristics, dependencies, interfaces, or construction techniques.
|
|
9
|
-
|
|
10
|
-
**Scope:** Create, update, and supersede ADRs. Does NOT implement the decisions themselves.
|
|
11
|
-
|
|
12
|
-
## Workflow
|
|
13
|
-
|
|
14
|
-
1. **Read the context.** `docs/architecture-characteristics.md` — every Decision is justified against these, with trade-offs framed as which are favored vs. sacrificed. If it is missing, read `.claude/skills/architecture-characteristic-writer/SKILL.md` and use its questions to gather the driving characteristics from the user before going on. Then read `docs/adr/README.md` for the decisions already recorded — one ADR's Consequences are often the next one's Context.
|
|
15
|
-
|
|
16
|
-
2. **Research before suggesting** — REQUIRED whenever a technology, vendor, product, version, or price is in play. Invoke `/research`; never propose options from memory, it goes stale. Confirm each option still exists and is supported today. Report in one pass, source and verdict per option.
|
|
17
|
-
|
|
18
|
-
3. **Challenge the proposal — be harsh.** REQUIRED whenever the user proposes a specific option. Do not rubber-stamp it:
|
|
19
|
-
- **State why** — the concrete reasons, not familiarity or preference.
|
|
20
|
-
- **Score it against each driving and implicit characteristic** — does it *serve*, *ignore*, or *actively harm* it?
|
|
21
|
-
- **Give a verdict** — suitable / suitable-with-trade-offs / unsuitable. If it conflicts with a driving characteristic, say so plainly and recommend the better fit, even when that is not what was asked for.
|
|
22
|
-
- Continue only once it survives, or the user overrides knowing the trade-off — record that override as a Consequence.
|
|
23
|
-
|
|
24
|
-
4. **Create the file.** From the repo root:
|
|
25
|
-
```bash
|
|
26
|
-
adr new -- "Use X for Z"
|
|
27
|
-
```
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
1
|
+
---
|
|
2
|
+
name: adr-writer
|
|
3
|
+
description: Write and manage Architecture Decision Records (ADRs) following structured methodology with proper numbering, status tracking, governance, and conversational writing style.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ADR Writer
|
|
7
|
+
|
|
8
|
+
Write Architecture Decision Records — the log of "architecturally significant" decisions affecting structure, non-functional characteristics, dependencies, interfaces, or construction techniques.
|
|
9
|
+
|
|
10
|
+
**Scope:** Create, update, and supersede ADRs. Does NOT implement the decisions themselves.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
1. **Read the context.** `docs/architecture-characteristics.md` — every Decision is justified against these, with trade-offs framed as which are favored vs. sacrificed. If it is missing, read `.claude/skills/architecture-characteristic-writer/SKILL.md` and use its questions to gather the driving characteristics from the user before going on. Then read `docs/adr/README.md` for the decisions already recorded — one ADR's Consequences are often the next one's Context.
|
|
15
|
+
|
|
16
|
+
2. **Research before suggesting** — REQUIRED whenever a technology, vendor, product, version, or price is in play. Invoke `/research`; never propose options from memory, it goes stale. Confirm each option still exists and is supported today. Report in one pass, source and verdict per option.
|
|
17
|
+
|
|
18
|
+
3. **Challenge the proposal — be harsh.** REQUIRED whenever the user proposes a specific option. Do not rubber-stamp it:
|
|
19
|
+
- **State why** — the concrete reasons, not familiarity or preference.
|
|
20
|
+
- **Score it against each driving and implicit characteristic** — does it *serve*, *ignore*, or *actively harm* it?
|
|
21
|
+
- **Give a verdict** — suitable / suitable-with-trade-offs / unsuitable. If it conflicts with a driving characteristic, say so plainly and recommend the better fit, even when that is not what was asked for.
|
|
22
|
+
- Continue only once it survives, or the user overrides knowing the trade-off — record that override as a Consequence.
|
|
23
|
+
|
|
24
|
+
4. **Create the file.** From the repo root:
|
|
25
|
+
```bash
|
|
26
|
+
adr new -q -- "Use X for Z"
|
|
27
|
+
```
|
|
28
|
+
- `-q` is required on every call. Without it an ambiguous `-s` prompts on stdin and hangs the session; with it, that case errors instead.
|
|
29
|
+
- `adr new` prints nothing. Run `adr list` (last line is the new file) or read `docs/adr/README.md` — never guess the number or slug.
|
|
30
|
+
- Never use uppercase `STATUS` in a title. It is substituted after the title is inserted, so "Use STATUS codes" silently becomes "Use Accepted codes" and leaves the real Status unset. Lowercase is fine.
|
|
31
|
+
- Superseding — always the full padded stem, never a bare number. `-s` matches by substring: with `-q` an *ambiguous* match errors, but a single *wrong* match still succeeds silently. Writes the cross-link into both ADRs' `## Status`:
|
|
32
|
+
```bash
|
|
33
|
+
adr new -q -s 0002-use-mysql-for-persistence -- "…"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
5. **Write the ADR.** Replace every `{…}` placeholder — nothing else. `adr new` has already written the number, title, `Accepted` status, and any supersede/link lines; leave all of them alone. Section Guidance below covers what each section needs. An Accepted ADR is immutable — to change it, write a new ADR that supersedes it.
|
|
37
|
+
|
|
38
|
+
## Writing Style
|
|
39
|
+
|
|
40
|
+
- **Calibrate against `references/adr-example.md`** — re-read it before drafting; it is the target for terseness. Cut any section markedly longer than its equivalent.
|
|
41
|
+
- **Match `references/adr-template.md` exactly.** Use only the sections it defines. No invented sections or fields; research citations go inline in the Decision.
|
|
42
|
+
|
|
43
|
+
## Section Guidance
|
|
44
|
+
|
|
45
|
+
- **Title** — reveal the *decision*, not the topic: "Use X for Z". Bad: "Gmail Polling for Ingestion". Good: "Use Cloud Scheduler Polling for Gmail Ingestion".
|
|
46
|
+
- **Context** — value-neutral, tensions explicit. No alternatives here, and no notes about what is *not* being decided.
|
|
47
|
+
- **Decision** — record the WHY, not the HOW — omit libraries, drivers, and wiring.
|
|
48
|
+
- **Consequences** — both `### Positive` and `### Negative` required. Consider team, infrastructure, cost, and one-way doors.
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// PreToolUse guard: inject the env vars every `adr new` call needs, so the
|
|
3
|
-
// agent can write a bare `adr new -- "Title"` and get a correct command.
|
|
4
|
-
//
|
|
5
|
-
// VISUAL=true EDITOR=true — without them an ambient EDITOR opens an
|
|
6
|
-
// interactive editor and hangs the session (adr-new always shells out to
|
|
7
|
-
// $VISUAL/$EDITOR to "edit" the new file).
|
|
8
|
-
// ADR_TEMPLATE=...adr-template.md — points adr-new at this skill's template
|
|
9
|
-
// instead of adr-tools' own bundled default.
|
|
10
|
-
//
|
|
11
|
-
// Uses PreToolUse's `updatedInput` (not just allow/deny) to rewrite the
|
|
12
|
-
// command before it runs. Only fills in vars that are missing — an assignment
|
|
13
|
-
// the agent already wrote (any value, even a deliberately different template)
|
|
14
|
-
// is left alone. Silent no-op if all three are already present.
|
|
15
|
-
//
|
|
16
|
-
// Safety: a title that happens to contain the literal text "adr new" could
|
|
17
|
-
// make the matching regex fire inside a quoted string. Guarded by counting
|
|
18
|
-
// quote characters before each match — an odd count means "inside an open
|
|
19
|
-
// string", and that occurrence is left untouched rather than risk corrupting
|
|
20
|
-
// the title.
|
|
21
|
-
|
|
22
|
-
const fs = require('fs');
|
|
23
|
-
|
|
24
|
-
const DEFAULTS = [
|
|
25
|
-
['ADR_TEMPLATE', '.claude/skills/adr-writer/references/adr-template.md'],
|
|
26
|
-
['VISUAL', 'true'],
|
|
27
|
-
['EDITOR', 'true'],
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
// boundary/start, leading whitespace, any existing KEY=value prefix, `adr new`.
|
|
31
|
-
const ADR_NEW_RE = /(^|[;&|\n])([ \t]*)((?:[A-Za-z_][A-Za-z0-9_]*=(?:'[^']*'|"[^"]*"|\S*)[ \t]+)*)(adr[ \t]+new\b)/g;
|
|
32
|
-
|
|
33
|
-
function existingVars(prefix) {
|
|
34
|
-
const names = new Set();
|
|
35
|
-
const re = /([A-Za-z_][A-Za-z0-9_]*)=/g;
|
|
36
|
-
let m;
|
|
37
|
-
while ((m = re.exec(prefix))) names.add(m[1]);
|
|
38
|
-
return names;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function isInsideQuotes(command, index) {
|
|
42
|
-
const before = command.slice(0, index);
|
|
43
|
-
const dq = (before.match(/"/g) || []).length;
|
|
44
|
-
const sq = (before.match(/'/g) || []).length;
|
|
45
|
-
return dq % 2 === 1 || sq % 2 === 1;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function main() {
|
|
49
|
-
const payload = JSON.parse(fs.readFileSync(0, 'utf8'));
|
|
50
|
-
const command = payload?.tool_input?.command || '';
|
|
51
|
-
if (!/\badr\s+new\b/.test(command)) return;
|
|
52
|
-
|
|
53
|
-
let changed = false;
|
|
54
|
-
const updated = command.replace(ADR_NEW_RE, (whole, boundary, ws, existingPrefix, adrNew, offset) => {
|
|
55
|
-
if (isInsideQuotes(command, offset)) return whole;
|
|
56
|
-
const present = existingVars(existingPrefix);
|
|
57
|
-
const missing = DEFAULTS.filter(([name]) => !present.has(name));
|
|
58
|
-
if (missing.length === 0) return whole;
|
|
59
|
-
changed = true;
|
|
60
|
-
const injected = missing.map(([name, value]) => `${name}=${value}`).join(' ');
|
|
61
|
-
return `${boundary}${ws}${injected} ${existingPrefix}${adrNew}`;
|
|
62
|
-
});
|
|
63
|
-
if (!changed) return;
|
|
64
|
-
|
|
65
|
-
process.stdout.write(
|
|
66
|
-
JSON.stringify({
|
|
67
|
-
systemMessage: 'Added missing VISUAL/EDITOR/ADR_TEMPLATE env vars before `adr new`.',
|
|
68
|
-
hookSpecificOutput: {
|
|
69
|
-
hookEventName: 'PreToolUse',
|
|
70
|
-
permissionDecision: 'allow',
|
|
71
|
-
updatedInput: { command: updated },
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
main();
|
|
79
|
-
} catch {
|
|
80
|
-
/* fail open: leave the command untouched */
|
|
81
|
-
}
|
|
82
|
-
process.exit(0);
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//------------------------------------------------------------------------------
|
|
2
|
-
// <auto-generated>
|
|
3
|
-
// This code was generated by a tool.
|
|
4
|
-
//
|
|
5
|
-
// Changes to this file may cause incorrect behavior and will be lost if
|
|
6
|
-
// the code is regenerated.
|
|
7
|
-
// </auto-generated>
|
|
8
|
-
//------------------------------------------------------------------------------
|
|
9
|
-
|
|
10
|
-
using System;
|
|
11
|
-
using System.Reflection;
|
|
12
|
-
|
|
13
|
-
[assembly: System.Reflection.AssemblyCompanyAttribute("__SolutionName__.Api")]
|
|
14
|
-
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
|
15
|
-
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
|
16
|
-
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b8b9e4e3c73f140ae7b06d954c63afb26d78c687")]
|
|
17
|
-
[assembly: System.Reflection.AssemblyProductAttribute("__SolutionName__.Api")]
|
|
18
|
-
[assembly: System.Reflection.AssemblyTitleAttribute("__SolutionName__.Api")]
|
|
19
|
-
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
|
20
|
-
|
|
21
|
-
// Generated by the MSBuild WriteCodeFragment class.
|
|
22
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
922649250c3cbe1ea76366976311f3d76bad60fe3f765d7bf9d3d9b685476c9f
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
is_global = true
|
|
2
|
-
build_property.TargetFramework = net10.0
|
|
3
|
-
build_property.TargetFrameworkIdentifier = .NETCoreApp
|
|
4
|
-
build_property.TargetFrameworkVersion = v10.0
|
|
5
|
-
build_property.TargetPlatformMinVersion =
|
|
6
|
-
build_property.UsingMicrosoftNETSdkWeb = true
|
|
7
|
-
build_property.ProjectTypeGuids =
|
|
8
|
-
build_property.InvariantGlobalization =
|
|
9
|
-
build_property.PlatformNeutralAssembly =
|
|
10
|
-
build_property.EnforceExtendedAnalyzerRules =
|
|
11
|
-
build_property._SupportedPlatformList = Linux,macOS,Windows
|
|
12
|
-
build_property.RootNamespace = __SolutionName__.Api
|
|
13
|
-
build_property.RootNamespace = __SolutionName__.Api
|
|
14
|
-
build_property.ProjectDir = C:\Projects2\Personal\musketeer\template\dotnet-scaffold\src\__SolutionName__.Api\
|
|
15
|
-
build_property.EnableComHosting =
|
|
16
|
-
build_property.EnableGeneratedComInterfaceComImportInterop =
|
|
17
|
-
build_property.RazorLangVersion = 9.0
|
|
18
|
-
build_property.SupportLocalizedComponentNames =
|
|
19
|
-
build_property.GenerateRazorMetadataSourceChecksumAttributes =
|
|
20
|
-
build_property.MSBuildProjectDirectory = C:\Projects2\Personal\musketeer\template\dotnet-scaffold\src\__SolutionName__.Api
|
|
21
|
-
build_property._RazorSourceGeneratorDebug =
|
|
22
|
-
build_property.EffectiveAnalysisLevelStyle = 10.0
|
|
23
|
-
build_property.EnableCodeStyleSeverity =
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// <auto-generated/>
|
|
2
|
-
global using Microsoft.AspNetCore.Builder;
|
|
3
|
-
global using Microsoft.AspNetCore.Hosting;
|
|
4
|
-
global using Microsoft.AspNetCore.Http;
|
|
5
|
-
global using Microsoft.AspNetCore.Routing;
|
|
6
|
-
global using Microsoft.Extensions.Configuration;
|
|
7
|
-
global using Microsoft.Extensions.DependencyInjection;
|
|
8
|
-
global using Microsoft.Extensions.Hosting;
|
|
9
|
-
global using Microsoft.Extensions.Logging;
|
|
10
|
-
global using System;
|
|
11
|
-
global using System.Collections.Generic;
|
|
12
|
-
global using System.IO;
|
|
13
|
-
global using System.Linq;
|
|
14
|
-
global using System.Net.Http;
|
|
15
|
-
global using System.Net.Http.Json;
|
|
16
|
-
global using System.Threading;
|
|
17
|
-
global using System.Threading.Tasks;
|