azcodr 2.1.0 → 2.2.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/.github/workflows/ci.yml +1 -0
- package/AGENTS.md +1 -1
- package/bin/azcodr.js +3 -1
- package/lib/errors.d.ts +15 -0
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +9 -0
- package/lib/errors.js.map +1 -1
- package/lib/git.d.ts +8 -0
- package/lib/git.d.ts.map +1 -1
- package/lib/git.js +8 -0
- package/lib/git.js.map +1 -1
- package/lib/guards.d.ts +16 -1
- package/lib/guards.d.ts.map +1 -1
- package/lib/guards.js +13 -1
- package/lib/guards.js.map +1 -1
- package/lib/index.d.ts +19 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -1
- package/lib/links.d.ts +14 -0
- package/lib/links.d.ts.map +1 -1
- package/lib/links.js +11 -0
- package/lib/links.js.map +1 -1
- package/lib/permissions.d.ts +4 -0
- package/lib/permissions.d.ts.map +1 -1
- package/lib/permissions.js +4 -0
- package/lib/permissions.js.map +1 -1
- package/lib/repo.d.ts +10 -0
- package/lib/repo.d.ts.map +1 -1
- package/lib/repo.js +7 -0
- package/lib/repo.js.map +1 -1
- package/lib/scaffold.d.ts +30 -1
- package/lib/scaffold.d.ts.map +1 -1
- package/lib/scaffold.js +23 -18
- package/lib/scaffold.js.map +1 -1
- package/memory.md +8 -0
- package/package.json +4 -5
- package/src/errors.ts +15 -0
- package/src/git.ts +8 -0
- package/src/guards.ts +16 -1
- package/src/index.ts +21 -0
- package/src/links.ts +14 -0
- package/src/permissions.ts +4 -0
- package/src/repo.ts +10 -0
- package/src/scaffold.ts +38 -29
- package/scripts/test_coverage.js +0 -66
package/.github/workflows/ci.yml
CHANGED
package/AGENTS.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **azcodr: Enterprise Architecture & Agentic Engineering Starter Template**
|
|
4
4
|
> **Workspace Mission:** Problem-first, topology-aligned production architectures governed by strict systemic atomicity, 100% open-source standards, true incremental TDD nano-cycles, and zero speculative bloat.
|
|
5
5
|
> **Runtime & Tools:** Node.js (`>=22.8.0`), npm (`>=10.0.0`) | `npm test` (test runner), `npm run test:coverage` (coverage gate), `npm run lint`, `npm run validate`.
|
|
6
|
-
> **Node floor rationale:** `>=22.8.0`
|
|
6
|
+
> **Node floor rationale:** `>=22.8.0` satisfies Jest native ESM requirements (`--experimental-vm-modules`) and modern LTS security baselines. Node 18 (EOL 2025-04-30) and 20 (EOL 2026-04-30) no longer receive security patches.
|
|
7
7
|
> **Rule Zero:** Assume nothing. Every action must be grounded in verified evidence from this workspace or direct instructions from the user.
|
|
8
8
|
> **Atomicity Mandate:** All rules, skills, code units, migrations, and transactions must be strictly atomic (indivisible, self-contained, composable with full ACID safety).
|
|
9
9
|
> **Architecture Mandate:** Architecture emerges strictly from problem constraints and execution targets (Problem-First; zero tool/platform bias). Match architectural style to problem topology (Hexagonal for backends, Platform Scripting for extensions, Data-Oriented Design for game engines, Command Pipeline for CLIs, Game Loop for canvas games).
|
package/bin/azcodr.js
CHANGED
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import process from 'node:process';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
10
11
|
import * as cli from '../lib/cli.js';
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
14
|
+
const isDirectRun = process.argv[1] ? fs.realpathSync(path.resolve(process.argv[1])).toLowerCase() === fs.realpathSync(selfPath).toLowerCase() : false;
|
|
13
15
|
|
|
14
16
|
if (isDirectRun) {
|
|
15
17
|
cli.main();
|
package/lib/errors.d.ts
CHANGED
|
@@ -14,14 +14,29 @@ export declare const ERROR_CODES: {
|
|
|
14
14
|
readonly E_GIT_BLOCKED: "Blocked git subcommand";
|
|
15
15
|
readonly E_PATH_ESCAPE: "Path escapes allowed root";
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Union of valid machine-readable error codes for scaffolding failures.
|
|
19
|
+
*/
|
|
17
20
|
export type ScaffoldErrorCode = keyof typeof ERROR_CODES;
|
|
21
|
+
/**
|
|
22
|
+
* Structural interface contract for errors thrown by the scaffolder.
|
|
23
|
+
*/
|
|
18
24
|
export interface ScaffoldErrorShape extends Error {
|
|
19
25
|
name: 'ScaffoldError';
|
|
20
26
|
code: ScaffoldErrorCode;
|
|
21
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
30
|
+
*/
|
|
22
31
|
export declare class ScaffoldError extends Error implements ScaffoldErrorShape {
|
|
23
32
|
readonly name: 'ScaffoldError';
|
|
24
33
|
readonly code: ScaffoldErrorCode;
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a new ScaffoldError instance.
|
|
36
|
+
*
|
|
37
|
+
* @param code - Machine-readable error code.
|
|
38
|
+
* @param message - Human-readable explanation of the error.
|
|
39
|
+
*/
|
|
25
40
|
constructor(code: ScaffoldErrorCode, message: string);
|
|
26
41
|
}
|
|
27
42
|
declare const _default: {
|
package/lib/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;;;;;;;CAOd,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,WAAW,CAAC;AAEzD,MAAM,WAAW,kBAAmB,SAAQ,KAAK;IAC/C,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,qBAAa,aAAc,SAAQ,KAAM,YAAW,kBAAkB;IACpE,SAAkB,IAAI,EAAE,eAAe,CAAmB;IAC1D,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;;;;;;;CAOd,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,WAAW,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,KAAK;IAC/C,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAM,YAAW,kBAAkB;IACpE,SAAkB,IAAI,EAAE,eAAe,CAAmB;IAC1D,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAEjC;;;;;OAKG;gBACS,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAIrD;;;;;;;;;;;;AAED,wBAA8C"}
|
package/lib/errors.js
CHANGED
|
@@ -14,9 +14,18 @@ export const ERROR_CODES = {
|
|
|
14
14
|
E_GIT_BLOCKED: 'Blocked git subcommand',
|
|
15
15
|
E_PATH_ESCAPE: 'Path escapes allowed root'
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
19
|
+
*/
|
|
17
20
|
export class ScaffoldError extends Error {
|
|
18
21
|
name = 'ScaffoldError';
|
|
19
22
|
code;
|
|
23
|
+
/**
|
|
24
|
+
* Constructs a new ScaffoldError instance.
|
|
25
|
+
*
|
|
26
|
+
* @param code - Machine-readable error code.
|
|
27
|
+
* @param message - Human-readable explanation of the error.
|
|
28
|
+
*/
|
|
20
29
|
constructor(code, message) {
|
|
21
30
|
super(message);
|
|
22
31
|
this.code = code;
|
package/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,oBAAoB,EAAE,2DAA2D;IACjF,kBAAkB,EAAE,+BAA+B;IACnD,qBAAqB,EAAE,wDAAwD;IAC/E,kBAAkB,EAAE,wCAAwC;IAC5D,aAAa,EAAE,wBAAwB;IACvC,aAAa,EAAE,2BAA2B;CAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,oBAAoB,EAAE,2DAA2D;IACjF,kBAAkB,EAAE,+BAA+B;IACnD,qBAAqB,EAAE,wDAAwD;IAC/E,kBAAkB,EAAE,wCAAwC;IAC5D,aAAa,EAAE,wBAAwB;IACvC,aAAa,EAAE,2BAA2B;CAClC,CAAC;AAeX;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACpB,IAAI,GAAoB,eAAe,CAAC;IACjD,IAAI,CAAoB;IAEjC;;;;;OAKG;IACH,YAAY,IAAuB,EAAE,OAAe;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC"}
|
package/lib/git.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ import cp from 'node:child_process';
|
|
|
6
6
|
* No network, no env exfiltration; cwd is constrained to targetDir callers.
|
|
7
7
|
*/
|
|
8
8
|
export declare const GIT_ALLOWED_SUBCOMMANDS: Set<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Safely executes an allowlisted git subcommand using execFileSync with an argument array and shell disabled.
|
|
11
|
+
*
|
|
12
|
+
* @param args - Subcommand and arguments array to pass to git.
|
|
13
|
+
* @param options - Child process execution options.
|
|
14
|
+
* @returns Standard output from git as a string.
|
|
15
|
+
* @throws {ScaffoldError} When args is empty or the subcommand is not in GIT_ALLOWED_SUBCOMMANDS.
|
|
16
|
+
*/
|
|
9
17
|
export declare function runGit(args: string[], options?: cp.ExecFileSyncOptions): string;
|
|
10
18
|
declare const _default: {
|
|
11
19
|
GIT_ALLOWED_SUBCOMMANDS: Set<string>;
|
package/lib/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGpC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,aAMlC,CAAC;AAEH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,EAAE,CAAC,mBAAwB,GAAG,MAAM,CAcnF;;;;;AAED,wBAAmD"}
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGpC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,aAMlC,CAAC;AAEH;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,EAAE,CAAC,mBAAwB,GAAG,MAAM,CAcnF;;;;;AAED,wBAAmD"}
|
package/lib/git.js
CHANGED
|
@@ -13,6 +13,14 @@ export const GIT_ALLOWED_SUBCOMMANDS = new Set([
|
|
|
13
13
|
'add',
|
|
14
14
|
'commit'
|
|
15
15
|
]);
|
|
16
|
+
/**
|
|
17
|
+
* Safely executes an allowlisted git subcommand using execFileSync with an argument array and shell disabled.
|
|
18
|
+
*
|
|
19
|
+
* @param args - Subcommand and arguments array to pass to git.
|
|
20
|
+
* @param options - Child process execution options.
|
|
21
|
+
* @returns Standard output from git as a string.
|
|
22
|
+
* @throws {ScaffoldError} When args is empty or the subcommand is not in GIT_ALLOWED_SUBCOMMANDS.
|
|
23
|
+
*/
|
|
16
24
|
export function runGit(args, options = {}) {
|
|
17
25
|
if (!Array.isArray(args) || args.length === 0) {
|
|
18
26
|
throw new ScaffoldError('E_GIT_ARGS_INVALID', ERROR_CODES.E_GIT_ARGS_INVALID);
|
package/lib/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IAC7C,WAAW;IACX,MAAM;IACN,QAAQ;IACR,KAAK;IACL,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,UAAkC,EAAE;IACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,aAAa,CAAC,oBAAoB,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,UAAU,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,aAAa,CAAC,eAAe,EAAE,GAAG,WAAW,CAAC,aAAa,KAAK,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;QAClC,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,KAAK;QACZ,GAAG,OAAO;KACX,CAAW,CAAC;AACf,CAAC;AAED,eAAe,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IAC7C,WAAW;IACX,MAAM;IACN,QAAQ;IACR,KAAK;IACL,QAAQ;CACT,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,UAAkC,EAAE;IACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,aAAa,CAAC,oBAAoB,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,UAAU,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,aAAa,CAAC,eAAe,EAAE,GAAG,WAAW,CAAC,aAAa,KAAK,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;QAClC,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,KAAK;QACZ,GAAG,OAAO;KACX,CAAW,CAAC;AACf,CAAC;AAED,eAAe,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC"}
|
package/lib/guards.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for configuring protected target verification.
|
|
3
|
+
*/
|
|
1
4
|
export interface ProtectedTargetOptions {
|
|
2
5
|
templateDir?: string;
|
|
3
6
|
force?: boolean;
|
|
@@ -6,13 +9,21 @@ export interface ProtectedTargetOptions {
|
|
|
6
9
|
}
|
|
7
10
|
/**
|
|
8
11
|
* Filesystem scope guard (Supply Chain: filesystem access).
|
|
9
|
-
* Constrains all reads/writes to targetDir / templateDir.
|
|
12
|
+
* Constrains all reads/writes to targetDir / templateDir, throwing if candidate escapes root.
|
|
13
|
+
*
|
|
14
|
+
* @param root - Absolute base directory.
|
|
15
|
+
* @param candidate - Candidate file or directory path to check.
|
|
16
|
+
* @param message - Optional custom error message.
|
|
17
|
+
* @throws {ScaffoldError} When candidate path escapes root directory.
|
|
10
18
|
*/
|
|
11
19
|
export declare function assertInside(root: string, candidate: string, message?: string): void;
|
|
12
20
|
/**
|
|
13
21
|
* Normalizes a path for protected-target comparison. On Windows the filesystem
|
|
14
22
|
* is case-insensitive, so `C:\Users\Name` and `c:\users\name` are the same
|
|
15
23
|
* directory and must compare equal.
|
|
24
|
+
*
|
|
25
|
+
* @param p - File or directory path to normalize.
|
|
26
|
+
* @returns Normalized path string.
|
|
16
27
|
*/
|
|
17
28
|
export declare function normalizeForComparison(p: string): string;
|
|
18
29
|
/**
|
|
@@ -24,6 +35,10 @@ export declare function normalizeForComparison(p: string): string;
|
|
|
24
35
|
*
|
|
25
36
|
* Lexical comparison is not enough: a symlink pointing at home must also be
|
|
26
37
|
* caught, so an existing target is resolved with realpath before comparing.
|
|
38
|
+
*
|
|
39
|
+
* @param targetDir - The target directory path to evaluate.
|
|
40
|
+
* @param options - Optional configuration for protected target evaluation.
|
|
41
|
+
* @returns True if target is a protected location, false otherwise.
|
|
27
42
|
*/
|
|
28
43
|
export declare function isProtectedTarget(targetDir: string, options?: ProtectedTargetOptions): boolean;
|
|
29
44
|
declare const _default: {
|
package/lib/guards.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAOpF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGxD;AAwCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CASlG;;;;;;AAED,wBAIE"}
|
package/lib/guards.js
CHANGED
|
@@ -6,7 +6,12 @@ import { ScaffoldError, ERROR_CODES } from './errors.js';
|
|
|
6
6
|
import { getTemplateDir } from './scaffold.js';
|
|
7
7
|
/**
|
|
8
8
|
* Filesystem scope guard (Supply Chain: filesystem access).
|
|
9
|
-
* Constrains all reads/writes to targetDir / templateDir.
|
|
9
|
+
* Constrains all reads/writes to targetDir / templateDir, throwing if candidate escapes root.
|
|
10
|
+
*
|
|
11
|
+
* @param root - Absolute base directory.
|
|
12
|
+
* @param candidate - Candidate file or directory path to check.
|
|
13
|
+
* @param message - Optional custom error message.
|
|
14
|
+
* @throws {ScaffoldError} When candidate path escapes root directory.
|
|
10
15
|
*/
|
|
11
16
|
export function assertInside(root, candidate, message) {
|
|
12
17
|
const resolvedRoot = path.resolve(root);
|
|
@@ -20,6 +25,9 @@ export function assertInside(root, candidate, message) {
|
|
|
20
25
|
* Normalizes a path for protected-target comparison. On Windows the filesystem
|
|
21
26
|
* is case-insensitive, so `C:\Users\Name` and `c:\users\name` are the same
|
|
22
27
|
* directory and must compare equal.
|
|
28
|
+
*
|
|
29
|
+
* @param p - File or directory path to normalize.
|
|
30
|
+
* @returns Normalized path string.
|
|
23
31
|
*/
|
|
24
32
|
export function normalizeForComparison(p) {
|
|
25
33
|
const resolved = path.resolve(p);
|
|
@@ -73,6 +81,10 @@ function resolvesToProtectedLocation(resolvedTarget, home) {
|
|
|
73
81
|
*
|
|
74
82
|
* Lexical comparison is not enough: a symlink pointing at home must also be
|
|
75
83
|
* caught, so an existing target is resolved with realpath before comparing.
|
|
84
|
+
*
|
|
85
|
+
* @param targetDir - The target directory path to evaluate.
|
|
86
|
+
* @param options - Optional configuration for protected target evaluation.
|
|
87
|
+
* @returns True if target is a protected location, false otherwise.
|
|
76
88
|
*/
|
|
77
89
|
export function isProtectedTarget(targetDir, options = {}) {
|
|
78
90
|
const resolvedTarget = path.resolve(targetDir);
|
package/lib/guards.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @azcodr/azcodr
|
|
3
|
+
* Enterprise Architecture & Agentic Engineering Starter Template.
|
|
4
|
+
*
|
|
5
|
+
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
|
+
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Union type of all valid machine-readable error codes.
|
|
10
|
+
*/
|
|
1
11
|
export type ScaffoldErrorCode = 'E_TARGET_IS_TEMPLATE' | 'E_TARGET_NOT_EMPTY' | 'E_TARGET_IS_PROTECTED' | 'E_GIT_ARGS_INVALID' | 'E_GIT_BLOCKED' | 'E_PATH_ESCAPE';
|
|
12
|
+
/**
|
|
13
|
+
* Core scaffolding functions, guards, utilities, error classes, and constants.
|
|
14
|
+
*/
|
|
2
15
|
export { scaffold, validateTarget, copyTemplate, ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, initGit, isInsideGitWorkTree, runGit, assertInside, isProtectedTarget, getTemplateDir, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES } from './scaffold.js';
|
|
16
|
+
/**
|
|
17
|
+
* Type definitions and option interfaces for scaffolding operations.
|
|
18
|
+
*/
|
|
3
19
|
export type { ScaffoldOptions, ScaffoldResult, ValidateTargetOptions, CopyTemplateOptions, EnsureSymlinkOptions, InitGitOptions, ScaffoldErrorShape } from './scaffold.js';
|
|
4
20
|
import scaffoldModule from './scaffold.js';
|
|
21
|
+
/**
|
|
22
|
+
* Default export providing the unified azcodr scaffolding module.
|
|
23
|
+
*/
|
|
5
24
|
export default scaffoldModule;
|
|
6
25
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,oBAAoB,GACpB,eAAe,GACf,eAAe,CAAC;AAEpB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,OAAO,EACP,mBAAmB,EACnB,MAAM,EACN,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,EACb,WAAW,EACZ,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,cAAc,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,oBAAoB,GACpB,eAAe,GACf,eAAe,CAAC;AAEpB;;GAEG;AACH,OAAO,EACL,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,OAAO,EACP,mBAAmB,EACnB,MAAM,EACN,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,EACb,WAAW,EACZ,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,YAAY,EACV,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,cAAc,MAAM,eAAe,CAAC;AAE3C;;GAEG;AACH,eAAe,cAAc,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @azcodr/azcodr
|
|
3
|
+
* Enterprise Architecture & Agentic Engineering Starter Template.
|
|
4
|
+
*
|
|
5
|
+
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
|
+
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Core scaffolding functions, guards, utilities, error classes, and constants.
|
|
10
|
+
*/
|
|
1
11
|
export { scaffold, validateTarget, copyTemplate, ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, initGit, isInsideGitWorkTree, runGit, assertInside, isProtectedTarget, getTemplateDir, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES } from './scaffold.js';
|
|
2
12
|
import scaffoldModule from './scaffold.js';
|
|
13
|
+
/**
|
|
14
|
+
* Default export providing the unified azcodr scaffolding module.
|
|
15
|
+
*/
|
|
3
16
|
export default scaffoldModule;
|
|
4
17
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH;;GAEG;AACH,OAAO,EACL,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,OAAO,EACP,mBAAmB,EACnB,MAAM,EACN,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,EACb,WAAW,EACZ,MAAM,eAAe,CAAC;AAevB,OAAO,cAAc,MAAM,eAAe,CAAC;AAE3C;;GAEG;AACH,eAAe,cAAc,CAAC"}
|
package/lib/links.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for symlink and pointer creation.
|
|
3
|
+
*/
|
|
1
4
|
export interface EnsureSymlinkOptions {
|
|
2
5
|
targetDir: string;
|
|
3
6
|
linkName: string;
|
|
@@ -7,16 +10,27 @@ export interface EnsureSymlinkOptions {
|
|
|
7
10
|
/**
|
|
8
11
|
* Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
|
|
9
12
|
* Uses exact directory listing (not existsSync, which lies on case-insensitive systems).
|
|
13
|
+
*
|
|
14
|
+
* @param targetDir - Directory containing the file entries.
|
|
15
|
+
* @param linkName - Name of the proposed symlink or alias entry.
|
|
16
|
+
* @param targetFileName - Target file name to match against.
|
|
17
|
+
* @returns True if both names resolve to the same disk file on a case-insensitive filesystem.
|
|
10
18
|
*/
|
|
11
19
|
export declare function isSameCaseInsensitiveFile(targetDir: string, linkName: string, targetFileName: string): boolean;
|
|
12
20
|
/**
|
|
13
21
|
* Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
|
|
22
|
+
*
|
|
23
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
24
|
+
* @returns True if the symlink or copy fallback was successfully established.
|
|
14
25
|
*/
|
|
15
26
|
export declare function ensureSymlink(options: EnsureSymlinkOptions): boolean;
|
|
16
27
|
/**
|
|
17
28
|
* Creates a symlink, falling back to a text pointer (not a full copy).
|
|
18
29
|
* Used for .github/copilot-instructions.md where a full AGENTS.md copy would
|
|
19
30
|
* break relative markdown links (they resolve from .github/, not root).
|
|
31
|
+
*
|
|
32
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
33
|
+
* @returns True if the symlink or pointer fallback was successfully established.
|
|
20
34
|
*/
|
|
21
35
|
export declare function ensureSymlinkOrPointer(options: EnsureSymlinkOptions): boolean;
|
|
22
36
|
declare const _default: {
|
package/lib/links.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA6DD
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA6DD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAWT;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAapE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAmB7E;;;;;;AAED,wBAIE"}
|
package/lib/links.js
CHANGED
|
@@ -56,6 +56,11 @@ function copyFallback(targetDir, linkName, targetFileName) {
|
|
|
56
56
|
/**
|
|
57
57
|
* Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
|
|
58
58
|
* Uses exact directory listing (not existsSync, which lies on case-insensitive systems).
|
|
59
|
+
*
|
|
60
|
+
* @param targetDir - Directory containing the file entries.
|
|
61
|
+
* @param linkName - Name of the proposed symlink or alias entry.
|
|
62
|
+
* @param targetFileName - Target file name to match against.
|
|
63
|
+
* @returns True if both names resolve to the same disk file on a case-insensitive filesystem.
|
|
59
64
|
*/
|
|
60
65
|
export function isSameCaseInsensitiveFile(targetDir, linkName, targetFileName) {
|
|
61
66
|
if (linkName === targetFileName)
|
|
@@ -74,6 +79,9 @@ export function isSameCaseInsensitiveFile(targetDir, linkName, targetFileName) {
|
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
81
|
* Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
|
|
82
|
+
*
|
|
83
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
84
|
+
* @returns True if the symlink or copy fallback was successfully established.
|
|
77
85
|
*/
|
|
78
86
|
export function ensureSymlink(options) {
|
|
79
87
|
const { targetDir, linkName, targetFileName, dryRun = false } = options;
|
|
@@ -96,6 +104,9 @@ export function ensureSymlink(options) {
|
|
|
96
104
|
* Creates a symlink, falling back to a text pointer (not a full copy).
|
|
97
105
|
* Used for .github/copilot-instructions.md where a full AGENTS.md copy would
|
|
98
106
|
* break relative markdown links (they resolve from .github/, not root).
|
|
107
|
+
*
|
|
108
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
109
|
+
* @returns True if the symlink or pointer fallback was successfully established.
|
|
99
110
|
*/
|
|
100
111
|
export function ensureSymlinkOrPointer(options) {
|
|
101
112
|
const { targetDir, linkName, targetFileName, dryRun = false } = options;
|
package/lib/links.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"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"}
|
package/lib/permissions.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ensures all bash scripts in agent and skill directories have executable permissions (0o755).
|
|
3
|
+
*
|
|
4
|
+
* @param targetDir - Root directory containing .agents and skills.
|
|
5
|
+
* @param dryRun - When true, simulates permission changes without modifying disk.
|
|
6
|
+
* @returns Array of file paths that were modified or would be modified.
|
|
3
7
|
*/
|
|
4
8
|
export declare function makeScriptsExecutable(targetDir: string, dryRun?: boolean): string[];
|
|
5
9
|
declare const _default: {
|
package/lib/permissions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAyBA
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAyBA;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,EAAE,CAWjF;;;;AAED,wBAAyC"}
|
package/lib/permissions.js
CHANGED
|
@@ -26,6 +26,10 @@ function chmodShFilesIn(scriptsDir, dryRun) {
|
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Ensures all bash scripts in agent and skill directories have executable permissions (0o755).
|
|
29
|
+
*
|
|
30
|
+
* @param targetDir - Root directory containing .agents and skills.
|
|
31
|
+
* @param dryRun - When true, simulates permission changes without modifying disk.
|
|
32
|
+
* @returns Array of file paths that were modified or would be modified.
|
|
29
33
|
*/
|
|
30
34
|
export function makeScriptsExecutable(targetDir, dryRun = false) {
|
|
31
35
|
const agentScriptsDir = path.join(targetDir, '.agents', 'scripts');
|
package/lib/permissions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,WAAW,CAAC,QAAgB,EAAE,MAAe;IACpD,IAAI,MAAM;QAAE,OAAO;IACnB,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;IAClE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,UAAkB,EAAE,MAAe;IACzD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;QAAE,OAAO,QAAQ,CAAC;IAC1F,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,WAAW,CAAC,QAAgB,EAAE,MAAe;IACpD,IAAI,MAAM;QAAE,OAAO;IACnB,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;IAClE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,UAAkB,EAAE,MAAe;IACzD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;QAAE,OAAO,QAAQ,CAAC;IAC1F,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB,EAAE,MAAM,GAAG,KAAK;IACrE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/C,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAC1D,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,eAAe,EAAE,qBAAqB,EAAE,CAAC"}
|
package/lib/repo.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options controlling git repository initialization.
|
|
3
|
+
*/
|
|
1
4
|
export interface InitGitOptions {
|
|
2
5
|
noGit?: boolean;
|
|
3
6
|
dryRun?: boolean;
|
|
@@ -5,11 +8,18 @@ export interface InitGitOptions {
|
|
|
5
8
|
/**
|
|
6
9
|
* Detects whether targetDir is already inside an existing Git worktree.
|
|
7
10
|
* Socket note: shell access is limited to `git rev-parse` via runGit (no shell).
|
|
11
|
+
*
|
|
12
|
+
* @param targetDir - Directory path to inspect.
|
|
13
|
+
* @returns True if target directory is within a git worktree, false otherwise.
|
|
8
14
|
*/
|
|
9
15
|
export declare function isInsideGitWorkTree(targetDir: string): boolean;
|
|
10
16
|
/**
|
|
11
17
|
* Initializes a git repository in the target directory if not already inside one.
|
|
12
18
|
* Socket note: only allowlisted `git init/branch/add/commit` via execFileSync, cwd scoped.
|
|
19
|
+
*
|
|
20
|
+
* @param targetDir - Directory where git repository should be initialized.
|
|
21
|
+
* @param options - Configuration options for git initialization.
|
|
22
|
+
* @returns True if repository was initialized and committed, false otherwise.
|
|
13
23
|
*/
|
|
14
24
|
export declare function initGit(targetDir: string, options?: InitGitOptions): boolean;
|
|
15
25
|
declare const _default: {
|
package/lib/repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAW9D;AA8CD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAchF;;;;;AAED,wBAAgD"}
|
package/lib/repo.js
CHANGED
|
@@ -6,6 +6,9 @@ const INITIAL_COMMIT_MESSAGE = 'chore: initial scaffold from azcodr template';
|
|
|
6
6
|
/**
|
|
7
7
|
* Detects whether targetDir is already inside an existing Git worktree.
|
|
8
8
|
* Socket note: shell access is limited to `git rev-parse` via runGit (no shell).
|
|
9
|
+
*
|
|
10
|
+
* @param targetDir - Directory path to inspect.
|
|
11
|
+
* @returns True if target directory is within a git worktree, false otherwise.
|
|
9
12
|
*/
|
|
10
13
|
export function isInsideGitWorkTree(targetDir) {
|
|
11
14
|
try {
|
|
@@ -67,6 +70,10 @@ function initialCommit(targetDir) {
|
|
|
67
70
|
/**
|
|
68
71
|
* Initializes a git repository in the target directory if not already inside one.
|
|
69
72
|
* Socket note: only allowlisted `git init/branch/add/commit` via execFileSync, cwd scoped.
|
|
73
|
+
*
|
|
74
|
+
* @param targetDir - Directory where git repository should be initialized.
|
|
75
|
+
* @param options - Configuration options for git initialization.
|
|
76
|
+
* @returns True if repository was initialized and committed, false otherwise.
|
|
70
77
|
*/
|
|
71
78
|
export function initGit(targetDir, options = {}) {
|
|
72
79
|
const { noGit = false, dryRun = false } = options;
|
package/lib/repo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,sBAAsB,GAAG,8CAA8C,CAAC;
|
|
1
|
+
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"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"}
|
package/lib/scaffold.d.ts
CHANGED
|
@@ -7,7 +7,13 @@ import type { EnsureSymlinkOptions } from './links.js';
|
|
|
7
7
|
import { makeScriptsExecutable } from './permissions.js';
|
|
8
8
|
import { isInsideGitWorkTree, initGit } from './repo.js';
|
|
9
9
|
import type { InitGitOptions } from './repo.js';
|
|
10
|
+
/**
|
|
11
|
+
* Canonical list of template files and directories copied into a new workspace.
|
|
12
|
+
*/
|
|
10
13
|
export declare const TEMPLATE_ITEMS: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* Configuration options for the primary scaffold orchestration function.
|
|
16
|
+
*/
|
|
11
17
|
export interface ScaffoldOptions {
|
|
12
18
|
targetDir?: string;
|
|
13
19
|
force?: boolean;
|
|
@@ -16,6 +22,9 @@ export interface ScaffoldOptions {
|
|
|
16
22
|
dryRun?: boolean;
|
|
17
23
|
silent?: boolean;
|
|
18
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Result object returned upon completion of a scaffold operation.
|
|
27
|
+
*/
|
|
19
28
|
export interface ScaffoldResult {
|
|
20
29
|
success: boolean;
|
|
21
30
|
targetDir: string;
|
|
@@ -23,30 +32,50 @@ export interface ScaffoldResult {
|
|
|
23
32
|
dryRun: boolean;
|
|
24
33
|
actions: string[];
|
|
25
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Options controlling pre-scaffold target directory validation.
|
|
37
|
+
*/
|
|
26
38
|
export interface ValidateTargetOptions {
|
|
27
39
|
templateDir?: string;
|
|
28
40
|
force?: boolean;
|
|
29
41
|
dryRun?: boolean;
|
|
30
42
|
allowProtected?: boolean;
|
|
31
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Options controlling template file copying and file generation.
|
|
46
|
+
*/
|
|
32
47
|
export interface CopyTemplateOptions {
|
|
33
48
|
dryRun?: boolean;
|
|
34
49
|
}
|
|
35
50
|
/**
|
|
36
|
-
*
|
|
51
|
+
* Resolves the root filesystem directory of the azcodr template files.
|
|
52
|
+
*
|
|
53
|
+
* @returns Absolute filesystem path to the template root directory.
|
|
37
54
|
*/
|
|
38
55
|
export declare function getTemplateDir(): string;
|
|
39
56
|
/**
|
|
40
57
|
* Validates the target directory to ensure it is suitable for scaffolding.
|
|
58
|
+
*
|
|
59
|
+
* @param targetDir - Target directory path to validate.
|
|
60
|
+
* @param options - Validation options including force, dry-run, and protected overrides.
|
|
61
|
+
* @throws {ScaffoldError} When target is invalid, protected, or non-empty without force.
|
|
41
62
|
*/
|
|
42
63
|
export declare function validateTarget(targetDir: string, options?: ValidateTargetOptions): void;
|
|
43
64
|
/**
|
|
44
65
|
* Recursively copies template files into the target directory and sets up symlinks and permissions.
|
|
45
66
|
* Socket note: filesystem access is scoped to templateDir -> targetDir only (assertInside).
|
|
67
|
+
*
|
|
68
|
+
* @param targetDir - Destination directory path.
|
|
69
|
+
* @param templateDir - Source template directory path.
|
|
70
|
+
* @param options - Copy options including dry-run flag.
|
|
71
|
+
* @returns Array of recorded scaffolding action descriptions.
|
|
46
72
|
*/
|
|
47
73
|
export declare function copyTemplate(targetDir: string, templateDir?: string, options?: CopyTemplateOptions): string[];
|
|
48
74
|
/**
|
|
49
75
|
* High-level orchestration function to scaffold the azcodr workspace into targetDir.
|
|
76
|
+
*
|
|
77
|
+
* @param options - Scaffolding options.
|
|
78
|
+
* @returns Result object containing success flag, target directory, and action log.
|
|
50
79
|
*/
|
|
51
80
|
export declare function scaffold(options?: ScaffoldOptions): ScaffoldResult;
|
|
52
81
|
export { ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, isInsideGitWorkTree, initGit, runGit, assertInside, ScaffoldError, ERROR_CODES, isProtectedTarget };
|
package/lib/scaffold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAW3C,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAW3C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAkCD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,IAAI,CAW3F;AAwFD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,WAAW,GAAE,MAAyB,EACtC,OAAO,GAAE,mBAAwB,GAChC,MAAM,EAAE,CAcV;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,CActE;AAED,OAAO,EACL,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAChE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAC3D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAC5D,CAAC;AAEF,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AAE5F,wBAKE"}
|
package/lib/scaffold.js
CHANGED
|
@@ -8,6 +8,9 @@ import { assertInside, isProtectedTarget } from './guards.js';
|
|
|
8
8
|
import { ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile } from './links.js';
|
|
9
9
|
import { makeScriptsExecutable } from './permissions.js';
|
|
10
10
|
import { isInsideGitWorkTree, initGit } from './repo.js';
|
|
11
|
+
/**
|
|
12
|
+
* Canonical list of template files and directories copied into a new workspace.
|
|
13
|
+
*/
|
|
11
14
|
export const TEMPLATE_ITEMS = [
|
|
12
15
|
'AGENTS.md',
|
|
13
16
|
'memory.md',
|
|
@@ -21,7 +24,9 @@ export const TEMPLATE_ITEMS = [
|
|
|
21
24
|
'LICENSE'
|
|
22
25
|
];
|
|
23
26
|
/**
|
|
24
|
-
*
|
|
27
|
+
* Resolves the root filesystem directory of the azcodr template files.
|
|
28
|
+
*
|
|
29
|
+
* @returns Absolute filesystem path to the template root directory.
|
|
25
30
|
*/
|
|
26
31
|
export function getTemplateDir() {
|
|
27
32
|
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -48,6 +53,10 @@ function rejectNonEmptyTarget(resolvedTarget, force) {
|
|
|
48
53
|
}
|
|
49
54
|
/**
|
|
50
55
|
* Validates the target directory to ensure it is suitable for scaffolding.
|
|
56
|
+
*
|
|
57
|
+
* @param targetDir - Target directory path to validate.
|
|
58
|
+
* @param options - Validation options including force, dry-run, and protected overrides.
|
|
59
|
+
* @throws {ScaffoldError} When target is invalid, protected, or non-empty without force.
|
|
51
60
|
*/
|
|
52
61
|
export function validateTarget(targetDir, options = {}) {
|
|
53
62
|
const { templateDir = getTemplateDir(), force = false, dryRun = false, allowProtected = false } = options;
|
|
@@ -123,7 +132,7 @@ function starterPackageJson(resolvedTarget) {
|
|
|
123
132
|
description: 'Scaffolded with azcodr enterprise architecture template',
|
|
124
133
|
scripts: {
|
|
125
134
|
test: 'node --test',
|
|
126
|
-
'test:coverage': '
|
|
135
|
+
'test:coverage': 'jest --coverage',
|
|
127
136
|
lint: 'echo "No linter configured yet. Run /lets-build to configure toolchain."',
|
|
128
137
|
validate: 'node scripts/validate-cli.js'
|
|
129
138
|
}
|
|
@@ -150,6 +159,11 @@ function chmodTemplateScripts(inspectDir, dryRun) {
|
|
|
150
159
|
/**
|
|
151
160
|
* Recursively copies template files into the target directory and sets up symlinks and permissions.
|
|
152
161
|
* Socket note: filesystem access is scoped to templateDir -> targetDir only (assertInside).
|
|
162
|
+
*
|
|
163
|
+
* @param targetDir - Destination directory path.
|
|
164
|
+
* @param templateDir - Source template directory path.
|
|
165
|
+
* @param options - Copy options including dry-run flag.
|
|
166
|
+
* @returns Array of recorded scaffolding action descriptions.
|
|
153
167
|
*/
|
|
154
168
|
export function copyTemplate(targetDir, templateDir = getTemplateDir(), options = {}) {
|
|
155
169
|
const { dryRun = false } = options;
|
|
@@ -168,6 +182,9 @@ export function copyTemplate(targetDir, templateDir = getTemplateDir(), options
|
|
|
168
182
|
}
|
|
169
183
|
/**
|
|
170
184
|
* High-level orchestration function to scaffold the azcodr workspace into targetDir.
|
|
185
|
+
*
|
|
186
|
+
* @param options - Scaffolding options.
|
|
187
|
+
* @returns Result object containing success flag, target directory, and action log.
|
|
171
188
|
*/
|
|
172
189
|
export function scaffold(options = {}) {
|
|
173
190
|
const { targetDir = process.cwd(), force = false, noGit = false, templateDir = getTemplateDir(), dryRun = false } = options;
|
|
@@ -181,21 +198,9 @@ export function scaffold(options = {}) {
|
|
|
181
198
|
}
|
|
182
199
|
export { ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, isInsideGitWorkTree, initGit, runGit, assertInside, ScaffoldError, ERROR_CODES, isProtectedTarget };
|
|
183
200
|
export default {
|
|
184
|
-
scaffold,
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
ensureSymlinkOrPointer,
|
|
189
|
-
isSameCaseInsensitiveFile,
|
|
190
|
-
makeScriptsExecutable,
|
|
191
|
-
isInsideGitWorkTree,
|
|
192
|
-
initGit,
|
|
193
|
-
getTemplateDir,
|
|
194
|
-
runGit,
|
|
195
|
-
assertInside,
|
|
196
|
-
TEMPLATE_ITEMS,
|
|
197
|
-
ScaffoldError,
|
|
198
|
-
ERROR_CODES,
|
|
199
|
-
isProtectedTarget
|
|
201
|
+
scaffold, validateTarget, copyTemplate, ensureSymlink,
|
|
202
|
+
ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable,
|
|
203
|
+
isInsideGitWorkTree, initGit, getTemplateDir, runGit,
|
|
204
|
+
assertInside, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES, isProtectedTarget
|
|
200
205
|
};
|
|
201
206
|
//# sourceMappingURL=scaffold.js.map
|
package/lib/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzD,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,WAAW;IACX,WAAW;IACX,WAAW;IACX,MAAM;IACN,SAAS;IACT,SAAS;IACT,SAAS;IACT,YAAY;IACZ,eAAe;IACf,SAAS;CACV,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
package/memory.md
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
| [ADR-012](./memory.md#adr-012-enforce-the-file-and-function-gates-the-repo-prescribes) | Enforce the file and function gates the repo prescribes | 2026-10-07 | ACCEPTED | [`clean_code.md`](./docs/rules/clean_code.md) |
|
|
32
32
|
| [ADR-013](./memory.md#adr-013-native-esm-port-and-jsr-package-publishing) | Native ESM port and JSR package publishing | 2026-10-07 | ACCEPTED | [`devops_ci_cd.md`](./docs/rules/devops_ci_cd.md) |
|
|
33
33
|
| [ADR-014](./memory.md#adr-014-author-in-typescript-with-tsc-compilation-to-native-esm) | Author in TypeScript with tsc compilation to native ESM | 2026-10-07 | ACCEPTED | [`type_safety.md`](./docs/rules/type_safety.md) |
|
|
34
|
+
| [ADR-015](./memory.md#adr-015-consolidate-testing-on-jest-with-typescript-test-migration) | Consolidate testing on Jest with TypeScript test migration | 2026-10-08 | ACCEPTED | [`test_driven_development.md`](./docs/rules/test_driven_development.md) |
|
|
34
35
|
|
|
35
36
|
---
|
|
36
37
|
|
|
@@ -71,6 +72,13 @@
|
|
|
71
72
|
- **Consequences:** ✅ 100% strict type coverage across all 11 modules (`src/*.ts`). ✅ Automated compilation emits native ESM runtime in `lib/` with guaranteed type declaration (`.d.ts`) parity. ✅ Zero runtime dependencies invariant preserved. ✅ 100.00% line & function coverage maintained with 416 passing tests. ✅ JSR publish dry-run passes with zero errors and zero slow types.
|
|
72
73
|
- **Enforced In:** `tsconfig.json`, `jsr.json`, `package.json`, `jest.config.js`, `src/`, `lib/`, `tests/`
|
|
73
74
|
|
|
75
|
+
#### ADR-015: Consolidate Testing on Jest with TypeScript Test Migration
|
|
76
|
+
- **Date:** 2026-10-08 | **Status:** ACCEPTED
|
|
77
|
+
- **Context:** Following the TypeScript migration (ADR-014), the repository ran a fragmented dual test runner architecture: native `node:test` via `scripts/test_coverage.js` evaluating compiled JavaScript artifacts in `lib/`, and Jest for developer workflows and specs. Testing compiled output disconnected tests from authored TypeScript source definitions, required manual synchronization between compilation and testing, and prevented strict compile-time type verification of test suites (`tsc --noEmit` did not typecheck `tests/`). Furthermore, `scripts/test_coverage.js` imposed brittle Node version gating (`>=22.8.0`) for experimental V8 flags.
|
|
78
|
+
- **Decision:** (1) Consolidate 100% of testing and coverage on Jest (`jest: 29.7.0`, `ts-jest: 29.2.6`). Retire and delete `scripts/test_coverage.js` and `npm run test:jest`. Update `package.json` so `test` and `test:coverage` invoke Jest with `--experimental-vm-modules`. (2) Migrate all 35 test suites from JavaScript (`.test.js` / `.spec.ts`) to TypeScript (`tests/**/*.test.ts`) with strict typing, Jest lifecycle globals, and typed mocks. (3) Configure `tsconfig.json` with `"noEmit": true`, `"allowJs": true`, and include `["src/**/*", "tests/**/*"]` for comprehensive `npm run typecheck` coverage across both source and tests. Create `tsconfig.build.json` with `rootDir: src` and `outDir: lib` to strictly isolate production compilation from test suites. (4) Configure `jest.config.js` to collect coverage directly from authored TypeScript source and validator scripts (`['src/**/*.ts', 'scripts/validate/**/*.js', 'scripts/validate.js']`), enforcing strict global thresholds: 100% lines, 97% functions, and 98% branches. (5) Update `src/scaffold.ts` and `lib/scaffold.js` to align starter template configurations with the consolidated Jest and TypeScript runner.
|
|
79
|
+
- **Consequences:** ✅ Unified, single-tool test runner across developer and CI pipelines. ✅ End-to-end type safety: `tsc --noEmit` verifies all source and 35 test files without error. ✅ Direct source instrumentation: 100.00% line coverage, 100.00% function coverage, and 98.44% branch coverage achieved on authored TypeScript (`src/`) and scripts. ✅ Clean build separation: `npm run build` strictly emits compiled production code in `lib/` without test artifacts. ✅ Zero external runtime dependencies preserved.
|
|
80
|
+
- **Enforced In:** `package.json`, `tsconfig.json`, `tsconfig.build.json`, `jest.config.js`, `tests/**/*.test.ts`, `src/scaffold.ts`, `lib/scaffold.js`
|
|
81
|
+
|
|
74
82
|
#### ADR-011: The Bash Scaffolder Refuses Protected Targets
|
|
75
83
|
- **Date:** 2026-10-07 | **Status:** ACCEPTED
|
|
76
84
|
- **Context:** ADR-010 closed the protected-target hole for the Node scaffolder (`lib/scaffold.js`), but the same hole existed in `.agents/skills/lets-build/scripts/bootstrap_workspace.sh`, which runs with no guard at all: invoked with `/` or `~` as the workspace root it would create `src/`, `tests/`, `deploy/`, `specs/` trees there. Its blast radius is smaller than the Node scaffolder's (every file write is create-only — `tokens.json` and `smoke_test.sh` are written only if absent, and `memory.md` is append-only since ADR-009 — except the explicit `AZCODR_RESET_MEMORY=1` reset), so this is pollution rather than destruction. Pollution of `/` or `~` is still unacceptable for a script agents run autonomously.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azcodr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Enterprise Architecture & Agentic Engineering Starter Template",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -55,10 +55,9 @@
|
|
|
55
55
|
"node": ">=22.8.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
|
-
"build": "tsc",
|
|
59
|
-
"test": "node --
|
|
60
|
-
"test:coverage": "node
|
|
61
|
-
"test:jest": "jest --coverage",
|
|
58
|
+
"build": "tsc -p tsconfig.build.json",
|
|
59
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
60
|
+
"test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
|
|
62
61
|
"lint": "eslint .",
|
|
63
62
|
"typecheck": "tsc --noEmit",
|
|
64
63
|
"validate": "node scripts/validate-cli.js",
|
package/src/errors.ts
CHANGED
|
@@ -15,17 +15,32 @@ export const ERROR_CODES = {
|
|
|
15
15
|
E_PATH_ESCAPE: 'Path escapes allowed root'
|
|
16
16
|
} as const;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Union of valid machine-readable error codes for scaffolding failures.
|
|
20
|
+
*/
|
|
18
21
|
export type ScaffoldErrorCode = keyof typeof ERROR_CODES;
|
|
19
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Structural interface contract for errors thrown by the scaffolder.
|
|
25
|
+
*/
|
|
20
26
|
export interface ScaffoldErrorShape extends Error {
|
|
21
27
|
name: 'ScaffoldError';
|
|
22
28
|
code: ScaffoldErrorCode;
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
33
|
+
*/
|
|
25
34
|
export class ScaffoldError extends Error implements ScaffoldErrorShape {
|
|
26
35
|
override readonly name: 'ScaffoldError' = 'ScaffoldError';
|
|
27
36
|
readonly code: ScaffoldErrorCode;
|
|
28
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Constructs a new ScaffoldError instance.
|
|
40
|
+
*
|
|
41
|
+
* @param code - Machine-readable error code.
|
|
42
|
+
* @param message - Human-readable explanation of the error.
|
|
43
|
+
*/
|
|
29
44
|
constructor(code: ScaffoldErrorCode, message: string) {
|
|
30
45
|
super(message);
|
|
31
46
|
this.code = code;
|
package/src/git.ts
CHANGED
|
@@ -15,6 +15,14 @@ export const GIT_ALLOWED_SUBCOMMANDS = new Set([
|
|
|
15
15
|
'commit'
|
|
16
16
|
]);
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Safely executes an allowlisted git subcommand using execFileSync with an argument array and shell disabled.
|
|
20
|
+
*
|
|
21
|
+
* @param args - Subcommand and arguments array to pass to git.
|
|
22
|
+
* @param options - Child process execution options.
|
|
23
|
+
* @returns Standard output from git as a string.
|
|
24
|
+
* @throws {ScaffoldError} When args is empty or the subcommand is not in GIT_ALLOWED_SUBCOMMANDS.
|
|
25
|
+
*/
|
|
18
26
|
export function runGit(args: string[], options: cp.ExecFileSyncOptions = {}): string {
|
|
19
27
|
if (!Array.isArray(args) || args.length === 0) {
|
|
20
28
|
throw new ScaffoldError('E_GIT_ARGS_INVALID', ERROR_CODES.E_GIT_ARGS_INVALID);
|
package/src/guards.ts
CHANGED
|
@@ -5,6 +5,9 @@ import process from 'node:process';
|
|
|
5
5
|
import { ScaffoldError, ERROR_CODES } from './errors.js';
|
|
6
6
|
import { getTemplateDir } from './scaffold.js';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Options for configuring protected target verification.
|
|
10
|
+
*/
|
|
8
11
|
export interface ProtectedTargetOptions {
|
|
9
12
|
templateDir?: string;
|
|
10
13
|
force?: boolean;
|
|
@@ -14,7 +17,12 @@ export interface ProtectedTargetOptions {
|
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Filesystem scope guard (Supply Chain: filesystem access).
|
|
17
|
-
* Constrains all reads/writes to targetDir / templateDir.
|
|
20
|
+
* Constrains all reads/writes to targetDir / templateDir, throwing if candidate escapes root.
|
|
21
|
+
*
|
|
22
|
+
* @param root - Absolute base directory.
|
|
23
|
+
* @param candidate - Candidate file or directory path to check.
|
|
24
|
+
* @param message - Optional custom error message.
|
|
25
|
+
* @throws {ScaffoldError} When candidate path escapes root directory.
|
|
18
26
|
*/
|
|
19
27
|
export function assertInside(root: string, candidate: string, message?: string): void {
|
|
20
28
|
const resolvedRoot = path.resolve(root);
|
|
@@ -29,6 +37,9 @@ export function assertInside(root: string, candidate: string, message?: string):
|
|
|
29
37
|
* Normalizes a path for protected-target comparison. On Windows the filesystem
|
|
30
38
|
* is case-insensitive, so `C:\Users\Name` and `c:\users\name` are the same
|
|
31
39
|
* directory and must compare equal.
|
|
40
|
+
*
|
|
41
|
+
* @param p - File or directory path to normalize.
|
|
42
|
+
* @returns Normalized path string.
|
|
32
43
|
*/
|
|
33
44
|
export function normalizeForComparison(p: string): string {
|
|
34
45
|
const resolved = path.resolve(p);
|
|
@@ -82,6 +93,10 @@ function resolvesToProtectedLocation(resolvedTarget: string, home: string): bool
|
|
|
82
93
|
*
|
|
83
94
|
* Lexical comparison is not enough: a symlink pointing at home must also be
|
|
84
95
|
* caught, so an existing target is resolved with realpath before comparing.
|
|
96
|
+
*
|
|
97
|
+
* @param targetDir - The target directory path to evaluate.
|
|
98
|
+
* @param options - Optional configuration for protected target evaluation.
|
|
99
|
+
* @returns True if target is a protected location, false otherwise.
|
|
85
100
|
*/
|
|
86
101
|
export function isProtectedTarget(targetDir: string, options: ProtectedTargetOptions = {}): boolean {
|
|
87
102
|
const resolvedTarget = path.resolve(targetDir);
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @azcodr/azcodr
|
|
3
|
+
* Enterprise Architecture & Agentic Engineering Starter Template.
|
|
4
|
+
*
|
|
5
|
+
* Provides problem-first, topology-aligned project scaffolding with strict systemic atomicity,
|
|
6
|
+
* filesystem scope guards, git worktree initialization, and multi-agent harness parity.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Union type of all valid machine-readable error codes.
|
|
11
|
+
*/
|
|
1
12
|
export type ScaffoldErrorCode =
|
|
2
13
|
| 'E_TARGET_IS_TEMPLATE'
|
|
3
14
|
| 'E_TARGET_NOT_EMPTY'
|
|
@@ -6,6 +17,9 @@ export type ScaffoldErrorCode =
|
|
|
6
17
|
| 'E_GIT_BLOCKED'
|
|
7
18
|
| 'E_PATH_ESCAPE';
|
|
8
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Core scaffolding functions, guards, utilities, error classes, and constants.
|
|
22
|
+
*/
|
|
9
23
|
export {
|
|
10
24
|
scaffold,
|
|
11
25
|
validateTarget,
|
|
@@ -25,6 +39,9 @@ export {
|
|
|
25
39
|
ERROR_CODES
|
|
26
40
|
} from './scaffold.js';
|
|
27
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Type definitions and option interfaces for scaffolding operations.
|
|
44
|
+
*/
|
|
28
45
|
export type {
|
|
29
46
|
ScaffoldOptions,
|
|
30
47
|
ScaffoldResult,
|
|
@@ -36,4 +53,8 @@ export type {
|
|
|
36
53
|
} from './scaffold.js';
|
|
37
54
|
|
|
38
55
|
import scaffoldModule from './scaffold.js';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default export providing the unified azcodr scaffolding module.
|
|
59
|
+
*/
|
|
39
60
|
export default scaffoldModule;
|
package/src/links.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options for symlink and pointer creation.
|
|
6
|
+
*/
|
|
4
7
|
export interface EnsureSymlinkOptions {
|
|
5
8
|
targetDir: string;
|
|
6
9
|
linkName: string;
|
|
@@ -70,6 +73,11 @@ function copyFallback(targetDir: string, linkName: string, targetFileName: strin
|
|
|
70
73
|
/**
|
|
71
74
|
* Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
|
|
72
75
|
* Uses exact directory listing (not existsSync, which lies on case-insensitive systems).
|
|
76
|
+
*
|
|
77
|
+
* @param targetDir - Directory containing the file entries.
|
|
78
|
+
* @param linkName - Name of the proposed symlink or alias entry.
|
|
79
|
+
* @param targetFileName - Target file name to match against.
|
|
80
|
+
* @returns True if both names resolve to the same disk file on a case-insensitive filesystem.
|
|
73
81
|
*/
|
|
74
82
|
export function isSameCaseInsensitiveFile(
|
|
75
83
|
targetDir: string,
|
|
@@ -90,6 +98,9 @@ export function isSameCaseInsensitiveFile(
|
|
|
90
98
|
|
|
91
99
|
/**
|
|
92
100
|
* Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
|
|
101
|
+
*
|
|
102
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
103
|
+
* @returns True if the symlink or copy fallback was successfully established.
|
|
93
104
|
*/
|
|
94
105
|
export function ensureSymlink(options: EnsureSymlinkOptions): boolean {
|
|
95
106
|
const { targetDir, linkName, targetFileName, dryRun = false } = options;
|
|
@@ -110,6 +121,9 @@ export function ensureSymlink(options: EnsureSymlinkOptions): boolean {
|
|
|
110
121
|
* Creates a symlink, falling back to a text pointer (not a full copy).
|
|
111
122
|
* Used for .github/copilot-instructions.md where a full AGENTS.md copy would
|
|
112
123
|
* break relative markdown links (they resolve from .github/, not root).
|
|
124
|
+
*
|
|
125
|
+
* @param options - Options specifying target directory, link name, target file name, and dry-run mode.
|
|
126
|
+
* @returns True if the symlink or pointer fallback was successfully established.
|
|
113
127
|
*/
|
|
114
128
|
export function ensureSymlinkOrPointer(options: EnsureSymlinkOptions): boolean {
|
|
115
129
|
const { targetDir, linkName, targetFileName, dryRun = false } = options;
|
package/src/permissions.ts
CHANGED
|
@@ -25,6 +25,10 @@ function chmodShFilesIn(scriptsDir: string, dryRun: boolean): string[] {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Ensures all bash scripts in agent and skill directories have executable permissions (0o755).
|
|
28
|
+
*
|
|
29
|
+
* @param targetDir - Root directory containing .agents and skills.
|
|
30
|
+
* @param dryRun - When true, simulates permission changes without modifying disk.
|
|
31
|
+
* @returns Array of file paths that were modified or would be modified.
|
|
28
32
|
*/
|
|
29
33
|
export function makeScriptsExecutable(targetDir: string, dryRun = false): string[] {
|
|
30
34
|
const agentScriptsDir = path.join(targetDir, '.agents', 'scripts');
|
package/src/repo.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { runGit } from './git.js';
|
|
|
5
5
|
|
|
6
6
|
const INITIAL_COMMIT_MESSAGE = 'chore: initial scaffold from azcodr template';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Options controlling git repository initialization.
|
|
10
|
+
*/
|
|
8
11
|
export interface InitGitOptions {
|
|
9
12
|
noGit?: boolean;
|
|
10
13
|
dryRun?: boolean;
|
|
@@ -13,6 +16,9 @@ export interface InitGitOptions {
|
|
|
13
16
|
/**
|
|
14
17
|
* Detects whether targetDir is already inside an existing Git worktree.
|
|
15
18
|
* Socket note: shell access is limited to `git rev-parse` via runGit (no shell).
|
|
19
|
+
*
|
|
20
|
+
* @param targetDir - Directory path to inspect.
|
|
21
|
+
* @returns True if target directory is within a git worktree, false otherwise.
|
|
16
22
|
*/
|
|
17
23
|
export function isInsideGitWorkTree(targetDir: string): boolean {
|
|
18
24
|
try {
|
|
@@ -74,6 +80,10 @@ function initialCommit(targetDir: string): void {
|
|
|
74
80
|
/**
|
|
75
81
|
* Initializes a git repository in the target directory if not already inside one.
|
|
76
82
|
* Socket note: only allowlisted `git init/branch/add/commit` via execFileSync, cwd scoped.
|
|
83
|
+
*
|
|
84
|
+
* @param targetDir - Directory where git repository should be initialized.
|
|
85
|
+
* @param options - Configuration options for git initialization.
|
|
86
|
+
* @returns True if repository was initialized and committed, false otherwise.
|
|
77
87
|
*/
|
|
78
88
|
export function initGit(targetDir: string, options: InitGitOptions = {}): boolean {
|
|
79
89
|
const { noGit = false, dryRun = false } = options;
|
package/src/scaffold.ts
CHANGED
|
@@ -12,6 +12,9 @@ import { makeScriptsExecutable } from './permissions.js';
|
|
|
12
12
|
import { isInsideGitWorkTree, initGit } from './repo.js';
|
|
13
13
|
import type { InitGitOptions } from './repo.js';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Canonical list of template files and directories copied into a new workspace.
|
|
17
|
+
*/
|
|
15
18
|
export const TEMPLATE_ITEMS: readonly string[] = [
|
|
16
19
|
'AGENTS.md',
|
|
17
20
|
'memory.md',
|
|
@@ -25,6 +28,9 @@ export const TEMPLATE_ITEMS: readonly string[] = [
|
|
|
25
28
|
'LICENSE'
|
|
26
29
|
];
|
|
27
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Configuration options for the primary scaffold orchestration function.
|
|
33
|
+
*/
|
|
28
34
|
export interface ScaffoldOptions {
|
|
29
35
|
targetDir?: string;
|
|
30
36
|
force?: boolean;
|
|
@@ -34,6 +40,9 @@ export interface ScaffoldOptions {
|
|
|
34
40
|
silent?: boolean;
|
|
35
41
|
}
|
|
36
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Result object returned upon completion of a scaffold operation.
|
|
45
|
+
*/
|
|
37
46
|
export interface ScaffoldResult {
|
|
38
47
|
success: boolean;
|
|
39
48
|
targetDir: string;
|
|
@@ -42,6 +51,9 @@ export interface ScaffoldResult {
|
|
|
42
51
|
actions: string[];
|
|
43
52
|
}
|
|
44
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Options controlling pre-scaffold target directory validation.
|
|
56
|
+
*/
|
|
45
57
|
export interface ValidateTargetOptions {
|
|
46
58
|
templateDir?: string;
|
|
47
59
|
force?: boolean;
|
|
@@ -49,12 +61,17 @@ export interface ValidateTargetOptions {
|
|
|
49
61
|
allowProtected?: boolean;
|
|
50
62
|
}
|
|
51
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Options controlling template file copying and file generation.
|
|
66
|
+
*/
|
|
52
67
|
export interface CopyTemplateOptions {
|
|
53
68
|
dryRun?: boolean;
|
|
54
69
|
}
|
|
55
70
|
|
|
56
71
|
/**
|
|
57
|
-
*
|
|
72
|
+
* Resolves the root filesystem directory of the azcodr template files.
|
|
73
|
+
*
|
|
74
|
+
* @returns Absolute filesystem path to the template root directory.
|
|
58
75
|
*/
|
|
59
76
|
export function getTemplateDir(): string {
|
|
60
77
|
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -94,6 +111,10 @@ function rejectNonEmptyTarget(resolvedTarget: string, force: boolean): void {
|
|
|
94
111
|
|
|
95
112
|
/**
|
|
96
113
|
* Validates the target directory to ensure it is suitable for scaffolding.
|
|
114
|
+
*
|
|
115
|
+
* @param targetDir - Target directory path to validate.
|
|
116
|
+
* @param options - Validation options including force, dry-run, and protected overrides.
|
|
117
|
+
* @throws {ScaffoldError} When target is invalid, protected, or non-empty without force.
|
|
97
118
|
*/
|
|
98
119
|
export function validateTarget(targetDir: string, options: ValidateTargetOptions = {}): void {
|
|
99
120
|
const { templateDir = getTemplateDir(), force = false, dryRun = false, allowProtected = false } = options;
|
|
@@ -169,7 +190,7 @@ function starterPackageJson(resolvedTarget: string): Record<string, unknown> {
|
|
|
169
190
|
description: 'Scaffolded with azcodr enterprise architecture template',
|
|
170
191
|
scripts: {
|
|
171
192
|
test: 'node --test',
|
|
172
|
-
'test:coverage': '
|
|
193
|
+
'test:coverage': 'jest --coverage',
|
|
173
194
|
lint: 'echo "No linter configured yet. Run /lets-build to configure toolchain."',
|
|
174
195
|
validate: 'node scripts/validate-cli.js'
|
|
175
196
|
}
|
|
@@ -197,6 +218,11 @@ function chmodTemplateScripts(inspectDir: string, dryRun: boolean): string[] {
|
|
|
197
218
|
/**
|
|
198
219
|
* Recursively copies template files into the target directory and sets up symlinks and permissions.
|
|
199
220
|
* Socket note: filesystem access is scoped to templateDir -> targetDir only (assertInside).
|
|
221
|
+
*
|
|
222
|
+
* @param targetDir - Destination directory path.
|
|
223
|
+
* @param templateDir - Source template directory path.
|
|
224
|
+
* @param options - Copy options including dry-run flag.
|
|
225
|
+
* @returns Array of recorded scaffolding action descriptions.
|
|
200
226
|
*/
|
|
201
227
|
export function copyTemplate(
|
|
202
228
|
targetDir: string,
|
|
@@ -220,6 +246,9 @@ export function copyTemplate(
|
|
|
220
246
|
|
|
221
247
|
/**
|
|
222
248
|
* High-level orchestration function to scaffold the azcodr workspace into targetDir.
|
|
249
|
+
*
|
|
250
|
+
* @param options - Scaffolding options.
|
|
251
|
+
* @returns Result object containing success flag, target directory, and action log.
|
|
223
252
|
*/
|
|
224
253
|
export function scaffold(options: ScaffoldOptions = {}): ScaffoldResult {
|
|
225
254
|
const {
|
|
@@ -238,36 +267,16 @@ export function scaffold(options: ScaffoldOptions = {}): ScaffoldResult {
|
|
|
238
267
|
}
|
|
239
268
|
|
|
240
269
|
export {
|
|
241
|
-
ensureSymlink,
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
makeScriptsExecutable,
|
|
245
|
-
isInsideGitWorkTree,
|
|
246
|
-
initGit,
|
|
247
|
-
runGit,
|
|
248
|
-
assertInside,
|
|
249
|
-
ScaffoldError,
|
|
250
|
-
ERROR_CODES,
|
|
251
|
-
isProtectedTarget
|
|
270
|
+
ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile,
|
|
271
|
+
makeScriptsExecutable, isInsideGitWorkTree, initGit, runGit,
|
|
272
|
+
assertInside, ScaffoldError, ERROR_CODES, isProtectedTarget
|
|
252
273
|
};
|
|
253
274
|
|
|
254
275
|
export type { EnsureSymlinkOptions, InitGitOptions, ScaffoldErrorCode, ScaffoldErrorShape };
|
|
255
276
|
|
|
256
277
|
export default {
|
|
257
|
-
scaffold,
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
ensureSymlinkOrPointer,
|
|
262
|
-
isSameCaseInsensitiveFile,
|
|
263
|
-
makeScriptsExecutable,
|
|
264
|
-
isInsideGitWorkTree,
|
|
265
|
-
initGit,
|
|
266
|
-
getTemplateDir,
|
|
267
|
-
runGit,
|
|
268
|
-
assertInside,
|
|
269
|
-
TEMPLATE_ITEMS,
|
|
270
|
-
ScaffoldError,
|
|
271
|
-
ERROR_CODES,
|
|
272
|
-
isProtectedTarget
|
|
278
|
+
scaffold, validateTarget, copyTemplate, ensureSymlink,
|
|
279
|
+
ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable,
|
|
280
|
+
isInsideGitWorkTree, initGit, getTemplateDir, runGit,
|
|
281
|
+
assertInside, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES, isProtectedTarget
|
|
273
282
|
};
|
package/scripts/test_coverage.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { spawnSync } from 'node:child_process';
|
|
4
|
-
import process from 'node:process';
|
|
5
|
-
|
|
6
|
-
// Native threshold flags and include filtering were added in Node v22.8.0.
|
|
7
|
-
// Fail closed on older runtimes instead of silently passing without a gate.
|
|
8
|
-
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
9
|
-
const supportsThresholds = major > 22 || (major === 22 && minor >= 8);
|
|
10
|
-
if (!supportsThresholds) {
|
|
11
|
-
console.error(
|
|
12
|
-
`test:coverage requires Node >=22.8.0 for threshold enforcement (current: ${process.versions.node}). ` +
|
|
13
|
-
`Upgrade Node, or invoke the runner directly: node --test --experimental-test-coverage.`
|
|
14
|
-
);
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const args = [
|
|
19
|
-
'--test',
|
|
20
|
-
'--experimental-test-coverage',
|
|
21
|
-
'--test-coverage-include=bin/**',
|
|
22
|
-
'--test-coverage-include=lib/**',
|
|
23
|
-
// Explicit file, not scripts/**: validate-cli.js is a two-line process entry
|
|
24
|
-
// that only runs when invoked directly, so it cannot be covered in-process.
|
|
25
|
-
// Every other script IS gated.
|
|
26
|
-
'--test-coverage-include=scripts/validate.js',
|
|
27
|
-
'--test-coverage-include=scripts/validate/io.js',
|
|
28
|
-
'--test-coverage-include=scripts/validate/text.js',
|
|
29
|
-
'--test-coverage-include=scripts/validate/parity.js',
|
|
30
|
-
'--test-coverage-include=scripts/validate/adr.js',
|
|
31
|
-
'--test-coverage-include=scripts/validate/root.js',
|
|
32
|
-
'--test-coverage-include=scripts/validate/rules.js',
|
|
33
|
-
'--test-coverage-include=scripts/validate/skills.js',
|
|
34
|
-
'--test-coverage-include=scripts/validate/links.js',
|
|
35
|
-
'--test-coverage-include=scripts/test_coverage.js',
|
|
36
|
-
// bin/, lib/ and test_coverage.js hold no environment-dependent defensive
|
|
37
|
-
// branches and are held at 100%. validate.js is a filesystem auditor: it
|
|
38
|
-
// contains fault handlers for conditions this host cannot produce (creating
|
|
39
|
-
// symlinks requires Developer Mode; a RangeError needs a tree thousands of
|
|
40
|
-
// levels deep). Those are exercised by tests/validate-faults.test.js where
|
|
41
|
-
// the fault can be injected, so the gate here is deliberately lower rather
|
|
42
|
-
// than silently passing.
|
|
43
|
-
'--test-coverage-branches=98',
|
|
44
|
-
'--test-coverage-functions=97',
|
|
45
|
-
'--test-coverage-lines=100'
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
const result = spawnSync(process.execPath, args, {
|
|
49
|
-
stdio: 'inherit',
|
|
50
|
-
env: process.env
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
if (result.error) {
|
|
54
|
-
console.error(result.error);
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// A null status means the child was killed by a signal (OOM, SIGKILL from a
|
|
59
|
-
// runner timeout). `status ?? 0` reported success for a crashed runner, which
|
|
60
|
-
// is how a green build can carry zero coverage data.
|
|
61
|
-
if (result.signal) {
|
|
62
|
-
console.error(`test runner terminated by signal ${result.signal}; coverage gate could not be evaluated.`);
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
process.exit(result.status ?? 1);
|