azcodr 1.5.2 → 2.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 (136) hide show
  1. package/.agents/hooks.json +42 -42
  2. package/.agents/hooks.json.example +42 -42
  3. package/.agents/mcp_config.json.example +29 -29
  4. package/.agents/scripts/safety_guard.sh +143 -34
  5. package/.agents/scripts/verify_completion.sh +90 -27
  6. package/.agents/skills/agentic-architect/SKILL.md +125 -125
  7. package/.agents/skills/agentic-architect/references/agents_md_template.md +62 -62
  8. package/.agents/skills/agentic-architect/references/refinement_workflow.md +32 -32
  9. package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +63 -63
  10. package/.agents/skills/agentic-architect/references/skill_template.md +56 -56
  11. package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +402 -402
  12. package/.agents/skills/clean-code-refactor/SKILL.md +91 -91
  13. package/.agents/skills/clean-code-refactor/references/clean_code_smells.md +27 -27
  14. package/.agents/skills/clean-code-refactor/references/design_patterns_ts.md +65 -65
  15. package/.agents/skills/compliance-audit/SKILL.md +120 -120
  16. package/.agents/skills/compliance-audit/references/owasp_top10_controls.md +16 -16
  17. package/.agents/skills/compliance-audit/references/soc2_iso_controls.md +28 -28
  18. package/.agents/skills/lets-build/SKILL.md +173 -173
  19. package/.agents/skills/lets-build/references/architecture_interview_matrix.md +115 -115
  20. package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +160 -160
  21. package/.agents/skills/lets-build/references/project_readme_template.md +79 -79
  22. package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +419 -255
  23. package/.agents/skills/product-analyst/SKILL.md +154 -154
  24. package/.agents/skills/product-analyst/references/backlog_ordering_techniques.md +107 -107
  25. package/.agents/skills/product-analyst/references/gherkin_patterns.md +46 -46
  26. package/.agents/skills/product-analyst/references/invest_checklist.md +38 -38
  27. package/.agents/skills/product-analyst/references/okr_alignment_guide.md +76 -76
  28. package/.agents/skills/product-analyst/references/smart_tasks.md +59 -59
  29. package/.agents/skills/relentless-questioner/SKILL.md +128 -128
  30. package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +102 -102
  31. package/.editorconfig +19 -19
  32. package/.github/workflows/ci.yml +167 -78
  33. package/.github/workflows/publish.yml +196 -0
  34. package/.gitignore +40 -25
  35. package/AGENTS.md +103 -102
  36. package/LICENSE +21 -21
  37. package/README.md +168 -165
  38. package/bin/azcodr.js +19 -228
  39. package/docs/knowledge/ubiquitous_language.md +31 -18
  40. package/docs/rules/agentic_configuration.md +259 -259
  41. package/docs/rules/api_architecture.md +179 -179
  42. package/docs/rules/authentication.md +76 -76
  43. package/docs/rules/authorization.md +75 -75
  44. package/docs/rules/caching.md +69 -69
  45. package/docs/rules/clean_code.md +62 -62
  46. package/docs/rules/cloud_native.md +41 -41
  47. package/docs/rules/cqrs.md +203 -203
  48. package/docs/rules/database_design.md +125 -125
  49. package/docs/rules/database_operations.md +69 -69
  50. package/docs/rules/design_patterns.md +98 -98
  51. package/docs/rules/devops_ci_cd.md +76 -76
  52. package/docs/rules/domain_driven_design.md +122 -122
  53. package/docs/rules/error_handling.md +54 -52
  54. package/docs/rules/feature_flags.md +59 -59
  55. package/docs/rules/frontend_architecture.md +157 -157
  56. package/docs/rules/multitenancy_architecture.md +98 -98
  57. package/docs/rules/product_ownership.md +127 -127
  58. package/docs/rules/project_management.md +49 -49
  59. package/docs/rules/relentless_questioning.md +52 -52
  60. package/docs/rules/requirements_engineering.md +98 -98
  61. package/docs/rules/security_compliance.md +53 -53
  62. package/docs/rules/server_driven_ui.md +88 -88
  63. package/docs/rules/test_driven_development.md +185 -185
  64. package/docs/rules/transactional_email.md +27 -27
  65. package/docs/rules/type_safety.md +65 -65
  66. package/docs/rules/ui_ux_architecture.md +150 -150
  67. package/docs/rules/workflow_state_machines.md +117 -117
  68. package/lib/cli-parse.d.ts +32 -0
  69. package/lib/cli-parse.d.ts.map +1 -0
  70. package/lib/cli-parse.js +55 -0
  71. package/lib/cli-parse.js.map +1 -0
  72. package/lib/cli-target.d.ts +66 -0
  73. package/lib/cli-target.d.ts.map +1 -0
  74. package/lib/cli-target.js +102 -0
  75. package/lib/cli-target.js.map +1 -0
  76. package/lib/cli.d.ts +40 -0
  77. package/lib/cli.d.ts.map +1 -0
  78. package/lib/cli.js +166 -0
  79. package/lib/cli.js.map +1 -0
  80. package/lib/errors.d.ts +39 -0
  81. package/lib/errors.d.ts.map +1 -0
  82. package/lib/errors.js +26 -0
  83. package/lib/errors.js.map +1 -0
  84. package/lib/git.d.ts +15 -0
  85. package/lib/git.d.ts.map +1 -0
  86. package/lib/git.js +32 -0
  87. package/lib/git.js.map +1 -0
  88. package/lib/guards.d.ts +35 -0
  89. package/lib/guards.d.ts.map +1 -0
  90. package/lib/guards.js +95 -0
  91. package/lib/guards.js.map +1 -0
  92. package/lib/index.d.ts +6 -134
  93. package/lib/index.d.ts.map +1 -0
  94. package/lib/index.js +4 -5
  95. package/lib/index.js.map +1 -0
  96. package/lib/links.d.ts +28 -0
  97. package/lib/links.d.ts.map +1 -0
  98. package/lib/links.js +129 -0
  99. package/lib/links.js.map +1 -0
  100. package/lib/permissions.d.ts +9 -0
  101. package/lib/permissions.d.ts.map +1 -0
  102. package/lib/permissions.js +44 -0
  103. package/lib/permissions.js.map +1 -0
  104. package/lib/repo.d.ts +20 -0
  105. package/lib/repo.d.ts.map +1 -0
  106. package/lib/repo.js +92 -0
  107. package/lib/repo.js.map +1 -0
  108. package/lib/scaffold.d.ts +80 -0
  109. package/lib/scaffold.d.ts.map +1 -0
  110. package/lib/scaffold.js +201 -448
  111. package/lib/scaffold.js.map +1 -0
  112. package/memory.md +135 -36
  113. package/package.json +75 -62
  114. package/scripts/test_coverage.js +66 -38
  115. package/scripts/validate/adr.js +155 -0
  116. package/scripts/validate/io.js +82 -0
  117. package/scripts/validate/links.js +166 -0
  118. package/scripts/validate/parity.js +122 -0
  119. package/scripts/validate/root.js +183 -0
  120. package/scripts/validate/rules.js +42 -0
  121. package/scripts/validate/skills.js +94 -0
  122. package/scripts/validate/text.js +27 -0
  123. package/scripts/validate-cli.js +12 -0
  124. package/scripts/validate.js +158 -258
  125. package/src/cli-parse.ts +77 -0
  126. package/src/cli-target.ts +167 -0
  127. package/src/cli.ts +240 -0
  128. package/src/errors.ts +35 -0
  129. package/src/git.ts +34 -0
  130. package/src/guards.ts +101 -0
  131. package/src/index.ts +39 -0
  132. package/src/links.ts +139 -0
  133. package/src/permissions.ts +42 -0
  134. package/src/repo.ts +94 -0
  135. package/src/scaffold.ts +273 -0
  136. package/.github/copilot-instructions.md +0 -1
