azcodr 1.0.0 → 1.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.
- package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +24 -8
- package/.editorconfig +19 -0
- package/.gitignore +3 -0
- package/AGENTS.md +1 -2
- package/README.md +3 -3
- package/bin/azcodr.js +215 -64
- package/changes.md +50 -0
- package/docs/rules/upstream_synchronization.md +28 -26
- package/lib/index.d.ts +153 -0
- package/lib/scaffold.js +132 -24
- package/package.json +15 -4
- package/.agents/skills/merge-ai/SKILL.md +0 -90
- package/.agents/skills/merge-ai/scripts/audit_divergence.sh +0 -108
- package/.agents/skills/merge-ai/scripts/resolve_repo.sh +0 -177
|
@@ -45,21 +45,37 @@ if [[ -L "${CLAUDE_FILE}" ]]; then
|
|
|
45
45
|
else
|
|
46
46
|
log_fail "CLAUDE.md points to '${TARGET}' instead of 'AGENTS.md'."
|
|
47
47
|
fi
|
|
48
|
+
elif [[ -f "${CLAUDE_FILE}" ]] && [[ "$(< "${CLAUDE_FILE}")" == "AGENTS.md" ]]; then
|
|
49
|
+
log_pass "CLAUDE.md is a text pointer to AGENTS.md (symlink fallback)."
|
|
48
50
|
else
|
|
49
51
|
log_fail "CLAUDE.md is not a symbolic link."
|
|
50
52
|
fi
|
|
51
53
|
|
|
52
|
-
# Check agents.md symlink
|
|
54
|
+
# Check agents.md symlink (case-insensitive filesystem aware)
|
|
53
55
|
AGENTS_LOWER="${WORKSPACE_ROOT}/agents.md"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
IS_CASE_INSENSITIVE=false
|
|
57
|
+
if [[ "$(uname -s)" == "Darwin" ]] || [[ "$(uname -s)" =~ (MINGW|MSYS|CYGWIN) ]]; then
|
|
58
|
+
IS_CASE_INSENSITIVE=true
|
|
59
|
+
elif [[ -f "${AGENTS_FILE}" ]] && [[ -f "${AGENTS_LOWER}" ]] && [[ ! -L "${AGENTS_LOWER}" ]]; then
|
|
60
|
+
IS_CASE_INSENSITIVE=true
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [[ "${IS_CASE_INSENSITIVE}" == "true" ]]; then
|
|
64
|
+
log_pass "agents.md is satisfied natively by AGENTS.md (case-insensitive filesystem)."
|
|
65
|
+
else
|
|
66
|
+
if [[ ! -L "${AGENTS_LOWER}" ]] && [[ ! -e "${AGENTS_LOWER}" ]] && [[ -f "${AGENTS_FILE}" ]]; then
|
|
67
|
+
ln -sf "AGENTS.md" "${AGENTS_LOWER}"
|
|
68
|
+
fi
|
|
69
|
+
if [[ -L "${AGENTS_LOWER}" ]]; then
|
|
70
|
+
TARGET=$(readlink "${AGENTS_LOWER}")
|
|
71
|
+
if [[ "${TARGET}" == "AGENTS.md" ]]; then
|
|
72
|
+
log_pass "agents.md is a valid symlink to AGENTS.md."
|
|
73
|
+
else
|
|
74
|
+
log_fail "agents.md points to '${TARGET}' instead of 'AGENTS.md'."
|
|
75
|
+
fi
|
|
58
76
|
else
|
|
59
|
-
log_fail "agents.md
|
|
77
|
+
log_fail "agents.md is not a symbolic link."
|
|
60
78
|
fi
|
|
61
|
-
else
|
|
62
|
-
log_fail "agents.md is not a symbolic link."
|
|
63
79
|
fi
|
|
64
80
|
|
|
65
81
|
# 2. Checking Progressive Disclosure Rules (docs/rules)
|
package/.editorconfig
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# http://editorconfig.org
|
|
2
|
+
root = true
|
|
3
|
+
|
|
4
|
+
[*]
|
|
5
|
+
indent_style = space
|
|
6
|
+
indent_size = 2
|
|
7
|
+
end_of_line = lf
|
|
8
|
+
charset = utf-8
|
|
9
|
+
trim_trailing_whitespace = true
|
|
10
|
+
insert_final_newline = true
|
|
11
|
+
|
|
12
|
+
[*.md]
|
|
13
|
+
trim_trailing_whitespace = false
|
|
14
|
+
|
|
15
|
+
[Makefile]
|
|
16
|
+
indent_style = tab
|
|
17
|
+
|
|
18
|
+
[*.go]
|
|
19
|
+
indent_style = tab
|
package/.gitignore
CHANGED
package/AGENTS.md
CHANGED
|
@@ -100,7 +100,7 @@ To prevent context bloat and keep prompt overhead minimal, detailed engineering
|
|
|
100
100
|
| **Relentless Questioning** | [docs/rules/relentless_questioning.md](./docs/rules/relentless_questioning.md) | Dynamic context-aware interrogation loops, adaptive decision trees. |
|
|
101
101
|
| **Workspace Isolation** | [docs/rules/workspace_isolation.md](./docs/rules/workspace_isolation.md) | Strict workspace sovereignty, zero global contamination, local ground truth. |
|
|
102
102
|
| **Continuous Learning** | [docs/rules/continuous_learning.md](./docs/rules/continuous_learning.md) | Automated defect post-mortems, DO's/DONT's logging, dynamic rule updates. |
|
|
103
|
-
| **Upstream Sync** | [docs/rules/upstream_synchronization.md](./docs/rules/upstream_synchronization.md) |
|
|
103
|
+
| **Upstream Sync** | [docs/rules/upstream_synchronization.md](./docs/rules/upstream_synchronization.md) | Logging generic architecture improvements to changes.md; zero baseline pollution. |
|
|
104
104
|
---
|
|
105
105
|
|
|
106
106
|
## 4. Agent Configuration & Workspace Architecture
|
|
@@ -113,7 +113,6 @@ To prevent context bloat and keep prompt overhead minimal, detailed engineering
|
|
|
113
113
|
- [`clean-code-refactor`](.agents/skills/clean-code-refactor/SKILL.md): Refactoring code smells with Clean Code, SOLID, and design patterns.
|
|
114
114
|
- [`lets-build`](.agents/skills/lets-build/SKILL.md): Conducting architecture interviews to finalize stack, frameworks, package managers, and bootstrapping projects.
|
|
115
115
|
- [`relentless-questioner`](.agents/skills/relentless-questioner/SKILL.md): Dynamic context-aware interrogation loops before planning and coding.
|
|
116
|
-
- [`merge-ai`](.agents/skills/merge-ai/SKILL.md): Auditing, filtering, and merging generic rules and skills to upstream baseline.
|
|
117
116
|
- **Relentless Skill Architecture Inquiry:** Never author or update skills on assumptions. Interrogate all 7 inquiry branches (placement, trigger intent, domain truth, gotchas/anti-patterns, determinism, progressive bloat, verification loop) defined in [docs/rules/agentic_configuration.md](./docs/rules/agentic_configuration.md) before writing `SKILL.md`.
|
|
118
117
|
- **Workspace Memory & Knowledge Hub:** Consult [`memory.md`](./memory.md) for ADRs, and [`docs/knowledge/`](./docs/knowledge/knowledge_graph.md) for system topologies, issue logs, and DO's/DONT's.
|
|
119
118
|
- **Harness Parity & Symlinks:** `AGENTS.md`, `CLAUDE.md`, and `agents.md` must remain identical via filesystem symbolic links to eliminate configuration divergence across different agent harnesses.
|
package/README.md
CHANGED
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
│ ├── clean-code-refactor/ # Refactoring code smells with GoF & Clean Code
|
|
32
32
|
│ ├── compliance-audit/ # SOC 2, ISO 27001 & OWASP open-source audits
|
|
33
33
|
│ ├── lets-build/ # Architecture interview & project bootstrapper
|
|
34
|
-
│ ├── merge-ai/ # Auditing & merging generic AI knowledge to upstream
|
|
35
34
|
│ ├── product-analyst/ # INVEST user stories & Gherkin criteria
|
|
36
35
|
│ └── relentless-questioner/ # Context-aware dynamic interrogation loop
|
|
37
36
|
├── docs/
|
|
@@ -45,6 +44,7 @@
|
|
|
45
44
|
├── AGENTS.md # Lean root agentic configuration (< 120 lines)
|
|
46
45
|
├── CLAUDE.md -> AGENTS.md # Filesystem symlink for harness parity
|
|
47
46
|
├── agents.md -> AGENTS.md # Filesystem symlink for harness parity
|
|
47
|
+
├── changes.md # Upstream changes ledger
|
|
48
48
|
├── memory.md # Master memory hub & Lightweight ADR ledger
|
|
49
49
|
└── README.md # Project documentation
|
|
50
50
|
```
|
|
@@ -103,7 +103,7 @@ The architecture enforces 47 atomic, single-responsibility domain rules. Read on
|
|
|
103
103
|
| **Relentless Questioning** | [`relentless_questioning.md`](./docs/rules/relentless_questioning.md) | Dynamic context-aware interrogation loops, adaptive decision trees. |
|
|
104
104
|
| **Workspace Isolation** | [`workspace_isolation.md`](./docs/rules/workspace_isolation.md) | Strict workspace sovereignty, zero global contamination, local ground truth. |
|
|
105
105
|
| **Continuous Learning** | [`continuous_learning.md`](./docs/rules/continuous_learning.md) | Automated defect post-mortems, DO's/DONT's logging, dynamic rule updates. |
|
|
106
|
-
| **Upstream Sync** | [`upstream_synchronization.md`](./docs/rules/upstream_synchronization.md) |
|
|
106
|
+
| **Upstream Sync** | [`upstream_synchronization.md`](./docs/rules/upstream_synchronization.md) | Logging generic architecture improvements to changes.md; zero baseline pollution. |
|
|
107
107
|
|
|
108
108
|
---
|
|
109
109
|
|
|
@@ -113,7 +113,6 @@ The architecture enforces 47 atomic, single-responsibility domain rules. Read on
|
|
|
113
113
|
- [`clean-code-refactor`](.agents/skills/clean-code-refactor/SKILL.md): Refactoring code smells with Clean Code, SOLID, and modern design patterns.
|
|
114
114
|
- [`compliance-audit`](.agents/skills/compliance-audit/SKILL.md): Conducting SOC 2, ISO 27001, and OWASP audits using open-source scanners.
|
|
115
115
|
- [`lets-build`](.agents/skills/lets-build/SKILL.md): Conducting architecture interviews to finalize stack, frameworks, package managers, and bootstrapping projects.
|
|
116
|
-
- [`merge-ai`](.agents/skills/merge-ai/SKILL.md): Auditing, filtering, and merging generic rules and skills to upstream baseline.
|
|
117
116
|
- [`product-analyst`](.agents/skills/product-analyst/SKILL.md): Aligning OKRs, backlog ordering (Kano/MoSCoW/RICE), INVEST stories, and Gherkin criteria.
|
|
118
117
|
- [`relentless-questioner`](.agents/skills/relentless-questioner/SKILL.md): Dynamic context-aware interrogation loops before planning and coding.
|
|
119
118
|
|
|
@@ -182,3 +181,4 @@ Once confirmed, the agent automatically executes:
|
|
|
182
181
|
- 🐛 **[Coding Issue Log](./docs/knowledge/issue_log.md)**: Defect post-mortems and preventative rules.
|
|
183
182
|
- 💡 **[Institutional Lessons Learned](./docs/knowledge/lessons_learned.md)**: Strategic engineering insights.
|
|
184
183
|
- 📜 **[Lightweight ADR Ledger](./memory.md)**: Formal Architectural Decision Records.
|
|
184
|
+
- 📝 **[Upstream Changes Ledger](./changes.md)**: Record candidate improvements and generic patterns for the upstream azcodr template.
|
package/bin/azcodr.js
CHANGED
|
@@ -3,149 +3,300 @@
|
|
|
3
3
|
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const readline = require('node:readline');
|
|
6
|
-
const
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const { scaffold, logChange, getTemplateDir } = require('../lib/scaffold.js');
|
|
7
8
|
const pkg = require('../package.json');
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
function printHelp() {
|
|
12
|
-
console.log(`
|
|
10
|
+
function printHelp(out = console.log) {
|
|
11
|
+
out(`
|
|
13
12
|
azcodr v${pkg.version}
|
|
14
13
|
Enterprise Multi-Tenant Architecture & Agentic Engineering Starter Template
|
|
15
14
|
|
|
16
15
|
Usage:
|
|
17
16
|
npx azcodr [directory] [options]
|
|
17
|
+
npx azcodr change <title> [options]
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
directory
|
|
19
|
+
Commands:
|
|
20
|
+
[directory] Scaffold azcodr template into directory (default: current directory)
|
|
21
|
+
change <title> Log a generic architectural change to changes.md
|
|
21
22
|
|
|
22
|
-
Options:
|
|
23
|
+
Scaffold Options:
|
|
24
|
+
-d, --dry-run Simulate scaffolding without modifying filesystem
|
|
25
|
+
-s, --silent Suppress console output messages
|
|
23
26
|
-f, --force Overwrite existing files in target directory without confirmation
|
|
24
27
|
--no-git Do not initialize a git repository
|
|
25
28
|
-v, --version Display version number
|
|
26
29
|
-h, --help Display this help message
|
|
27
30
|
|
|
31
|
+
Change Options:
|
|
32
|
+
-c, --category Category (Architecture | Rule | Skill | Infrastructure | CLI | Knowledge Hub)
|
|
33
|
+
-f, --files Target file(s) affected (e.g. "docs/rules/caching.md")
|
|
34
|
+
-r, --rationale Rationale for upstream template incorporation
|
|
35
|
+
-d, --desc Detailed description of the change
|
|
36
|
+
|
|
28
37
|
Examples:
|
|
29
38
|
npx azcodr my-project
|
|
39
|
+
npx azcodr . --dry-run
|
|
30
40
|
npx azcodr . --force
|
|
41
|
+
npx azcodr change "Add Wasm plugin interface" -c Architecture
|
|
31
42
|
`);
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
function printVersion() {
|
|
35
|
-
|
|
45
|
+
function printVersion(out = console.log) {
|
|
46
|
+
out(pkg.version);
|
|
36
47
|
}
|
|
37
48
|
|
|
38
|
-
function askQuestion(query) {
|
|
39
|
-
const rl = readline.createInterface({
|
|
40
|
-
input: process.stdin,
|
|
41
|
-
output: process.stdout
|
|
42
|
-
});
|
|
49
|
+
function askQuestion(query, { input = process.stdin, output = process.stdout } = {}) {
|
|
50
|
+
const rl = readline.createInterface({ input, output });
|
|
43
51
|
|
|
44
52
|
return new Promise((resolve) => {
|
|
53
|
+
let resolved = false;
|
|
45
54
|
rl.question(query, (answer) => {
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
if (!resolved) {
|
|
56
|
+
resolved = true;
|
|
57
|
+
rl.close();
|
|
58
|
+
resolve(answer.trim());
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
rl.on('close', () => {
|
|
62
|
+
if (!resolved) {
|
|
63
|
+
resolved = true;
|
|
64
|
+
resolve('');
|
|
65
|
+
}
|
|
48
66
|
});
|
|
49
67
|
});
|
|
50
68
|
}
|
|
51
69
|
|
|
52
|
-
async function
|
|
70
|
+
async function handleLogChange(rawArgs = process.argv.slice(2), io = {}) {
|
|
71
|
+
const {
|
|
72
|
+
out = console.log,
|
|
73
|
+
err = console.error,
|
|
74
|
+
exit = process.exit,
|
|
75
|
+
stdin = process.stdin,
|
|
76
|
+
stdout = process.stdout,
|
|
77
|
+
cwd = process.cwd(),
|
|
78
|
+
logChange: logChangeFn = logChange
|
|
79
|
+
} = io;
|
|
80
|
+
|
|
81
|
+
let title = null;
|
|
82
|
+
let category = 'Architecture';
|
|
83
|
+
let targetFiles = 'docs/rules/';
|
|
84
|
+
let rationale = 'Generic architectural enhancement';
|
|
85
|
+
let description = '';
|
|
86
|
+
|
|
87
|
+
for (let i = 1; i < rawArgs.length; i++) {
|
|
88
|
+
const a = rawArgs[i];
|
|
89
|
+
if (a === '-c' || a === '--category') {
|
|
90
|
+
category = rawArgs[++i] || category;
|
|
91
|
+
} else if (a === '-f' || a === '--files') {
|
|
92
|
+
targetFiles = rawArgs[++i] || targetFiles;
|
|
93
|
+
} else if (a === '-r' || a === '--rationale') {
|
|
94
|
+
rationale = rawArgs[++i] || rationale;
|
|
95
|
+
} else if (a === '-d' || a === '--desc' || a === '--description') {
|
|
96
|
+
description = rawArgs[++i] || description;
|
|
97
|
+
} else if (a.startsWith('-')) {
|
|
98
|
+
err(`❌ Error: Unknown argument '${a}'. Run 'npx azcodr --help' for available options.`);
|
|
99
|
+
return exit(1);
|
|
100
|
+
} else if (!title) {
|
|
101
|
+
title = a;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!title) {
|
|
106
|
+
if (stdin.isTTY) {
|
|
107
|
+
title = await askQuestion('? Change title: ', { input: stdin, output: stdout });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!title) {
|
|
112
|
+
err('❌ Error: A title is required to log an upstream change.');
|
|
113
|
+
err('Usage: npx azcodr change "<title>" [-c Category] [-f Files] [-r Rationale] [-d Description]');
|
|
114
|
+
return exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const res = logChangeFn({
|
|
119
|
+
title,
|
|
120
|
+
category,
|
|
121
|
+
targetFiles,
|
|
122
|
+
rationale,
|
|
123
|
+
description,
|
|
124
|
+
targetDir: cwd
|
|
125
|
+
});
|
|
126
|
+
out(`\n✅ Upstream change logged to ${res.filePath}\n`);
|
|
127
|
+
return exit(0);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
err(`\n❌ Failed to log change: ${error.message}\n`);
|
|
130
|
+
return exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function runCli(rawArgs = process.argv.slice(2), io = {}) {
|
|
135
|
+
const {
|
|
136
|
+
out = console.log,
|
|
137
|
+
err = console.error,
|
|
138
|
+
exit = process.exit,
|
|
139
|
+
stdin = process.stdin,
|
|
140
|
+
stdout = process.stdout,
|
|
141
|
+
cwd = process.cwd(),
|
|
142
|
+
templateDir = getTemplateDir(),
|
|
143
|
+
scaffold: scaffoldFn = scaffold
|
|
144
|
+
} = io;
|
|
145
|
+
|
|
146
|
+
if (rawArgs[0] === 'change' || rawArgs[0] === 'log-change') {
|
|
147
|
+
return handleLogChange(rawArgs, io);
|
|
148
|
+
}
|
|
149
|
+
|
|
53
150
|
let targetDir = null;
|
|
54
151
|
let force = false;
|
|
55
152
|
let noGit = false;
|
|
153
|
+
let dryRun = false;
|
|
154
|
+
let silent = false;
|
|
56
155
|
|
|
57
|
-
for (let i = 0; i <
|
|
58
|
-
const arg =
|
|
156
|
+
for (let i = 0; i < rawArgs.length; i++) {
|
|
157
|
+
const arg = rawArgs[i];
|
|
59
158
|
if (arg === '-h' || arg === '--help') {
|
|
60
|
-
printHelp();
|
|
61
|
-
|
|
159
|
+
printHelp(out);
|
|
160
|
+
return exit(0);
|
|
62
161
|
} else if (arg === '-v' || arg === '--version') {
|
|
63
|
-
printVersion();
|
|
64
|
-
|
|
162
|
+
printVersion(out);
|
|
163
|
+
return exit(0);
|
|
65
164
|
} else if (arg === '-f' || arg === '--force') {
|
|
66
165
|
force = true;
|
|
67
166
|
} else if (arg === '--no-git') {
|
|
68
167
|
noGit = true;
|
|
69
|
-
} else if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
168
|
+
} else if (arg === '-d' || arg === '--dry-run') {
|
|
169
|
+
dryRun = true;
|
|
170
|
+
} else if (arg === '-s' || arg === '--silent') {
|
|
171
|
+
silent = true;
|
|
172
|
+
} else if (arg.startsWith('-')) {
|
|
173
|
+
err(`❌ Error: Unknown argument '${arg}'. Run 'npx azcodr --help' for available options.`);
|
|
174
|
+
return exit(1);
|
|
175
|
+
} else if (!targetDir) {
|
|
176
|
+
targetDir = arg;
|
|
73
177
|
}
|
|
74
178
|
}
|
|
75
179
|
|
|
76
|
-
|
|
180
|
+
if (!silent) {
|
|
181
|
+
out('\n🚀 azcodr - Enterprise Multi-Tenant Architecture & Agentic Engineering\n');
|
|
182
|
+
}
|
|
77
183
|
|
|
78
184
|
if (!targetDir) {
|
|
79
|
-
if (
|
|
80
|
-
const answer = await askQuestion('? Where would you like to initialize your project? (./) '
|
|
185
|
+
if (stdin.isTTY) {
|
|
186
|
+
const answer = await askQuestion('? Where would you like to initialize your project? (./) ', {
|
|
187
|
+
input: stdin,
|
|
188
|
+
output: stdout
|
|
189
|
+
});
|
|
81
190
|
targetDir = answer || '.';
|
|
82
191
|
} else {
|
|
83
192
|
targetDir = '.';
|
|
84
193
|
}
|
|
85
194
|
}
|
|
86
195
|
|
|
87
|
-
const resolvedTarget = path.resolve(
|
|
88
|
-
const templateDir = getTemplateDir();
|
|
196
|
+
const resolvedTarget = path.resolve(cwd, targetDir);
|
|
89
197
|
|
|
90
198
|
if (resolvedTarget === templateDir) {
|
|
91
|
-
|
|
92
|
-
|
|
199
|
+
err(`❌ Error: Cannot scaffold into the template directory itself: ${resolvedTarget}`);
|
|
200
|
+
return exit(1);
|
|
93
201
|
}
|
|
94
202
|
|
|
95
|
-
const fs = require('node:fs');
|
|
96
203
|
if (fs.existsSync(resolvedTarget)) {
|
|
204
|
+
const stat = fs.statSync(resolvedTarget);
|
|
205
|
+
if (!stat.isDirectory()) {
|
|
206
|
+
err(`❌ Error: Target '${resolvedTarget}' already exists and is not a directory.`);
|
|
207
|
+
return exit(1);
|
|
208
|
+
}
|
|
97
209
|
const entries = fs.readdirSync(resolvedTarget);
|
|
98
210
|
if (entries.length > 0 && !force) {
|
|
99
|
-
if (
|
|
211
|
+
if (stdin.isTTY) {
|
|
100
212
|
const confirm = await askQuestion(
|
|
101
|
-
`⚠️ Target directory '${targetDir}' is not empty (${entries.length} items). Continue? (y/N)
|
|
213
|
+
`⚠️ Target directory '${targetDir}' is not empty (${entries.length} items). Continue? (y/N) `,
|
|
214
|
+
{ input: stdin, output: stdout }
|
|
102
215
|
);
|
|
103
216
|
if (confirm.toLowerCase() !== 'y' && confirm.toLowerCase() !== 'yes') {
|
|
104
|
-
|
|
105
|
-
|
|
217
|
+
out('Scaffolding aborted.');
|
|
218
|
+
return exit(0);
|
|
106
219
|
}
|
|
107
220
|
force = true;
|
|
108
221
|
} else {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
);
|
|
112
|
-
process.exit(1);
|
|
222
|
+
err(`❌ Error: Target directory '${resolvedTarget}' is not empty. Use --force to proceed.`);
|
|
223
|
+
return exit(1);
|
|
113
224
|
}
|
|
114
225
|
}
|
|
115
226
|
}
|
|
116
227
|
|
|
117
|
-
|
|
228
|
+
if (dryRun) {
|
|
229
|
+
if (!silent) {
|
|
230
|
+
out(`🔍 DRY RUN: Simulating azcodr scaffolding into: ${resolvedTarget}\n`);
|
|
231
|
+
}
|
|
232
|
+
} else if (!silent) {
|
|
233
|
+
out(`📦 Scaffolding azcodr into: ${resolvedTarget}`);
|
|
234
|
+
}
|
|
118
235
|
|
|
119
236
|
try {
|
|
120
|
-
const result =
|
|
237
|
+
const result = scaffoldFn({
|
|
121
238
|
targetDir: resolvedTarget,
|
|
122
239
|
force,
|
|
123
240
|
noGit,
|
|
124
|
-
templateDir
|
|
241
|
+
templateDir,
|
|
242
|
+
dryRun,
|
|
243
|
+
silent
|
|
125
244
|
});
|
|
126
245
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
246
|
+
if (dryRun) {
|
|
247
|
+
if (!silent) {
|
|
248
|
+
for (const action of result.actions) {
|
|
249
|
+
out(` [preview] ${action}`);
|
|
250
|
+
}
|
|
251
|
+
out('\n🎉 Dry run completed. 0 files modified on disk.\n');
|
|
252
|
+
}
|
|
253
|
+
return exit(0);
|
|
133
254
|
}
|
|
134
255
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
256
|
+
if (!silent) {
|
|
257
|
+
out(' ✅ Progressive disclosure rules copied (docs/rules/)');
|
|
258
|
+
out(' ✅ Workspace knowledge hub and ADR ledger copied (docs/knowledge/, memory.md)');
|
|
259
|
+
out(' ✅ Specialized agentic skills copied (.agents/skills/)');
|
|
260
|
+
out(' ✅ Upstream changes ledger initialized (changes.md)');
|
|
261
|
+
out(' ✅ Editor formatting standards initialized (.editorconfig)');
|
|
262
|
+
out(' ✅ Agent directives and harness symlinks established (AGENTS.md, CLAUDE.md, agents.md)');
|
|
263
|
+
if (result.gitInitialized) {
|
|
264
|
+
out(' ✅ Git repository initialized');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
out('\n🎉 azcodr initialized successfully!\n');
|
|
268
|
+
out('Next steps:');
|
|
269
|
+
if (targetDir !== '.' && targetDir !== './') {
|
|
270
|
+
out(` 1. cd ${targetDir}`);
|
|
271
|
+
}
|
|
272
|
+
out(' 2. Open the project in your AI coding assistant (Antigravity, Claude Code, Cursor, OpenHands)');
|
|
273
|
+
out(' 3. Run /lets-build to start the architectural interview and scaffold your application stack!\n');
|
|
139
274
|
}
|
|
140
|
-
|
|
141
|
-
|
|
275
|
+
return exit(0);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
err(`\n❌ Scaffolding failed: ${error.message}\n`);
|
|
278
|
+
return exit(1);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function main() {
|
|
283
|
+
try {
|
|
284
|
+
await runCli(process.argv.slice(2));
|
|
142
285
|
} catch (err) {
|
|
143
|
-
console.error(
|
|
286
|
+
console.error('Unexpected error:', err);
|
|
144
287
|
process.exit(1);
|
|
145
288
|
}
|
|
146
289
|
}
|
|
147
290
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
291
|
+
if (require.main === module) {
|
|
292
|
+
main();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
module.exports = {
|
|
296
|
+
runCli,
|
|
297
|
+
handleLogChange,
|
|
298
|
+
askQuestion,
|
|
299
|
+
printHelp,
|
|
300
|
+
printVersion,
|
|
301
|
+
main
|
|
302
|
+
};
|
package/changes.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Upstream Changes Ledger (`changes.md`)
|
|
2
|
+
|
|
3
|
+
> **Core Purpose:** Record candidate improvements, generic architectural updates, defect post-mortems, and rule enhancements discovered in this workspace that should be incorporated into the upstream `azcodr` baseline template. No automated git merging or external repo mutation is performed.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Specification & Protocol
|
|
8
|
+
|
|
9
|
+
When an AI agent or engineer discovers a generic architectural improvement, bug fix, or rule refinement during project development, append an entry below using this atomic format:
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
### [YYYY-MM-DD] <Title of Change>
|
|
13
|
+
- **Category:** Rule | Skill | Infrastructure | CLI | Knowledge Hub
|
|
14
|
+
- **Target File(s):** `docs/rules/...`, `.agents/skills/...`, etc.
|
|
15
|
+
- **Rationale:** Why this improvement is necessary or valuable across all enterprise projects.
|
|
16
|
+
- **Description:** Concise summary of the mutation or invariant added.
|
|
17
|
+
- **Domain Filter Verification:** Verified 100% generic; purged of all project-specific business entities and models.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Upstream Changes Log
|
|
23
|
+
|
|
24
|
+
### [2026-09-25] Initialized npx Scaffolder CLI and npm Package
|
|
25
|
+
- **Category:** CLI & Infrastructure
|
|
26
|
+
- **Target File(s):** `bin/azcodr.js`, `lib/scaffold.js`, `package.json`, `tests/`
|
|
27
|
+
- **Rationale:** Eliminate manual `cp -r` copying; enable anyone to pull and scaffold the azcodr architecture template via `npx azcodr`.
|
|
28
|
+
- **Description:** Implemented zero-dependency Node.js CLI executable with Outside-In TDD, harness parity symlink generation, script execution bit setting, and full test suite passing with 100% agentic config validation.
|
|
29
|
+
- **Domain Filter Verification:** Verified 100% generic; no project-specific business models.
|
|
30
|
+
|
|
31
|
+
### [2026-09-25] Streamlined Upstream Sync Protocol to changes.md Ledger
|
|
32
|
+
- **Category:** Rule & Process
|
|
33
|
+
- **Target File(s):** `docs/rules/upstream_synchronization.md`, `changes.md`, `AGENTS.md`
|
|
34
|
+
- **Rationale:** Remove fragile git repo resolution and merge scripts; replace with atomic change logging in `changes.md`.
|
|
35
|
+
- **Description:** Retired `merge-ai` skill and removed machine-specific hardcoded paths. All upstream improvements are now recorded atomically in `changes.md`.
|
|
36
|
+
- **Domain Filter Verification:** Verified 100% generic.
|
|
37
|
+
|
|
38
|
+
### [2026-09-25] Harden CLI, achieve 100% test coverage gates, add multi-OS CI workflow, and TypeScript declarations
|
|
39
|
+
- **Category:** CLI
|
|
40
|
+
- **Target File(s):** bin/azcodr.js, lib/scaffold.js, lib/index.d.ts, .github/workflows/ci.yml
|
|
41
|
+
- **Rationale:** Fulfill 100.00% test coverage mandate, cross-platform CI matrix, and library type safety
|
|
42
|
+
- **Description:** Remediate gap assessment findings: add --dry-run and --silent flags, enforce 100.00% line/branch/function coverage gates, add GitHub Actions CI matrix across Node 18/20/22/24 and Linux/macOS/Windows, add .editorconfig template item, and export ambient TypeScript typings.
|
|
43
|
+
- **Domain Filter Verification:** Verified 100% generic; purged of all project-specific business entities and models.
|
|
44
|
+
|
|
45
|
+
### [2026-09-25] Resolve macOS/Windows Git Case-Collision and Cross-Version CI Matrix Coverage
|
|
46
|
+
- **Category:** Infrastructure & CI
|
|
47
|
+
- **Target File(s):** .gitignore, lib/scaffold.js, scripts/test_coverage.js, validate_agentic_configs.sh
|
|
48
|
+
- **Rationale:** Ensure flawless cross-platform and multi-version Node execution across macOS, Windows, and Linux on Node 18, 20, 22, 24.
|
|
49
|
+
- **Description:** Untracked agents.md from Git to prevent cyclic symlink overwrite on case-insensitive filesystems; hardened ensureSymlink with isSameCaseInsensitiveFile check; added cross-version test coverage runner script; updated npm test runner to use native discovery.
|
|
50
|
+
- **Domain Filter Verification:** Verified 100% generic; purged of all project-specific business entities and models.
|
|
@@ -1,40 +1,37 @@
|
|
|
1
|
-
# Upstream Baseline Synchronization &
|
|
1
|
+
# Upstream Baseline Synchronization & changes.md Ledger
|
|
2
2
|
|
|
3
|
-
> **Core Mandate:** Upstream template/baseline workspaces (`azcodr`) must remain strictly untouched
|
|
3
|
+
> **Core Mandate:** Upstream template/baseline workspaces (`azcodr`) must remain strictly untouched during project development. When generic architectural improvements, rule refinements, or post-mortems are identified, record them solely into the `changes.md` ledger with zero automated repo merging or baseline contamination.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## 1. The Baseline-Project Decoupling Principle
|
|
8
8
|
|
|
9
|
-
Workspaces operate under a
|
|
9
|
+
Workspaces operate under a clean, decoupled flow:
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
[Upstream Generic Baseline: azcodr]
|
|
13
13
|
│
|
|
14
|
-
▼ (
|
|
14
|
+
▼ (Scaffolded via npx azcodr)
|
|
15
15
|
[Derived Project Workspace: my-app / others]
|
|
16
16
|
│
|
|
17
17
|
│ (Accumulates project code, specificities, and institutional lessons)
|
|
18
18
|
│
|
|
19
|
-
▼ (
|
|
20
|
-
[
|
|
21
|
-
│
|
|
22
|
-
▼
|
|
23
|
-
[Clean Merge into Upstream Baseline: azcodr]
|
|
19
|
+
▼ (Record reusable improvements)
|
|
20
|
+
[Upstream Changes Ledger: changes.md]
|
|
24
21
|
```
|
|
25
22
|
|
|
26
|
-
- **Pristine Upstream Mandate:** Never edit, commit, or
|
|
27
|
-
- **
|
|
23
|
+
- **Pristine Upstream Mandate:** Never edit, commit, or attempt automated git merges to an upstream baseline repository during routine project development, feature implementation, or bug fixes.
|
|
24
|
+
- **Ledger-Only Synchronization:** When generic architectural discoveries or defect post-mortems occur, document them cleanly in `changes.md` at the workspace root. No automated merge AI or remote repo synchronization is executed.
|
|
28
25
|
|
|
29
26
|
---
|
|
30
27
|
|
|
31
28
|
## 2. Zero-Contamination Invariant (Generic vs. Specific)
|
|
32
29
|
|
|
33
|
-
When
|
|
30
|
+
When logging proposed changes into `changes.md`, enforce strict domain filtering:
|
|
34
31
|
|
|
35
|
-
| Element Category | Keep in Specific Project Workspace | Allow in
|
|
32
|
+
| Element Category | Keep in Specific Project Workspace | Allow in changes.md for Upstream (`azcodr`) |
|
|
36
33
|
|---|---|---|
|
|
37
|
-
| **Domain Entities** | Concrete business models (`Order`, `Customer`, `Invoice`,
|
|
34
|
+
| **Domain Entities** | Concrete business models (`Order`, `Customer`, `Invoice`, etc.) | Abstract archetypes (`Entity`, `Aggregate`, `ValueObject`, `Resource`) |
|
|
38
35
|
| **Tech Stack / Adapters** | Concrete choices (Prisma, SQLite dev, PostgreSQL prod, Vite React) | Hexagonal Ports, abstract repository contracts, polyglot adapter guidance |
|
|
39
36
|
| **Architectural Rules** | Specific entity validation, specific route paths | Universal invariants (5-Phase Agile Lifecycle, SemVer trigger matrix, FK dropdowns) |
|
|
40
37
|
| **ADRs** | Stack decisions (`ADR-006: Target Tech Stack for Project`) | Generic architecture patterns (`ADR-007` to `ADR-010`) |
|
|
@@ -42,25 +39,30 @@ When merging knowledge, rules, or skills back to the baseline, enforce strict do
|
|
|
42
39
|
|
|
43
40
|
---
|
|
44
41
|
|
|
45
|
-
## 3.
|
|
42
|
+
## 3. Atomic changes.md Entry Protocol
|
|
43
|
+
|
|
44
|
+
Every upstream-bound proposal logged to `changes.md` must follow the standardized format:
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
```markdown
|
|
47
|
+
### [YYYY-MM-DD] <Title of Change>
|
|
48
|
+
- **Category:** Rule | Skill | Infrastructure | CLI | Knowledge Hub
|
|
49
|
+
- **Target File(s):** `docs/rules/...`, `.agents/skills/...`, etc.
|
|
50
|
+
- **Rationale:** Why this improvement is necessary or valuable across all enterprise projects.
|
|
51
|
+
- **Description:** Concise summary of the mutation or invariant added.
|
|
52
|
+
- **Domain Filter Verification:** Verified 100% generic; purged of all project-specific business entities and models.
|
|
53
|
+
```
|
|
51
54
|
|
|
52
55
|
---
|
|
53
56
|
|
|
54
57
|
## 4. Invariants, DO's & DONT's
|
|
55
58
|
|
|
56
59
|
### DO's:
|
|
57
|
-
- **DO:**
|
|
58
|
-
- **DO:**
|
|
59
|
-
- **DO:** Distill all lessons and post-mortems into generic, domain-agnostic language before merging.
|
|
60
|
+
- **DO:** Record candidate generic architectural improvements in `changes.md`.
|
|
61
|
+
- **DO:** Distill all lessons and post-mortems into generic, domain-agnostic language before logging.
|
|
60
62
|
- **DO:** Colocate DOs and DONTs directly inside the relevant atomic rules and skills.
|
|
61
|
-
- **DO:**
|
|
63
|
+
- **DO:** Verify that all entries in `changes.md` are 100% stack- and domain-agnostic.
|
|
62
64
|
|
|
63
65
|
### DONT's:
|
|
64
|
-
- **DONT:** Never
|
|
65
|
-
- **DONT:** Never contaminate
|
|
66
|
-
- **DONT:** Never
|
|
66
|
+
- **DONT:** Never execute automated upstream git cloning or merge AI workflows during project work.
|
|
67
|
+
- **DONT:** Never contaminate `changes.md` with project-specific business logic, schemas, or customer requirements.
|
|
68
|
+
- **DONT:** Never leave machine-specific or absolute user paths in scripts or documentation.
|