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,102 +1,102 @@
1
- # Adaptive Questioning Trees & Contextual Branching Matrices
2
-
3
- > **Core Purpose:** Detailed decision trees for the `relentless-questioner` skill, demonstrating how subsequent questions adapt dynamically based on previous user responses.
4
-
5
- ---
6
-
7
- ## Decision Tree 1: Mutating Operations & State Changes
8
-
9
- ```mermaid
10
- flowchart TD
11
- Q1["Does the operation mutate database state?"]
12
- Q1 -->|Yes| Q2["Does it involve multiple tables, monetary balances, or inventory?"]
13
- Q1 -->|No / Read Only| Q_Read["Branch: Read Performance & Consistency"]
14
-
15
- Q2 -->|Yes: Financial / Inventory| Q_Acid["1. Transaction Isolation: REPEATABLE READ or SERIALIZABLE?\n2. Lock Ordering: How to prevent deadlocks?\n3. Concurrency: Optimistic Concurrency Control (version) or pessimistic locking?"]
16
- Q2 -->|No: Standard Entity CRUD| Q_Crud["1. Soft delete or hard delete?\n2. Unique constraints across tenant?\n3. Cascading relations?"]
17
-
18
- Q_Acid --> Q3["Does the mutation emit domain events or notify external systems?"]
19
- Q_Crud --> Q3
20
-
21
- Q3 -->|Yes| Q_Outbox["How is the dual-write avoided?\n(Enforce Transactional Outbox pattern before broker publish)"]
22
- Q3 -->|No| Q4["Idempotency: Is an Idempotency-Key header required to guard against network retries?"]
23
- ```
24
-
25
- ---
26
-
27
- ## Decision Tree 2: Multi-Tenancy & Authorization Boundaries
28
-
29
- ```mermaid
30
- flowchart TD
31
- Q1["Who executes this action and across which boundary?"]
32
- Q1 -->|End User via Web/API| Q_Auth["1. What roles are permitted (ADMIN, MEMBER, CUSTOMER)?\n2. Are dynamic ABAC attributes involved (e.g. order value threshold)?\n3. Can a user act across multiple tenants (switch tenant)?"]
33
- Q1 -->|System / Background Job| Q_Worker["1. How is tenant context established without an HTTP session?\n2. What service principal / token credentials are used?"]
34
-
35
- Q_Auth --> Q2["What happens if an unauthorized tenant accesses this resource ID?"]
36
- Q2 --> Q_Sec["1. Return 404 Not Found (enumeration masking) or 403 Forbidden?\n2. Is isolation enforced at the DB layer (RLS / AST interceptor)?"]
37
- ```
38
-
39
- ---
40
-
41
- ## Decision Tree 3: External Integrations & 3rd-Party APIs
42
-
43
- ```mermaid
44
- flowchart TD
45
- Q1["Does the feature integrate with an external SaaS or network endpoint?"]
46
- Q1 -->|Yes| Q2["What is the failure tolerance of the integration?"]
47
-
48
- Q2 -->|Synchronous / Critical| Q_Sync["1. What is the strict HTTP timeout (e.g. 3000ms)?\n2. What is the circuit breaker threshold before fast-failing?\n3. What fallback response is served if the 3rd-party is down?"]
49
- Q2 -->|Asynchronous / Event-Driven| Q_Async["1. Does the external system provide webhooks?\n2. How are webhook signatures cryptographically verified?\n3. What is the retry backoff and dead-letter queue (DLQ) policy?"]
50
-
51
- Q_Sync --> Q_Port["How is the external SDK isolated?\n(Enforce application-owned Port interface so domain never imports SDK)"]
52
- Q_Async --> Q_Port
53
- ```
54
-
55
- ---
56
-
57
- ## Decision Tree 4: Read Performance, Caching & Search
58
-
59
- ```mermaid
60
- flowchart TD
61
- Q1["What is the expected read volume and latency requirement?"]
62
- Q1 -->|High Volume / Sub-50ms Latency| Q2["Is stale data acceptable for seconds/minutes?"]
63
-
64
- Q2 -->|Yes| Q_Cache["1. What is the cache TTL and jitter window?\n2. What domain events trigger cache eviction?\n3. Is probabilistic early expiration (XFetch) needed?"]
65
- Q2 -->|No: Strict Read-After-Write Consistency| Q_Consistent["1. Read from primary database instance for 2s after mutation\n2. Bypass read replicas during write session"]
66
-
67
- Q_Cache --> Q_Page["Pagination Strategy: Enforce keyset/cursor pagination over OFFSET"]
68
- Q_Consistent --> Q_Page
69
- ```
70
-
71
- ---
72
-
73
- ## Decision Tree 5: User Interface, Experience Duality & Interaction Flows
74
-
75
- ```mermaid
76
- flowchart TD
77
- Q1["Does the feature introduce or modify a user interface?"]
78
- Q1 -->|Yes| Q2["Who is the primary actor and operational persona?"]
79
-
80
- Q2 -->|Operator / Admin| Q_Op["1. Information Density: Dense tabular grid with filters?\n2. Persistent App Shell: Left collapsible sidebar route?\n3. Actions: Inline row actions or full-page drawer?"]
81
- Q2 -->|Consumer / Member| Q_Member["1. Experience Duality: Consumer portal (/portal)?\n2. Touch Ergonomics: Clean cards & mobile drawer?\n3. Simplified self-service actions?"]
82
-
83
- Q_Op --> Q3["Navigation & State Synchronization"]
84
- Q_Member --> Q3
85
-
86
- Q3 --> Q_State["1. URL State: Deep-link query params (?tab=, ?q=, ?page=, ?modal=)?\n2. Server Cache: TanStack Query hook with automated invalidation?\n3. Accessibility: Accessible headless dialogs & ARIA live regions?"]
87
- ```
88
-
89
- ---
90
-
91
- ## Contextual Follow-Up Patterns
92
-
93
- When conducting the interview, use this exact syntax pattern to chain questions adaptively:
94
-
95
- 1. **Acknowledge and Pin Previous Answer**:
96
- `"Understood, you specified [Option A] for [Requirement X]."`
97
- 2. **Surface Immediate Architectural Implication**:
98
- `"Because of [Option A], [Potential Failure / Edge Case Y] becomes the primary risk."`
99
- 3. **Ask Context-Dependent Question**:
100
- `"How should the system behave when [Condition Y] occurs? Specifically:"`
101
- - *Sub-question 1*
102
- - *Sub-question 2*
1
+ # Adaptive Questioning Trees & Contextual Branching Matrices
2
+
3
+ > **Core Purpose:** Detailed decision trees for the `relentless-questioner` skill, demonstrating how subsequent questions adapt dynamically based on previous user responses.
4
+
5
+ ---
6
+
7
+ ## Decision Tree 1: Mutating Operations & State Changes
8
+
9
+ ```mermaid
10
+ flowchart TD
11
+ Q1["Does the operation mutate database state?"]
12
+ Q1 -->|Yes| Q2["Does it involve multiple tables, monetary balances, or inventory?"]
13
+ Q1 -->|No / Read Only| Q_Read["Branch: Read Performance & Consistency"]
14
+
15
+ Q2 -->|Yes: Financial / Inventory| Q_Acid["1. Transaction Isolation: REPEATABLE READ or SERIALIZABLE?\n2. Lock Ordering: How to prevent deadlocks?\n3. Concurrency: Optimistic Concurrency Control (version) or pessimistic locking?"]
16
+ Q2 -->|No: Standard Entity CRUD| Q_Crud["1. Soft delete or hard delete?\n2. Unique constraints across tenant?\n3. Cascading relations?"]
17
+
18
+ Q_Acid --> Q3["Does the mutation emit domain events or notify external systems?"]
19
+ Q_Crud --> Q3
20
+
21
+ Q3 -->|Yes| Q_Outbox["How is the dual-write avoided?\n(Enforce Transactional Outbox pattern before broker publish)"]
22
+ Q3 -->|No| Q4["Idempotency: Is an Idempotency-Key header required to guard against network retries?"]
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Decision Tree 2: Multi-Tenancy & Authorization Boundaries
28
+
29
+ ```mermaid
30
+ flowchart TD
31
+ Q1["Who executes this action and across which boundary?"]
32
+ Q1 -->|End User via Web/API| Q_Auth["1. What roles are permitted (ADMIN, MEMBER, CUSTOMER)?\n2. Are dynamic ABAC attributes involved (e.g. order value threshold)?\n3. Can a user act across multiple tenants (switch tenant)?"]
33
+ Q1 -->|System / Background Job| Q_Worker["1. How is tenant context established without an HTTP session?\n2. What service principal / token credentials are used?"]
34
+
35
+ Q_Auth --> Q2["What happens if an unauthorized tenant accesses this resource ID?"]
36
+ Q2 --> Q_Sec["1. Return 404 Not Found (enumeration masking) or 403 Forbidden?\n2. Is isolation enforced at the DB layer (RLS / AST interceptor)?"]
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Decision Tree 3: External Integrations & 3rd-Party APIs
42
+
43
+ ```mermaid
44
+ flowchart TD
45
+ Q1["Does the feature integrate with an external SaaS or network endpoint?"]
46
+ Q1 -->|Yes| Q2["What is the failure tolerance of the integration?"]
47
+
48
+ Q2 -->|Synchronous / Critical| Q_Sync["1. What is the strict HTTP timeout (e.g. 3000ms)?\n2. What is the circuit breaker threshold before fast-failing?\n3. What fallback response is served if the 3rd-party is down?"]
49
+ Q2 -->|Asynchronous / Event-Driven| Q_Async["1. Does the external system provide webhooks?\n2. How are webhook signatures cryptographically verified?\n3. What is the retry backoff and dead-letter queue (DLQ) policy?"]
50
+
51
+ Q_Sync --> Q_Port["How is the external SDK isolated?\n(Enforce application-owned Port interface so domain never imports SDK)"]
52
+ Q_Async --> Q_Port
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Decision Tree 4: Read Performance, Caching & Search
58
+
59
+ ```mermaid
60
+ flowchart TD
61
+ Q1["What is the expected read volume and latency requirement?"]
62
+ Q1 -->|High Volume / Sub-50ms Latency| Q2["Is stale data acceptable for seconds/minutes?"]
63
+
64
+ Q2 -->|Yes| Q_Cache["1. What is the cache TTL and jitter window?\n2. What domain events trigger cache eviction?\n3. Is probabilistic early expiration (XFetch) needed?"]
65
+ Q2 -->|No: Strict Read-After-Write Consistency| Q_Consistent["1. Read from primary database instance for 2s after mutation\n2. Bypass read replicas during write session"]
66
+
67
+ Q_Cache --> Q_Page["Pagination Strategy: Enforce keyset/cursor pagination over OFFSET"]
68
+ Q_Consistent --> Q_Page
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Decision Tree 5: User Interface, Experience Duality & Interaction Flows
74
+
75
+ ```mermaid
76
+ flowchart TD
77
+ Q1["Does the feature introduce or modify a user interface?"]
78
+ Q1 -->|Yes| Q2["Who is the primary actor and operational persona?"]
79
+
80
+ Q2 -->|Operator / Admin| Q_Op["1. Information Density: Dense tabular grid with filters?\n2. Persistent App Shell: Left collapsible sidebar route?\n3. Actions: Inline row actions or full-page drawer?"]
81
+ Q2 -->|Consumer / Member| Q_Member["1. Experience Duality: Consumer portal (/portal)?\n2. Touch Ergonomics: Clean cards & mobile drawer?\n3. Simplified self-service actions?"]
82
+
83
+ Q_Op --> Q3["Navigation & State Synchronization"]
84
+ Q_Member --> Q3
85
+
86
+ Q3 --> Q_State["1. URL State: Deep-link query params (?tab=, ?q=, ?page=, ?modal=)?\n2. Server Cache: TanStack Query hook with automated invalidation?\n3. Accessibility: Accessible headless dialogs & ARIA live regions?"]
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Contextual Follow-Up Patterns
92
+
93
+ When conducting the interview, use this exact syntax pattern to chain questions adaptively:
94
+
95
+ 1. **Acknowledge and Pin Previous Answer**:
96
+ `"Understood, you specified [Option A] for [Requirement X]."`
97
+ 2. **Surface Immediate Architectural Implication**:
98
+ `"Because of [Option A], [Potential Failure / Edge Case Y] becomes the primary risk."`
99
+ 3. **Ask Context-Dependent Question**:
100
+ `"How should the system behave when [Condition Y] occurs? Specifically:"`
101
+ - *Sub-question 1*
102
+ - *Sub-question 2*
package/.editorconfig CHANGED
@@ -1,19 +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
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
@@ -1,78 +1,167 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
-
9
- jobs:
10
- test:
11
- name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
12
- runs-on: ${{ matrix.os }}
13
- strategy:
14
- fail-fast: false
15
- matrix:
16
- os: [ ubuntu-24.04, macos-latest, windows-latest ]
17
- node-version: [ 18.x, 20.x, 22.x, 24.x ]
18
-
19
- steps:
20
- - name: Checkout Repository
21
- uses: actions/checkout@v7
22
-
23
- - name: Setup Node.js ${{ matrix.node-version }}
24
- uses: actions/setup-node@v7
25
- with:
26
- node-version: ${{ matrix.node-version }}
27
-
28
- - name: Verify Environment
29
- run: |
30
- node --version
31
- npm --version
32
-
33
- - name: Run Syntax & Lint Checks
34
- run: npm run lint
35
-
36
- - name: Validate Agentic Architecture
37
- run: npm run validate
38
-
39
- - name: Run Test Suite
40
- run: npm test
41
-
42
- coverage:
43
- name: 100.00% Coverage Gate (Node 24)
44
- runs-on: ubuntu-24.04
45
- steps:
46
- - name: Checkout Repository
47
- uses: actions/checkout@v7
48
-
49
- - name: Setup Node.js 24.x
50
- uses: actions/setup-node@v7
51
- with:
52
- node-version: 24.x
53
-
54
- # Native 100% threshold flags require Node >=22.8.0 (see scripts/test_coverage.js),
55
- # so the coverage gate runs once on the newest runtime instead of every matrix cell.
56
- - name: Verify 100.00% Test Coverage Gates
57
- run: npm run test:coverage
58
-
59
- security:
60
- name: Secret & Vulnerability Scans
61
- runs-on: ubuntu-24.04
62
- steps:
63
- - name: Checkout Repository
64
- uses: actions/checkout@v7
65
-
66
- - name: Secret Scan (Gitleaks)
67
- uses: gitleaks/gitleaks-action@v2
68
- env:
69
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70
-
71
- - name: Filesystem Vulnerability Scan (Trivy)
72
- uses: aquasecurity/trivy-action@v0.36.0
73
- with:
74
- scan-type: fs
75
- scan-ref: .
76
- scanners: vuln
77
- severity: HIGH,CRITICAL
78
- exit-code: '1'
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+ merge_group:
9
+ branches: [ main ]
10
+
11
+ # Least privilege by default. Every job here only needs to read the repository.
12
+ # A write-capable token executing `node --test` over PR-controlled content is a
13
+ # supply-chain exposure; grant write scopes only where a job genuinely needs them.
14
+ permissions:
15
+ contents: read
16
+
17
+ # Cancel superseded runs. Without this, five pushes to a PR queue five full
18
+ # matrix runs; with a publish workflow it also prevents two release runs racing
19
+ # the same version.
20
+ concurrency:
21
+ group: ci-${{ github.workflow }}-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ test:
26
+ name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
27
+ runs-on: ${{ matrix.os }}
28
+ timeout-minutes: 15
29
+ strategy:
30
+ fail-fast: false
31
+ matrix:
32
+ os: [ ubuntu-24.04, macos-latest, windows-latest ]
33
+ # Node 18 (EOL 2025-04-30) and 20 (EOL 2026-04-30) are no longer
34
+ # patched. Half the matrix was verifying unpatched runtimes. Supported
35
+ # lines as of Oct 2026: 24 (Active LTS), 22 (Maintenance), 26 (Current).
36
+ node-version: [ 22.x, 24.x, 26.x ]
37
+
38
+ steps:
39
+ - name: Checkout Repository
40
+ uses: actions/checkout@v7
41
+
42
+ - name: Setup Node.js ${{ matrix.node-version }}
43
+ uses: actions/setup-node@v7
44
+ with:
45
+ node-version: ${{ matrix.node-version }}
46
+
47
+ # The repo has zero runtime dependencies, but contributor tooling
48
+ # (ESLint, ADR-012) is a devDependency and must be installed.
49
+ - name: Install dependencies
50
+ run: npm ci
51
+
52
+ - name: Verify Environment
53
+ run: |
54
+ node --version
55
+ npm --version
56
+
57
+ - name: Run Syntax & Lint Checks
58
+ run: npm run lint
59
+
60
+ - name: Validate Agentic Architecture
61
+ run: npm run validate
62
+
63
+ - name: Run Test Suite
64
+ run: npm test
65
+
66
+ coverage:
67
+ name: Coverage Gate (Node 24)
68
+ runs-on: ubuntu-24.04
69
+ timeout-minutes: 15
70
+ steps:
71
+ - name: Checkout Repository
72
+ uses: actions/checkout@v7
73
+
74
+ - name: Setup Node.js 24.x
75
+ uses: actions/setup-node@v7
76
+ with:
77
+ node-version: 24.x
78
+
79
+ - name: Install dependencies
80
+ run: npm ci
81
+
82
+ # Native threshold flags require Node >=22.8.0 (see scripts/test_coverage.js),
83
+ # so the coverage gate runs once on the newest runtime instead of every matrix cell.
84
+ - name: Verify Coverage Gates
85
+ run: npm run test:coverage
86
+
87
+ shell-syntax:
88
+ name: Shell Script Syntax (shipped hooks)
89
+ runs-on: ubuntu-24.04
90
+ timeout-minutes: 10
91
+ steps:
92
+ - name: Checkout Repository
93
+ uses: actions/checkout@v7
94
+
95
+ # The .sh files ship to every scaffolded project and auto-run as agent
96
+ # hooks. `bash -n` catches a CRLF checkout or a syntax slip that the
97
+ # Node-only lint is blind to.
98
+ - name: Parse every shipped shell script
99
+ run: |
100
+ set -euo pipefail
101
+ failed=0
102
+ while IFS= read -r script; do
103
+ if bash -n "$script"; then
104
+ echo "ok: $script"
105
+ else
106
+ echo "FAIL: $script"
107
+ failed=1
108
+ fi
109
+ done < <(find .agents -name '*.sh' -not -path './node_modules/*')
110
+ exit $failed
111
+
112
+ - name: Verify hooks use LF line endings
113
+ run: |
114
+ set -euo pipefail
115
+ bad=0
116
+ while IFS= read -r script; do
117
+ if grep -qU $'\r' "$script"; then
118
+ echo "CRLF found (breaks shebang + 'set -euo pipefail'): $script"
119
+ bad=1
120
+ fi
121
+ done < <(find .agents -name '*.sh' -not -path './node_modules/*')
122
+ [ "$bad" -eq 0 ] && echo "all hook scripts are LF"
123
+
124
+ security:
125
+ name: Secret & Vulnerability Scans
126
+ runs-on: ubuntu-24.04
127
+ timeout-minutes: 20
128
+ permissions:
129
+ contents: read
130
+ # gitleaks-action comments on PRs when it finds a leak; without these it
131
+ # degrades gracefully to scan-only.
132
+ pull-requests: write
133
+ steps:
134
+ - name: Checkout Repository (full history for secret scanning)
135
+ uses: actions/checkout@v7
136
+ with:
137
+ fetch-depth: 0
138
+
139
+ # gitleaks-action v2 runs on the Node 20 action runtime, which GitHub
140
+ # removed from hosted runners on 2026-09-16 -- the job was failing for
141
+ # every PR. v3 targets Node 24.
142
+ - name: Secret Scan (Gitleaks)
143
+ uses: gitleaks/gitleaks-action@v3
144
+ env:
145
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
146
+
147
+ - name: Filesystem Vulnerability Scan (Trivy)
148
+ uses: aquasecurity/trivy-action@v0.36.0
149
+ with:
150
+ scan-type: fs
151
+ scan-ref: .
152
+ scanners: vuln
153
+ severity: HIGH,CRITICAL
154
+ exit-code: '1'
155
+
156
+ - name: Software Bill of Materials (CycloneDX)
157
+ uses: anchore/sbom-action@v0
158
+ with:
159
+ format: cyclonedx-json
160
+ output-file: sbom.cdx.json
161
+ artifact-name: sbom.cdx.json
162
+
163
+ - name: Dependency Review
164
+ if: github.event_name == 'pull_request'
165
+ uses: actions/dependency-review-action@v4
166
+ with:
167
+ fail-on-severity: high