@@ -1,255 +1,419 @@
1
- #!/usr/bin/env bash
2
- # ==============================================================================
3
- # bootstrap_workspace.sh
4
- # Topology-Aware Deterministic Scaffolder (Strict YAGNI, Zero Speculative Bloat)
5
- # ==============================================================================
6
-
7
- set -euo pipefail
8
-
9
- WORKSPACE_ROOT="${1:-$(pwd)}"
10
- TOPOLOGY="${2:-backend}"
11
- LANGUAGE="${3:-generic}"
12
-
13
- echo "🚀 Initializing Topology-Aware Workspace in: ${WORKSPACE_ROOT}"
14
- echo "🏗️ Target Topology: ${TOPOLOGY}"
15
- echo "📦 Target Language Profile: ${LANGUAGE}"
16
- echo "--------------------------------------------------------------"
17
-
18
- # Helper to create leaf directory with .gitkeep to ensure Git tracks empty structures
19
- create_leaf() {
20
- local dir="$1"
21
- mkdir -p "${dir}"
22
- if [[ -z "$(ls -A "${dir}" 2>/dev/null)" ]]; then
23
- touch "${dir}/.gitkeep"
24
- fi
25
- }
26
-
27
- case "${TOPOLOGY}" in
28
- extension)
29
- echo "1. Scaffolding Browser Extension Source Tree (src/)..."
30
- create_leaf "${WORKSPACE_ROOT}/src/background"
31
- create_leaf "${WORKSPACE_ROOT}/src/content"
32
- create_leaf "${WORKSPACE_ROOT}/src/popup"
33
- create_leaf "${WORKSPACE_ROOT}/src/shared"
34
- create_leaf "${WORKSPACE_ROOT}/public"
35
-
36
- echo "2. Scaffolding Extension Test Suites (tests/)..."
37
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
38
- create_leaf "${WORKSPACE_ROOT}/tests/e2e"
39
- ;;
40
-
41
- game|engine)
42
- echo "1. Scaffolding Game/Engine Source Tree (src/)..."
43
- create_leaf "${WORKSPACE_ROOT}/src/core"
44
- create_leaf "${WORKSPACE_ROOT}/src/ecs"
45
- create_leaf "${WORKSPACE_ROOT}/src/renderer"
46
- create_leaf "${WORKSPACE_ROOT}/src/assets"
47
-
48
- echo "2. Scaffolding Game/Engine Test Suites (tests/)..."
49
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
50
- create_leaf "${WORKSPACE_ROOT}/tests/benchmarks"
51
- ;;
52
-
53
- cli)
54
- echo "1. Scaffolding CLI Source Tree (src/)..."
55
- create_leaf "${WORKSPACE_ROOT}/src/cmd"
56
- create_leaf "${WORKSPACE_ROOT}/src/core"
57
- create_leaf "${WORKSPACE_ROOT}/src/io"
58
-
59
- echo "2. Scaffolding CLI Test Suites (tests/)..."
60
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
61
- create_leaf "${WORKSPACE_ROOT}/tests/integration"
62
- ;;
63
-
64
- web|saas|fullstack)
65
- echo "1. Scaffolding Backend / Enterprise Source Tree (src/)..."
66
- create_leaf "${WORKSPACE_ROOT}/src/domain/entities"
67
- create_leaf "${WORKSPACE_ROOT}/src/domain/value_objects"
68
- create_leaf "${WORKSPACE_ROOT}/src/domain/services"
69
- create_leaf "${WORKSPACE_ROOT}/src/ports/primary"
70
- create_leaf "${WORKSPACE_ROOT}/src/ports/secondary"
71
- create_leaf "${WORKSPACE_ROOT}/src/adapters/primary"
72
- create_leaf "${WORKSPACE_ROOT}/src/adapters/secondary"
73
-
74
- echo "2. Scaffolding Web Frontend Client Source Tree (client/)..."
75
- create_leaf "${WORKSPACE_ROOT}/client/src/components/layout"
76
- create_leaf "${WORKSPACE_ROOT}/client/src/components/ui"
77
- create_leaf "${WORKSPACE_ROOT}/client/src/pages"
78
- create_leaf "${WORKSPACE_ROOT}/client/src/hooks"
79
- create_leaf "${WORKSPACE_ROOT}/client/src/services"
80
- create_leaf "${WORKSPACE_ROOT}/client/public"
81
-
82
- echo "3. Scaffolding Specifications (specs/)..."
83
- create_leaf "${WORKSPACE_ROOT}/specs/openapi"
84
- create_leaf "${WORKSPACE_ROOT}/specs/tokens"
85
-
86
- echo "4. Scaffolding Fullstack Test Suites (tests/)..."
87
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
88
- create_leaf "${WORKSPACE_ROOT}/tests/integration"
89
- create_leaf "${WORKSPACE_ROOT}/tests/contracts"
90
- create_leaf "${WORKSPACE_ROOT}/tests/client"
91
- create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
92
-
93
- echo "5. Scaffolding Deployment Infrastructure (deploy/)..."
94
- create_leaf "${WORKSPACE_ROOT}/deploy/docker"
95
- create_leaf "${WORKSPACE_ROOT}/deploy/compose"
96
-
97
- TOKEN_SPEC="${WORKSPACE_ROOT}/specs/tokens/tokens.json"
98
- if [[ ! -f "${TOKEN_SPEC}" ]]; then
99
- cat << 'EOF' > "${TOKEN_SPEC}"
100
- {
101
- "color": {
102
- "brand": {
103
- "primary": { "$value": "#2563eb", "$type": "color" },
104
- "secondary": { "$value": "#475569", "$type": "color" },
105
- "accent": { "$value": "#f59e0b", "$type": "color" }
106
- }
107
- },
108
- "dimension": {
109
- "radius": {
110
- "base": { "$value": "6px", "$type": "dimension" }
111
- }
112
- }
113
- }
114
- EOF
115
- fi
116
- ;;
117
-
118
- backend)
119
- echo "1. Scaffolding Headless Backend Source Tree (src/)..."
120
- create_leaf "${WORKSPACE_ROOT}/src/domain/entities"
121
- create_leaf "${WORKSPACE_ROOT}/src/domain/value_objects"
122
- create_leaf "${WORKSPACE_ROOT}/src/domain/services"
123
- create_leaf "${WORKSPACE_ROOT}/src/ports/primary"
124
- create_leaf "${WORKSPACE_ROOT}/src/ports/secondary"
125
- create_leaf "${WORKSPACE_ROOT}/src/adapters/primary"
126
- create_leaf "${WORKSPACE_ROOT}/src/adapters/secondary"
127
-
128
- echo "2. Scaffolding Specifications (specs/)..."
129
- create_leaf "${WORKSPACE_ROOT}/specs/openapi"
130
- create_leaf "${WORKSPACE_ROOT}/specs/tokens"
131
-
132
- echo "3. Scaffolding Backend Test Suites (tests/)..."
133
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
134
- create_leaf "${WORKSPACE_ROOT}/tests/integration"
135
- create_leaf "${WORKSPACE_ROOT}/tests/contracts"
136
- create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
137
-
138
- echo "4. Scaffolding Deployment Infrastructure (deploy/)..."
139
- create_leaf "${WORKSPACE_ROOT}/deploy/docker"
140
- create_leaf "${WORKSPACE_ROOT}/deploy/compose"
141
-
142
- TOKEN_SPEC="${WORKSPACE_ROOT}/specs/tokens/tokens.json"
143
- if [[ ! -f "${TOKEN_SPEC}" ]]; then
144
- cat << 'EOF' > "${TOKEN_SPEC}"
145
- {
146
- "color": {
147
- "brand": {
148
- "primary": { "$value": "#2563eb", "$type": "color" },
149
- "secondary": { "$value": "#475569", "$type": "color" },
150
- "accent": { "$value": "#f59e0b", "$type": "color" }
151
- }
152
- },
153
- "dimension": {
154
- "radius": {
155
- "base": { "$value": "6px", "$type": "dimension" }
156
- }
157
- }
158
- }
159
- EOF
160
- fi
161
- ;;
162
-
163
- frontend)
164
- echo "1. Scaffolding Frontend Client Source Tree (src/)..."
165
- create_leaf "${WORKSPACE_ROOT}/src/components/layout"
166
- create_leaf "${WORKSPACE_ROOT}/src/components/ui"
167
- create_leaf "${WORKSPACE_ROOT}/src/pages"
168
- create_leaf "${WORKSPACE_ROOT}/src/hooks"
169
- create_leaf "${WORKSPACE_ROOT}/src/services"
170
- create_leaf "${WORKSPACE_ROOT}/public"
171
-
172
- echo "2. Scaffolding Specifications (specs/)..."
173
- create_leaf "${WORKSPACE_ROOT}/specs/tokens"
174
-
175
- echo "3. Scaffolding Frontend Test Suites (tests/)..."
176
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
177
- create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
178
- ;;
179
-
180
- *)
181
- echo "1. Scaffolding Generic / Library Source Tree (src/)..."
182
- create_leaf "${WORKSPACE_ROOT}/src"
183
- create_leaf "${WORKSPACE_ROOT}/tests/unit"
184
- ;;
185
- esac
186
-
187
- # Ensure memory.md in fresh projects starts with a clean ADR slate (ADR-001)
188
- MEMORY_FILE="${WORKSPACE_ROOT}/memory.md"
189
- if [[ -f "${MEMORY_FILE}" ]]; then
190
- if grep -qE "ADR-00[1-9]|ADR-0[1-9][0-9]|#### ADR-" "${MEMORY_FILE}"; then
191
- if ! grep -q "No decisions recorded yet" "${MEMORY_FILE}"; then
192
- echo "🧹 Sanitizing memory.md: Resetting legacy template ADRs to clean slate (ADR-001)..."
193
- cat << 'EOF' > "${MEMORY_FILE}"
194
- # Workspace Memory, Architecture Decisions & Knowledge Hub
195
-
196
- > **Core Purpose:** Authoritative persistent memory ledger for the workspace repository (`./`), maintaining Lightweight Architectural Decision Records (ADRs), system topologies, and living domain contracts.
197
-
198
- ---
199
-
200
- ## 1. Quick Navigation & Knowledge Repositories
201
-
202
- - 📖 **[Living Ubiquitous Language Glossary](./docs/knowledge/ubiquitous_language.md)**: Authoritative, single-name domain vocabulary contract.
203
- - 📜 **[Lightweight ADR Master Index](#adr-master-index)**: Summary of all architectural decisions and direct links to governing rules.
204
-
205
- ---
206
-
207
- ## 2. Consolidated Architectural Decision Records (ADRs)
208
-
209
- ### ADR Master Index
210
-
211
- | ID | Title | Date | Status | Governing Rule / Skill |
212
- |---|---|---|---|---|
213
- | *(No decisions recorded yet)* | *Record initial architecture decisions during Phase 3 of /lets-build.* | *YYYY-MM-DD* | *ACCEPTED* | *e.g. [`clean_code.md`](./docs/rules/clean_code.md)* |
214
-
215
- ---
216
-
217
- ### Lightweight Decision Summaries
218
-
219
- <!--
220
- Record project Architectural Decision Records (ADRs) below as decisions are finalized.
221
- Format:
222
-
223
- #### ADR-001: [Imperative Title]
224
- - **Date:** YYYY-MM-DD | **Status:** ACCEPTED
225
- - **Context:** Problem space, constraints, and operational context requiring a decision.
226
- - **Decision:** Chosen architecture, invariants, and implementation patterns.
227
- - **Consequences:** Positive benefits and deliberate trade-offs accepted.
228
- - **Enforced In:** Relevant rule files in docs/rules/ or code paths.
229
- -->
230
- EOF
231
- fi
232
- fi
233
- fi
234
-
235
- # Deterministically generate boundary verification smoke test script (Phase 5 requirement)
236
- SMOKE_TEST="${WORKSPACE_ROOT}/scripts/smoke_test.sh"
237
- if [[ ! -f "${SMOKE_TEST}" ]]; then
238
- echo "5. Generating boundary smoke test verification script (scripts/smoke_test.sh)..."
239
- mkdir -p "${WORKSPACE_ROOT}/scripts"
240
- cat << 'EOF' > "${SMOKE_TEST}"
241
- #!/usr/bin/env bash
242
- # ==============================================================================
243
- # Boundary Verification Smoke Test (Phase 5 Verification Gate)
244
- # ==============================================================================
245
- set -euo pipefail
246
-
247
- echo "Running boundary smoke verification..."
248
- # Extend with project-specific runtime health checks (e.g. ping health endpoint, CLI --help)
249
- echo "✅ Boundary smoke verification passed!"
250
- EOF
251
- chmod +x "${SMOKE_TEST}"
252
- fi
253
-
254
- echo "--------------------------------------------------------------"
255
- echo "✅ Topology '${TOPOLOGY}' scaffolded with strict YAGNI (0 speculative folders)!"
1
+ #!/usr/bin/env bash
2
+ # ==============================================================================
3
+ # bootstrap_workspace.sh
4
+ # Topology-Aware Deterministic Scaffolder (Strict YAGNI, Zero Speculative Bloat)
5
+ # ==============================================================================
6
+
7
+ set -euo pipefail
8
+
9
+ WORKSPACE_ROOT="${1:-$(pwd)}"
10
+ TOPOLOGY="${2:-backend}"
11
+ LANGUAGE="${3:-generic}"
12
+
13
+ echo "🚀 Initializing Topology-Aware Workspace in: ${WORKSPACE_ROOT}"
14
+ echo "🏗️ Target Topology: ${TOPOLOGY}"
15
+ echo "📦 Target Language Profile: ${LANGUAGE}"
16
+ echo "--------------------------------------------------------------"
17
+
18
+ # ------------------------------------------------------------------------------
19
+ # LANGUAGE is validated, not merely echoed. It previously appeared in the
20
+ # banner and nowhere else: every language produced an identical tree, which
21
+ # made the "deterministic scaffolder" claim false and hid typos from the agent.
22
+ # Unknown values are rejected instead of silently producing a generic layout.
23
+ # ------------------------------------------------------------------------------
24
+ case "${LANGUAGE}" in
25
+ typescript|javascript|python|rust|go|java|csharp|cpp|c|generic|deno|bun)
26
+ ;;
27
+ *)
28
+ echo "❌ Unknown language profile: '${LANGUAGE}'" >&2
29
+ cat >&2 << 'EOF'
30
+
31
+ Supported language profiles:
32
+ typescript javascript deno bun python rust go java csharp cpp c
33
+ generic
34
+
35
+ Use 'generic' when the language has not been decided yet.
36
+ EOF
37
+ exit 2
38
+ ;;
39
+ esac
40
+
41
+ # ------------------------------------------------------------------------------
42
+ # PROTECTED TARGETS. The scaffolder creates directories and files, so it must
43
+ # never run against the filesystem root, the user's home directory, or the
44
+ # home directory's parent (scaffolding into /home or C:\Users affects every
45
+ # user on the machine). This mirrors lib/scaffold.js isProtectedTarget(), which
46
+ # enforces the same rule -- plus template-ancestor and symlink checks -- for
47
+ # the Node scaffolder with E_TARGET_IS_PROTECTED.
48
+ #
49
+ # The check runs BEFORE anything is created: even the .azcodr profile write
50
+ # below must not execute for a protected target.
51
+ # ------------------------------------------------------------------------------
52
+ resolve_absolute() {
53
+ local p="$1"
54
+ if [[ -e "$p" ]]; then
55
+ (cd "$p" 2>/dev/null && pwd -P)
56
+ elif [[ -d "$(dirname "$p")" ]]; then
57
+ printf '%s/%s' "$(cd "$(dirname "$p")" 2>/dev/null && pwd -P)" "$(basename "$p")"
58
+ elif [[ "$p" = /* ]]; then
59
+ printf '%s' "$p"
60
+ else
61
+ printf '%s/%s' "$(pwd -P)" "$p"
62
+ fi
63
+ }
64
+
65
+ lowercase() {
66
+ # ${var,,} needs bash 4+; macOS ships bash 3.2, so use tr.
67
+ printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
68
+ }
69
+
70
+ RESOLVED_ROOT="$(resolve_absolute "${WORKSPACE_ROOT}")"
71
+ RESOLVED_HOME="$(resolve_absolute "${HOME:-/nonexistent-home}")"
72
+ LOWER_ROOT="$(lowercase "${RESOLVED_ROOT}")"
73
+ LOWER_HOME="$(lowercase "${RESOLVED_HOME}")"
74
+ HOME_PARENT="$(dirname "${RESOLVED_HOME}")"
75
+ LOWER_HOME_PARENT="$(lowercase "${HOME_PARENT}")"
76
+
77
+ PROTECTED_REASON=""
78
+ if [[ "${RESOLVED_ROOT}" == "/" ]]; then
79
+ PROTECTED_REASON="the filesystem root"
80
+ elif [[ "${RESOLVED_ROOT}" =~ ^/[a-zA-Z]$ ]]; then
81
+ # Git-Bash drive root (/c, /d, ...).
82
+ PROTECTED_REASON="a drive root"
83
+ elif [[ "$RESOLVED_ROOT" =~ ^[a-zA-Z]:[\\/]?$ ]]; then
84
+ # Native Windows drive root (C:\, D:).
85
+ PROTECTED_REASON="a drive root"
86
+ elif [[ "${LOWER_ROOT}" == "${LOWER_HOME}" ]]; then
87
+ PROTECTED_REASON="the home directory (${RESOLVED_HOME})"
88
+ elif [[ "${LOWER_ROOT}" == "${LOWER_HOME_PARENT}" ]]; then
89
+ PROTECTED_REASON="the home directory's parent (${HOME_PARENT})"
90
+ fi
91
+
92
+ if [[ -n "${PROTECTED_REASON}" && "${AZCODR_ALLOW_PROTECTED:-0}" != "1" ]]; then
93
+ echo "❌ Refusing to scaffold into protected directory: ${RESOLVED_ROOT} (${PROTECTED_REASON})." >&2
94
+ echo " Choose a project subdirectory instead." >&2
95
+ echo " Embedders that genuinely need this path: AZCODR_ALLOW_PROTECTED=1 <this command>" >&2
96
+ exit 2
97
+ fi
98
+
99
+ # Record the decided language so downstream phases can read it instead of
100
+ # re-deriving it (and so the scaffolder's own claim is verifiable).
101
+ mkdir -p "${WORKSPACE_ROOT}/.azcodr"
102
+ printf 'topology=%s\nlanguage=%s\n' "${TOPOLOGY}" "${LANGUAGE}" \
103
+ > "${WORKSPACE_ROOT}/.azcodr/workspace-profile.env"
104
+
105
+ # Helper to create leaf directory with .gitkeep to ensure Git tracks empty structures
106
+ create_leaf() {
107
+ local dir="$1"
108
+ mkdir -p "${dir}"
109
+ if [[ -z "$(ls -A "${dir}" 2>/dev/null)" ]]; then
110
+ touch "${dir}/.gitkeep"
111
+ fi
112
+ }
113
+
114
+ case "${TOPOLOGY}" in
115
+ extension)
116
+ echo "1. Scaffolding Browser Extension Source Tree (src/)..."
117
+ create_leaf "${WORKSPACE_ROOT}/src/background"
118
+ create_leaf "${WORKSPACE_ROOT}/src/content"
119
+ create_leaf "${WORKSPACE_ROOT}/src/popup"
120
+ create_leaf "${WORKSPACE_ROOT}/src/shared"
121
+ create_leaf "${WORKSPACE_ROOT}/public"
122
+
123
+ echo "2. Scaffolding Extension Test Suites (tests/)..."
124
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
125
+ create_leaf "${WORKSPACE_ROOT}/tests/e2e"
126
+ ;;
127
+
128
+ game|engine)
129
+ echo "1. Scaffolding Game/Engine Source Tree (src/)..."
130
+ create_leaf "${WORKSPACE_ROOT}/src/core"
131
+ create_leaf "${WORKSPACE_ROOT}/src/ecs"
132
+ create_leaf "${WORKSPACE_ROOT}/src/renderer"
133
+ create_leaf "${WORKSPACE_ROOT}/src/assets"
134
+
135
+ echo "2. Scaffolding Game/Engine Test Suites (tests/)..."
136
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
137
+ create_leaf "${WORKSPACE_ROOT}/tests/benchmarks"
138
+ ;;
139
+
140
+ cli)
141
+ echo "1. Scaffolding CLI Source Tree (src/)..."
142
+ create_leaf "${WORKSPACE_ROOT}/src/cmd"
143
+ create_leaf "${WORKSPACE_ROOT}/src/core"
144
+ create_leaf "${WORKSPACE_ROOT}/src/io"
145
+
146
+ echo "2. Scaffolding CLI Test Suites (tests/)..."
147
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
148
+ create_leaf "${WORKSPACE_ROOT}/tests/integration"
149
+ ;;
150
+
151
+ web|saas|fullstack)
152
+ echo "1. Scaffolding Backend / Enterprise Source Tree (src/)..."
153
+ create_leaf "${WORKSPACE_ROOT}/src/domain/entities"
154
+ create_leaf "${WORKSPACE_ROOT}/src/domain/value_objects"
155
+ create_leaf "${WORKSPACE_ROOT}/src/domain/services"
156
+ create_leaf "${WORKSPACE_ROOT}/src/ports/primary"
157
+ create_leaf "${WORKSPACE_ROOT}/src/ports/secondary"
158
+ create_leaf "${WORKSPACE_ROOT}/src/adapters/primary"
159
+ create_leaf "${WORKSPACE_ROOT}/src/adapters/secondary"
160
+
161
+ echo "2. Scaffolding Web Frontend Client Source Tree (client/)..."
162
+ create_leaf "${WORKSPACE_ROOT}/client/src/components/layout"
163
+ create_leaf "${WORKSPACE_ROOT}/client/src/components/ui"
164
+ create_leaf "${WORKSPACE_ROOT}/client/src/pages"
165
+ create_leaf "${WORKSPACE_ROOT}/client/src/hooks"
166
+ create_leaf "${WORKSPACE_ROOT}/client/src/services"
167
+ create_leaf "${WORKSPACE_ROOT}/client/public"
168
+
169
+ echo "3. Scaffolding Specifications (specs/)..."
170
+ create_leaf "${WORKSPACE_ROOT}/specs/openapi"
171
+ create_leaf "${WORKSPACE_ROOT}/specs/tokens"
172
+
173
+ echo "4. Scaffolding Fullstack Test Suites (tests/)..."
174
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
175
+ create_leaf "${WORKSPACE_ROOT}/tests/integration"
176
+ create_leaf "${WORKSPACE_ROOT}/tests/contracts"
177
+ create_leaf "${WORKSPACE_ROOT}/tests/client"
178
+ create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
179
+
180
+ echo "5. Scaffolding Deployment Infrastructure (deploy/)..."
181
+ create_leaf "${WORKSPACE_ROOT}/deploy/docker"
182
+ create_leaf "${WORKSPACE_ROOT}/deploy/compose"
183
+
184
+ TOKEN_SPEC="${WORKSPACE_ROOT}/specs/tokens/tokens.json"
185
+ if [[ ! -f "${TOKEN_SPEC}" ]]; then
186
+ cat << 'EOF' > "${TOKEN_SPEC}"
187
+ {
188
+ "color": {
189
+ "brand": {
190
+ "primary": { "$value": "#2563eb", "$type": "color" },
191
+ "secondary": { "$value": "#475569", "$type": "color" },
192
+ "accent": { "$value": "#f59e0b", "$type": "color" }
193
+ }
194
+ },
195
+ "dimension": {
196
+ "radius": {
197
+ "base": { "$value": "6px", "$type": "dimension" }
198
+ }
199
+ }
200
+ }
201
+ EOF
202
+ fi
203
+ ;;
204
+
205
+ backend)
206
+ echo "1. Scaffolding Headless Backend Source Tree (src/)..."
207
+ create_leaf "${WORKSPACE_ROOT}/src/domain/entities"
208
+ create_leaf "${WORKSPACE_ROOT}/src/domain/value_objects"
209
+ create_leaf "${WORKSPACE_ROOT}/src/domain/services"
210
+ create_leaf "${WORKSPACE_ROOT}/src/ports/primary"
211
+ create_leaf "${WORKSPACE_ROOT}/src/ports/secondary"
212
+ create_leaf "${WORKSPACE_ROOT}/src/adapters/primary"
213
+ create_leaf "${WORKSPACE_ROOT}/src/adapters/secondary"
214
+
215
+ echo "2. Scaffolding Specifications (specs/)..."
216
+ create_leaf "${WORKSPACE_ROOT}/specs/openapi"
217
+ create_leaf "${WORKSPACE_ROOT}/specs/tokens"
218
+
219
+ echo "3. Scaffolding Backend Test Suites (tests/)..."
220
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
221
+ create_leaf "${WORKSPACE_ROOT}/tests/integration"
222
+ create_leaf "${WORKSPACE_ROOT}/tests/contracts"
223
+ create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
224
+
225
+ echo "4. Scaffolding Deployment Infrastructure (deploy/)..."
226
+ create_leaf "${WORKSPACE_ROOT}/deploy/docker"
227
+ create_leaf "${WORKSPACE_ROOT}/deploy/compose"
228
+
229
+ TOKEN_SPEC="${WORKSPACE_ROOT}/specs/tokens/tokens.json"
230
+ if [[ ! -f "${TOKEN_SPEC}" ]]; then
231
+ cat << 'EOF' > "${TOKEN_SPEC}"
232
+ {
233
+ "color": {
234
+ "brand": {
235
+ "primary": { "$value": "#2563eb", "$type": "color" },
236
+ "secondary": { "$value": "#475569", "$type": "color" },
237
+ "accent": { "$value": "#f59e0b", "$type": "color" }
238
+ }
239
+ },
240
+ "dimension": {
241
+ "radius": {
242
+ "base": { "$value": "6px", "$type": "dimension" }
243
+ }
244
+ }
245
+ }
246
+ EOF
247
+ fi
248
+ ;;
249
+
250
+ frontend)
251
+ echo "1. Scaffolding Frontend Client Source Tree (src/)..."
252
+ create_leaf "${WORKSPACE_ROOT}/src/components/layout"
253
+ create_leaf "${WORKSPACE_ROOT}/src/components/ui"
254
+ create_leaf "${WORKSPACE_ROOT}/src/pages"
255
+ create_leaf "${WORKSPACE_ROOT}/src/hooks"
256
+ create_leaf "${WORKSPACE_ROOT}/src/services"
257
+ create_leaf "${WORKSPACE_ROOT}/public"
258
+
259
+ echo "2. Scaffolding Specifications (specs/)..."
260
+ create_leaf "${WORKSPACE_ROOT}/specs/tokens"
261
+
262
+ echo "3. Scaffolding Frontend Test Suites (tests/)..."
263
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
264
+ create_leaf "${WORKSPACE_ROOT}/tests/acceptance"
265
+ ;;
266
+
267
+ canvas-game|canvas|webgame)
268
+ # Topology D: Browser / Canvas Game (HTML5 Canvas / WebGL / WebGPU).
269
+ # Game Loop shaped: Input -> Update -> Render.
270
+ echo "1. Scaffolding Canvas Game Source Tree (game loop shaped)..."
271
+ create_leaf "${WORKSPACE_ROOT}/src/entities"
272
+ create_leaf "${WORKSPACE_ROOT}/src/systems/update"
273
+ create_leaf "${WORKSPACE_ROOT}/src/systems/render"
274
+ create_leaf "${WORKSPACE_ROOT}/src/input"
275
+ create_leaf "${WORKSPACE_ROOT}/src/audio"
276
+ create_leaf "${WORKSPACE_ROOT}/src/ui"
277
+ create_leaf "${WORKSPACE_ROOT}/src/scenes"
278
+ create_leaf "${WORKSPACE_ROOT}/src/config"
279
+
280
+ echo "2. Scaffolding Canvas Game Tests (tests/)..."
281
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
282
+ create_leaf "${WORKSPACE_ROOT}/tests/e2e"
283
+
284
+ echo "3. Scaffolding Public Assets (public/)..."
285
+ create_leaf "${WORKSPACE_ROOT}/public/assets"
286
+ ;;
287
+
288
+ systems-library|embedded|systems)
289
+ # Topology F: Embedded / Systems Library.
290
+ # No heap assumptions, no dynamic allocation in the hot path.
291
+ echo "1. Scaffolding Systems Library Source Tree (src/)..."
292
+ create_leaf "${WORKSPACE_ROOT}/src/core"
293
+ create_leaf "${WORKSPACE_ROOT}/src/hal"
294
+ create_leaf "${WORKSPACE_ROOT}/src/drivers"
295
+ create_leaf "${WORKSPACE_ROOT}/src/protocol"
296
+ create_leaf "${WORKSPACE_ROOT}/src/utils"
297
+
298
+ echo "2. Scaffolding Systems Library Tests (tests/)..."
299
+ create_leaf "${WORKSPACE_ROOT}/tests/unit"
300
+ create_leaf "${WORKSPACE_ROOT}/tests/hal"
301
+ create_leaf "${WORKSPACE_ROOT}/tests/benchmarks"
302
+ ;;
303
+
304
+ *)
305
+ # Fail loudly rather than scaffolding a generic tree and exiting 0. A
306
+ # wrong-but-successful scaffold is worse than a refusal: the agent reports
307
+ # success to the user and the mismatch surfaces much later.
308
+ echo "❌ Unknown topology: '${TOPOLOGY}'" >&2
309
+ cat >&2 << 'EOF'
310
+
311
+ Supported topologies:
312
+ extension Topology B Browser Extension (Manifest V3)
313
+ game|engine Topology C Game Engine / High-Performance Simulator
314
+ canvas-game Topology D Browser / Canvas Game (Canvas/WebGL/WebGPU)
315
+ cli Topology E Desktop Application / CLI Utility
316
+ backend Topology A Headless API / Service
317
+ web|saas|fullstack Topology A Fullstack Web Application
318
+ frontend Topology A Frontend-only Client
319
+ systems-library Topology F Embedded / Systems Library
320
+ EOF
321
+ echo >&2
322
+ echo "Re-run with one of the above." >&2
323
+ exit 2
324
+ ;;
325
+ esac
326
+
327
+ # ------------------------------------------------------------------------------
328
+ # memory.md is an APPEND-ONLY LEDGER. It is never rewritten automatically.
329
+ #
330
+ # HISTORY (this was a data-loss bug): this script previously overwrote
331
+ # memory.md with a template whenever the file contained any ADR heading that
332
+ # was not the untouched placeholder. Re-running /lets-build on a live project
333
+ # silently destroyed every recorded architectural decision -- irreplaceable
334
+ # work, with no backup and no error. ADRs are immutable history by rule
335
+ # (docs/rules/agentic_configuration.md); a scaffolder has no business
336
+ # rewriting them.
337
+ #
338
+ # Resetting the ledger is now opt-in, always backed up, and always announced.
339
+ # ------------------------------------------------------------------------------
340
+ MEMORY_FILE="${WORKSPACE_ROOT}/memory.md"
341
+ if [[ -f "${MEMORY_FILE}" ]]; then
342
+ # Only a genuinely recorded decision counts as "has content": an h4 ADR
343
+ # heading outside of an HTML comment.
344
+ RECORDED_ADRS="$(grep -cE '^####[[:space:]]+ADR-[0-9]+' "${MEMORY_FILE}" 2>/dev/null || true)"
345
+ RECORDED_ADRS="${RECORDED_ADRS:-0}"
346
+
347
+ if [[ "${RECORDED_ADRS}" -gt 0 ]]; then
348
+ if [[ "${AZCODR_RESET_MEMORY:-0}" == "1" ]]; then
349
+ BACKUP="${MEMORY_FILE}.bak"
350
+ cp -p "${MEMORY_FILE}" "${BACKUP}"
351
+ echo "⚠️ AZCODR_RESET_MEMORY=1 -- RESETTING ${RECORDED_ADRS} recorded ADR(s) in memory.md"
352
+ echo " Backup written to ${BACKUP}"
353
+ cat << 'EOF' > "${MEMORY_FILE}"
354
+ # Workspace Memory, Architecture Decisions & Knowledge Hub
355
+
356
+ > **Core Purpose:** Authoritative persistent memory ledger for the workspace repository (`./`), maintaining Lightweight Architectural Decision Records (ADRs), system topologies, and living domain contracts.
357
+
358
+ ---
359
+
360
+ ## 1. Quick Navigation & Knowledge Repositories
361
+
362
+ - 📖 **[Living Ubiquitous Language Glossary](./docs/knowledge/ubiquitous_language.md)**: Authoritative, single-name domain vocabulary contract.
363
+ - 📜 **[Lightweight ADR Master Index](#adr-master-index)**: Summary of all architectural decisions and direct links to governing rules.
364
+
365
+ ---
366
+
367
+ ## 2. Consolidated Architectural Decision Records (ADRs)
368
+
369
+ ### ADR Master Index
370
+
371
+ | ID | Title | Date | Status | Governing Rule / Skill |
372
+ |---|---|---|---|---|
373
+ | *(No decisions recorded yet)* | *Record initial architecture decisions during Phase 3 of /lets-build.* | *YYYY-MM-DD* | *ACCEPTED* | *e.g. [`clean_code.md`](./docs/rules/clean_code.md)* |
374
+
375
+ ---
376
+
377
+ ### Lightweight Decision Summaries
378
+
379
+ <!--
380
+ Record project Architectural Decision Records (ADRs) below as decisions are finalized.
381
+ Format:
382
+
383
+ #### ADR-001: [Imperative Title]
384
+ - **Date:** YYYY-MM-DD | **Status:** ACCEPTED
385
+ - **Context:** Problem space, constraints, and operational context requiring a decision.
386
+ - **Decision:** Chosen architecture, invariants, and implementation patterns.
387
+ - **Consequences:** Positive benefits and deliberate trade-offs accepted.
388
+ - **Enforced In:** Relevant rule files in docs/rules/ or code paths.
389
+ -->
390
+ EOF
391
+ else
392
+ echo "🧠 Preserving memory.md: ${RECORDED_ADRS} recorded ADR(s) found."
393
+ echo " memory.md is append-only and is never rewritten by the scaffolder."
394
+ echo " To intentionally reset the ledger: AZCODR_RESET_MEMORY=1 <this command>"
395
+ fi
396
+ fi
397
+ fi
398
+
399
+ # Deterministically generate boundary verification smoke test script (Phase 5 requirement)
400
+ SMOKE_TEST="${WORKSPACE_ROOT}/scripts/smoke_test.sh"
401
+ if [[ ! -f "${SMOKE_TEST}" ]]; then
402
+ echo "5. Generating boundary smoke test verification script (scripts/smoke_test.sh)..."
403
+ mkdir -p "${WORKSPACE_ROOT}/scripts"
404
+ cat << 'EOF' > "${SMOKE_TEST}"
405
+ #!/usr/bin/env bash
406
+ # ==============================================================================
407
+ # Boundary Verification Smoke Test (Phase 5 Verification Gate)
408
+ # ==============================================================================
409
+ set -euo pipefail
410
+
411
+ echo "Running boundary smoke verification..."
412
+ # Extend with project-specific runtime health checks (e.g. ping health endpoint, CLI --help)
413
+ echo "✅ Boundary smoke verification passed!"
414
+ EOF
415
+ chmod +x "${SMOKE_TEST}"
416
+ fi
417
+
418
+ echo "--------------------------------------------------------------"
419
+ echo "✅ Topology '${TOPOLOGY}' scaffolded with strict YAGNI (0 speculative folders)!"