azcodr 2.6.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/hooks.json +3 -3
- package/.agents/hooks.json.example +4 -4
- package/.agents/lib/agent-guard-command.js +6 -0
- package/.agents/lib/agent-guard-file.js +15 -0
- package/.agents/lib/agent-guard-tdd.js +30 -0
- package/.agents/lib/boundaries.js +35 -0
- package/.agents/scripts/desktop_doctor.js +108 -0
- package/.agents/scripts/safety_guard.js +82 -0
- package/.agents/scripts/smoke_test.js +78 -0
- package/.agents/scripts/verify_completion.js +76 -0
- package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +6 -0
- package/.gitignore +1 -0
- package/lib/agent-guard-command.d.ts +17 -0
- package/lib/agent-guard-command.d.ts.map +1 -1
- package/lib/agent-guard-command.js +6 -0
- package/lib/agent-guard-command.js.map +1 -1
- package/lib/agent-guard-file.d.ts +31 -0
- package/lib/agent-guard-file.d.ts.map +1 -1
- package/lib/agent-guard-file.js +15 -0
- package/lib/agent-guard-file.js.map +1 -1
- package/lib/agent-guard-tdd.d.ts +42 -0
- package/lib/agent-guard-tdd.d.ts.map +1 -1
- package/lib/agent-guard-tdd.js +30 -0
- package/lib/agent-guard-tdd.js.map +1 -1
- package/lib/agent-guard.d.ts +17 -0
- package/lib/agent-guard.d.ts.map +1 -1
- package/lib/agent-guard.js.map +1 -1
- package/lib/boundaries.d.ts +54 -0
- package/lib/boundaries.d.ts.map +1 -1
- package/lib/boundaries.js +35 -0
- package/lib/boundaries.js.map +1 -1
- package/lib/errors.d.ts +16 -0
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +8 -0
- package/lib/errors.js.map +1 -1
- package/lib/guards.d.ts +4 -0
- package/lib/guards.d.ts.map +1 -1
- package/lib/guards.js.map +1 -1
- package/lib/links.d.ts +4 -0
- package/lib/links.d.ts.map +1 -1
- package/lib/links.js.map +1 -1
- package/lib/repo.d.ts +2 -0
- package/lib/repo.d.ts.map +1 -1
- package/lib/repo.js.map +1 -1
- package/lib/scaffold.d.ts +19 -0
- package/lib/scaffold.d.ts.map +1 -1
- package/lib/scaffold.js +4 -0
- package/lib/scaffold.js.map +1 -1
- package/lib/validate.d.ts +17 -0
- package/lib/validate.d.ts.map +1 -1
- package/lib/validate.js.map +1 -1
- package/memory.md +8 -0
- package/package.json +1 -1
- package/src/agent-guard-command.ts +17 -0
- package/src/agent-guard-file.ts +31 -0
- package/src/agent-guard-tdd.ts +42 -0
- package/src/agent-guard.ts +17 -0
- package/src/boundaries.ts +54 -0
- package/src/errors.ts +10 -0
- package/src/guards.ts +4 -0
- package/src/links.ts +4 -0
- package/src/repo.ts +2 -0
- package/src/scaffold.ts +22 -7
- package/src/validate.ts +17 -0
|
@@ -1,19 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default maximum lines allowed per file before triggering Refactor-Before-Add enforcement.
|
|
3
|
+
*/
|
|
1
4
|
export declare const DEFAULT_MAX_FILE_LINES = 300;
|
|
5
|
+
/**
|
|
6
|
+
* Parameters provided to evaluate a proposed file write or edit operation.
|
|
7
|
+
*/
|
|
2
8
|
export interface FileCheckInput {
|
|
9
|
+
/** Path of the file being written or edited. */
|
|
3
10
|
filePath: string;
|
|
11
|
+
/** Proposed full file content when creating or overwriting a file. */
|
|
4
12
|
incomingContent?: string;
|
|
13
|
+
/** Chunk replacement string when applying an in-place edit. */
|
|
5
14
|
replacementContent?: string;
|
|
15
|
+
/** Target content chunk being matched and replaced. */
|
|
6
16
|
targetContent?: string;
|
|
17
|
+
/** Optional custom maximum line threshold (defaults to DEFAULT_MAX_FILE_LINES). */
|
|
7
18
|
maxLines?: number;
|
|
8
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Outcome of evaluating a proposed file modification against file size fitness functions.
|
|
22
|
+
*/
|
|
9
23
|
export interface FileCheckResult {
|
|
24
|
+
/** Whether the file edit is blocked under Refactor-Before-Add. */
|
|
10
25
|
blocked: boolean;
|
|
26
|
+
/** Human-readable explanation when the write is blocked. */
|
|
11
27
|
reason?: string;
|
|
28
|
+
/** Current line count of the file on disk. */
|
|
12
29
|
currentLines: number;
|
|
30
|
+
/** Projected line count after applying the proposed modification. */
|
|
13
31
|
projectedLines: number;
|
|
32
|
+
/** Maximum line limit enforced for this file. */
|
|
14
33
|
maxLines: number;
|
|
15
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Calculates the number of newline-delimited lines in a given text string.
|
|
37
|
+
*
|
|
38
|
+
* @param text - Input string to evaluate.
|
|
39
|
+
* @returns Total count of lines.
|
|
40
|
+
*/
|
|
16
41
|
export declare function countLines(text: string): number;
|
|
42
|
+
/**
|
|
43
|
+
* Reads an existing file from disk and returns its current line count.
|
|
44
|
+
*
|
|
45
|
+
* @param filePath - Path of the file to inspect.
|
|
46
|
+
* @returns Total number of lines, or 0 if unreadable or non-existent.
|
|
47
|
+
*/
|
|
17
48
|
export declare function readExistingLines(filePath: string): number;
|
|
18
49
|
/**
|
|
19
50
|
* Checks a proposed file write or edit against Refactor-Before-Add rules.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard-file.d.ts","sourceRoot":"","sources":["../src/agent-guard-file.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAgDD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAWvE;;;;;;;AAED,wBAKE"}
|
|
1
|
+
{"version":3,"file":"agent-guard-file.d.ts","sourceRoot":"","sources":["../src/agent-guard-file.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAgDD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAWvE;;;;;;;AAED,wBAKE"}
|
package/lib/agent-guard-file.js
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Default maximum lines allowed per file before triggering Refactor-Before-Add enforcement.
|
|
5
|
+
*/
|
|
3
6
|
export const DEFAULT_MAX_FILE_LINES = 300;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the number of newline-delimited lines in a given text string.
|
|
9
|
+
*
|
|
10
|
+
* @param text - Input string to evaluate.
|
|
11
|
+
* @returns Total count of lines.
|
|
12
|
+
*/
|
|
4
13
|
export function countLines(text) {
|
|
5
14
|
if (!text)
|
|
6
15
|
return 0;
|
|
7
16
|
return text.split('\n').length;
|
|
8
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Reads an existing file from disk and returns its current line count.
|
|
20
|
+
*
|
|
21
|
+
* @param filePath - Path of the file to inspect.
|
|
22
|
+
* @returns Total number of lines, or 0 if unreadable or non-existent.
|
|
23
|
+
*/
|
|
9
24
|
export function readExistingLines(filePath) {
|
|
10
25
|
if (!fs.existsSync(filePath))
|
|
11
26
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard-file.js","sourceRoot":"","sources":["../src/agent-guard-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-guard-file.js","sourceRoot":"","sources":["../src/agent-guard-file.ts"],"names":[],"mappings":"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"}
|
package/lib/agent-guard-tdd.d.ts
CHANGED
|
@@ -1,17 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent state tracking test-first TDD progress across an agent session.
|
|
3
|
+
*/
|
|
1
4
|
export interface SessionTddState {
|
|
5
|
+
/** Whether a failing test execution (RED phase) has been recorded in the session. */
|
|
2
6
|
lastFailingTestRecorded: boolean;
|
|
7
|
+
/** Unix timestamp in milliseconds when the last test execution occurred. */
|
|
3
8
|
lastTestRunTime?: number;
|
|
9
|
+
/** File path of the most recently executed test file. */
|
|
4
10
|
lastTestPath?: string;
|
|
5
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of evaluating a file edit against RED-before-GREEN TDD rules.
|
|
14
|
+
*/
|
|
6
15
|
export interface TddCheckResult {
|
|
16
|
+
/** Whether the file edit is blocked due to missing failing test. */
|
|
7
17
|
blocked: boolean;
|
|
18
|
+
/** Explanatory reason if the operation is blocked. */
|
|
8
19
|
reason?: string;
|
|
20
|
+
/** Whether the target file was identified as production source code. */
|
|
9
21
|
isProductionFile: boolean;
|
|
10
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Identifies whether a given path is a unit or integration test file.
|
|
25
|
+
*
|
|
26
|
+
* @param filePath - File path to inspect.
|
|
27
|
+
* @returns True if path matches test directory or file extension patterns.
|
|
28
|
+
*/
|
|
11
29
|
export declare function isTestFile(filePath: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Identifies whether a given path is a non-code file (markdown, json, yaml, images).
|
|
32
|
+
*
|
|
33
|
+
* @param filePath - File path to inspect.
|
|
34
|
+
* @returns True if file extension indicates non-code asset or configuration.
|
|
35
|
+
*/
|
|
12
36
|
export declare function isNonCodeFile(filePath: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Identifies whether a given file path corresponds to production code under src/, lib/, or app/.
|
|
39
|
+
*
|
|
40
|
+
* @param filePath - File path to inspect.
|
|
41
|
+
* @returns True if path is production source code subject to RED-before-GREEN discipline.
|
|
42
|
+
*/
|
|
13
43
|
export declare function isProductionFile(filePath: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Loads session TDD tracking state from disk, defaulting to unrecorded state if missing.
|
|
46
|
+
*
|
|
47
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
48
|
+
* @returns Parsed SessionTddState object.
|
|
49
|
+
*/
|
|
14
50
|
export declare function readTddState(stateFile: string): SessionTddState;
|
|
51
|
+
/**
|
|
52
|
+
* Persists session TDD state to disk with fail-safe error handling to avoid disrupting execution.
|
|
53
|
+
*
|
|
54
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
55
|
+
* @param state - SessionTddState object to record.
|
|
56
|
+
*/
|
|
15
57
|
export declare function writeTddState(stateFile: string, state: SessionTddState): void;
|
|
16
58
|
/**
|
|
17
59
|
* Checks whether an edit to a file is allowed under RED-before-GREEN TDD rules.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard-tdd.d.ts","sourceRoot":"","sources":["../src/agent-guard-tdd.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,uBAAuB,EAAE,OAAO,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMpD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAU/D;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAQ7E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EACtB,gBAAgB,GAAE,OAAe,GAChC,cAAc,CAgBhB;;;;;;;;;AAED,wBAOE"}
|
|
1
|
+
{"version":3,"file":"agent-guard-tdd.d.ts","sourceRoot":"","sources":["../src/agent-guard-tdd.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qFAAqF;IACrF,uBAAuB,EAAE,OAAO,CAAC;IACjC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMpD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAU/D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAQ7E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,eAAe,EACtB,gBAAgB,GAAE,OAAe,GAChC,cAAc,CAgBhB;;;;;;;;;AAED,wBAOE"}
|
package/lib/agent-guard-tdd.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Identifies whether a given path is a unit or integration test file.
|
|
5
|
+
*
|
|
6
|
+
* @param filePath - File path to inspect.
|
|
7
|
+
* @returns True if path matches test directory or file extension patterns.
|
|
8
|
+
*/
|
|
3
9
|
export function isTestFile(filePath) {
|
|
4
10
|
const norm = filePath.replace(/\\/g, '/').toLowerCase();
|
|
5
11
|
if (/(^|\/)(tests?|__tests__)(\/|$)/i.test(norm)) {
|
|
@@ -7,11 +13,23 @@ export function isTestFile(filePath) {
|
|
|
7
13
|
}
|
|
8
14
|
return /\.(test|spec)\.[a-z0-9]+$/i.test(norm);
|
|
9
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Identifies whether a given path is a non-code file (markdown, json, yaml, images).
|
|
18
|
+
*
|
|
19
|
+
* @param filePath - File path to inspect.
|
|
20
|
+
* @returns True if file extension indicates non-code asset or configuration.
|
|
21
|
+
*/
|
|
10
22
|
export function isNonCodeFile(filePath) {
|
|
11
23
|
const ext = path.extname(filePath).toLowerCase();
|
|
12
24
|
const nonCodeExts = new Set(['.md', '.json', '.yml', '.yaml', '.txt', '.toml', '.lock', '.svg', '.png']);
|
|
13
25
|
return nonCodeExts.has(ext);
|
|
14
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Identifies whether a given file path corresponds to production code under src/, lib/, or app/.
|
|
29
|
+
*
|
|
30
|
+
* @param filePath - File path to inspect.
|
|
31
|
+
* @returns True if path is production source code subject to RED-before-GREEN discipline.
|
|
32
|
+
*/
|
|
15
33
|
export function isProductionFile(filePath) {
|
|
16
34
|
if (isNonCodeFile(filePath))
|
|
17
35
|
return false;
|
|
@@ -20,6 +38,12 @@ export function isProductionFile(filePath) {
|
|
|
20
38
|
const norm = filePath.replace(/\\/g, '/').toLowerCase();
|
|
21
39
|
return norm.includes('src/') || norm.includes('lib/') || norm.includes('app/');
|
|
22
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Loads session TDD tracking state from disk, defaulting to unrecorded state if missing.
|
|
43
|
+
*
|
|
44
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
45
|
+
* @returns Parsed SessionTddState object.
|
|
46
|
+
*/
|
|
23
47
|
export function readTddState(stateFile) {
|
|
24
48
|
if (!fs.existsSync(stateFile)) {
|
|
25
49
|
return { lastFailingTestRecorded: false };
|
|
@@ -32,6 +56,12 @@ export function readTddState(stateFile) {
|
|
|
32
56
|
return { lastFailingTestRecorded: false };
|
|
33
57
|
}
|
|
34
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Persists session TDD state to disk with fail-safe error handling to avoid disrupting execution.
|
|
61
|
+
*
|
|
62
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
63
|
+
* @param state - SessionTddState object to record.
|
|
64
|
+
*/
|
|
35
65
|
export function writeTddState(stateFile, state) {
|
|
36
66
|
try {
|
|
37
67
|
const dir = path.dirname(stateFile);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard-tdd.js","sourceRoot":"","sources":["../src/agent-guard-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-guard-tdd.js","sourceRoot":"","sources":["../src/agent-guard-tdd.ts"],"names":[],"mappings":"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"}
|
package/lib/agent-guard.d.ts
CHANGED
|
@@ -4,18 +4,35 @@ import { inspectFileWrite } from './agent-guard-file.js';
|
|
|
4
4
|
import type { FileCheckResult } from './agent-guard-file.js';
|
|
5
5
|
import { inspectTddRequirement, readTddState, writeTddState } from './agent-guard-tdd.js';
|
|
6
6
|
import type { SessionTddState } from './agent-guard-tdd.js';
|
|
7
|
+
/**
|
|
8
|
+
* Verdict returned by agent-runtime safety and architecture inspection guards.
|
|
9
|
+
*/
|
|
7
10
|
export interface GuardDecision {
|
|
11
|
+
/** Whether the requested tool operation is permitted. */
|
|
8
12
|
allowed: boolean;
|
|
13
|
+
/** Explanatory failure reason when the action is blocked. */
|
|
9
14
|
reason?: string;
|
|
15
|
+
/** Subsystem that produced the decision ('command', 'file', or 'tdd'). */
|
|
10
16
|
source?: 'command' | 'file' | 'tdd';
|
|
11
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Normalized representation of an agent tool invocation payload.
|
|
20
|
+
*/
|
|
12
21
|
export interface ToolEnvelope {
|
|
22
|
+
/** Name of the tool invoked by the agent. */
|
|
13
23
|
tool_name?: string;
|
|
24
|
+
/** Parameter payload passed to the tool invocation. */
|
|
14
25
|
tool_input?: Record<string, unknown>;
|
|
15
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Configuration options governing agent guard enforcement behavior.
|
|
29
|
+
*/
|
|
16
30
|
export interface GuardOptions {
|
|
31
|
+
/** Target workspace root directory (defaults to process.cwd()). */
|
|
17
32
|
workspaceRoot?: string;
|
|
33
|
+
/** When true, strictly mandates RED failing test before modifying production code. */
|
|
18
34
|
enforceTestFirst?: boolean;
|
|
35
|
+
/** Maximum non-overflow file line threshold before Refactor-Before-Add triggers. */
|
|
19
36
|
maxFileLines?: number;
|
|
20
37
|
}
|
|
21
38
|
/**
|
package/lib/agent-guard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard.d.ts","sourceRoot":"","sources":["../src/agent-guard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,CAY1F;AAED,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACd,CAAC;AACF,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;;;;;;;AACnE,wBAA2F"}
|
|
1
|
+
{"version":3,"file":"agent-guard.d.ts","sourceRoot":"","sources":["../src/agent-guard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,CAY1F;AAED,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACd,CAAC;AACF,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;;;;;;;AACnE,wBAA2F"}
|
package/lib/agent-guard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-guard.js","sourceRoot":"","sources":["../src/agent-guard.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACd,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-guard.js","sourceRoot":"","sources":["../src/agent-guard.ts"],"names":[],"mappings":"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"}
|
package/lib/boundaries.d.ts
CHANGED
|
@@ -1,24 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines an architectural layer boundary rule disallowing imports from foreign layers.
|
|
3
|
+
*/
|
|
1
4
|
export interface BoundaryRule {
|
|
5
|
+
/** Name of the architectural layer (e.g., 'domain', 'core'). */
|
|
2
6
|
fromLayer: string;
|
|
7
|
+
/** Array of layer names that fromLayer is forbidden from importing. */
|
|
3
8
|
disallowImportsFrom: readonly string[];
|
|
4
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Represents an architectural boundary violation where a module imported a prohibited layer.
|
|
12
|
+
*/
|
|
5
13
|
export interface BoundaryViolation {
|
|
14
|
+
/** Path of the file containing the illegal import. */
|
|
6
15
|
file: string;
|
|
16
|
+
/** Path of the imported file that violates the rule. */
|
|
7
17
|
importedFile: string;
|
|
18
|
+
/** Origin layer of the importing file. */
|
|
8
19
|
fromLayer: string;
|
|
20
|
+
/** Target layer that was forbidden to import. */
|
|
9
21
|
toLayer: string;
|
|
10
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Report summarizing module count, detected circular cycles, and boundary violations.
|
|
25
|
+
*/
|
|
11
26
|
export interface BoundaryReport {
|
|
27
|
+
/** Total number of source modules scanned. */
|
|
12
28
|
moduleCount: number;
|
|
29
|
+
/** List of detected circular dependency cycles. */
|
|
13
30
|
cycles: string[][];
|
|
31
|
+
/** List of detected boundary violations. */
|
|
14
32
|
violations: BoundaryViolation[];
|
|
33
|
+
/** Whether the architecture is completely compliant (no cycles and no violations). */
|
|
15
34
|
ok: boolean;
|
|
16
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Canonical architectural boundary rules enforcing Hexagonal / Clean Architecture layer constraints.
|
|
38
|
+
*/
|
|
17
39
|
export declare const DEFAULT_BOUNDARY_RULES: readonly BoundaryRule[];
|
|
40
|
+
/**
|
|
41
|
+
* Recursively discovers all eligible source files (.ts and .js) within a directory,
|
|
42
|
+
* ignoring skipped directories (e.g. node_modules, lib) and test files.
|
|
43
|
+
*
|
|
44
|
+
* @param dir - Root directory to search.
|
|
45
|
+
* @returns Sorted array of absolute file paths.
|
|
46
|
+
*/
|
|
18
47
|
export declare function findSourceFiles(dir: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Scans a source file and extracts all local relative import and export paths.
|
|
50
|
+
*
|
|
51
|
+
* @param filePath - Absolute or relative path to the source file.
|
|
52
|
+
* @returns Sorted array of resolved local file paths imported or re-exported.
|
|
53
|
+
*/
|
|
19
54
|
export declare function extractLocalImports(filePath: string): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Constructs a dependency graph mapping each source file to its imported local files.
|
|
57
|
+
*
|
|
58
|
+
* @param files - Array of source file paths.
|
|
59
|
+
* @returns Map where keys are source file paths and values are arrays of imported local file paths.
|
|
60
|
+
*/
|
|
20
61
|
export declare function buildDependencyGraph(files: readonly string[]): Map<string, string[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Analyzes a dependency graph using depth-first search to detect circular import cycles.
|
|
64
|
+
*
|
|
65
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
66
|
+
* @returns Array of cycle paths, where each cycle path is an array of file paths.
|
|
67
|
+
*/
|
|
21
68
|
export declare function detectDependencyCycles(graph: Map<string, string[]>): string[][];
|
|
69
|
+
/**
|
|
70
|
+
* Evaluates a dependency graph against architectural boundary rules to detect prohibited cross-layer imports.
|
|
71
|
+
*
|
|
72
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
73
|
+
* @param rules - Architectural boundary rules to enforce (defaults to DEFAULT_BOUNDARY_RULES).
|
|
74
|
+
* @returns Array of detected boundary violations.
|
|
75
|
+
*/
|
|
22
76
|
export declare function detectBoundaryViolations(graph: Map<string, string[]>, rules?: readonly BoundaryRule[]): BoundaryViolation[];
|
|
23
77
|
/**
|
|
24
78
|
* Inspects a source tree for architectural boundary violations and circular dependency cycles.
|
package/lib/boundaries.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundaries.d.ts","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,EAAE,EAAE,OAAO,CAAC;CACb;AAED,eAAO,MAAM,sBAAsB,EAAE,SAAS,YAAY,EASzD,CAAC;AAYF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBrD;AAcD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB9D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAMpF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CA+B/E;AAMD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC5B,KAAK,GAAE,SAAS,YAAY,EAA2B,GACtD,iBAAiB,EAAE,CAuBrB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,SAAS,YAAY,EAA2B,GACtD,cAAc,CAYhB;;;;;;;;;;AAED,wBAQE"}
|
|
1
|
+
{"version":3,"file":"boundaries.d.ts","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,4CAA4C;IAC5C,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,sFAAsF;IACtF,EAAE,EAAE,OAAO,CAAC;CACb;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,YAAY,EASzD,CAAC;AAYF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBrD;AAcD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB9D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAMpF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,CA+B/E;AAMD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC5B,KAAK,GAAE,SAAS,YAAY,EAA2B,GACtD,iBAAiB,EAAE,CAuBrB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,SAAS,YAAY,EAA2B,GACtD,cAAc,CAYhB;;;;;;;;;;AAED,wBAQE"}
|
package/lib/boundaries.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Canonical architectural boundary rules enforcing Hexagonal / Clean Architecture layer constraints.
|
|
5
|
+
*/
|
|
3
6
|
export const DEFAULT_BOUNDARY_RULES = [
|
|
4
7
|
{
|
|
5
8
|
fromLayer: 'domain',
|
|
@@ -19,6 +22,13 @@ function isEligibleSource(name) {
|
|
|
19
22
|
return false;
|
|
20
23
|
return !name.includes('.test.') && !name.includes('.spec.');
|
|
21
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Recursively discovers all eligible source files (.ts and .js) within a directory,
|
|
27
|
+
* ignoring skipped directories (e.g. node_modules, lib) and test files.
|
|
28
|
+
*
|
|
29
|
+
* @param dir - Root directory to search.
|
|
30
|
+
* @returns Sorted array of absolute file paths.
|
|
31
|
+
*/
|
|
22
32
|
export function findSourceFiles(dir) {
|
|
23
33
|
if (!fs.existsSync(dir))
|
|
24
34
|
return [];
|
|
@@ -49,6 +59,12 @@ function resolveImportTarget(sourceFile, specifier) {
|
|
|
49
59
|
}
|
|
50
60
|
return null;
|
|
51
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Scans a source file and extracts all local relative import and export paths.
|
|
64
|
+
*
|
|
65
|
+
* @param filePath - Absolute or relative path to the source file.
|
|
66
|
+
* @returns Sorted array of resolved local file paths imported or re-exported.
|
|
67
|
+
*/
|
|
52
68
|
export function extractLocalImports(filePath) {
|
|
53
69
|
if (!fs.existsSync(filePath))
|
|
54
70
|
return [];
|
|
@@ -66,6 +82,12 @@ export function extractLocalImports(filePath) {
|
|
|
66
82
|
}
|
|
67
83
|
return imports.sort();
|
|
68
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Constructs a dependency graph mapping each source file to its imported local files.
|
|
87
|
+
*
|
|
88
|
+
* @param files - Array of source file paths.
|
|
89
|
+
* @returns Map where keys are source file paths and values are arrays of imported local file paths.
|
|
90
|
+
*/
|
|
69
91
|
export function buildDependencyGraph(files) {
|
|
70
92
|
const graph = new Map();
|
|
71
93
|
for (const file of files) {
|
|
@@ -73,6 +95,12 @@ export function buildDependencyGraph(files) {
|
|
|
73
95
|
}
|
|
74
96
|
return graph;
|
|
75
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Analyzes a dependency graph using depth-first search to detect circular import cycles.
|
|
100
|
+
*
|
|
101
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
102
|
+
* @returns Array of cycle paths, where each cycle path is an array of file paths.
|
|
103
|
+
*/
|
|
76
104
|
export function detectDependencyCycles(graph) {
|
|
77
105
|
const cycles = [];
|
|
78
106
|
const visited = new Set();
|
|
@@ -105,6 +133,13 @@ export function detectDependencyCycles(graph) {
|
|
|
105
133
|
function hasLayerSegment(pathStr, segment) {
|
|
106
134
|
return new RegExp(`(^|[/\\\\])${segment}([/\\\\]|$)`, 'i').test(pathStr);
|
|
107
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Evaluates a dependency graph against architectural boundary rules to detect prohibited cross-layer imports.
|
|
138
|
+
*
|
|
139
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
140
|
+
* @param rules - Architectural boundary rules to enforce (defaults to DEFAULT_BOUNDARY_RULES).
|
|
141
|
+
* @returns Array of detected boundary violations.
|
|
142
|
+
*/
|
|
108
143
|
export function detectBoundaryViolations(graph, rules = DEFAULT_BOUNDARY_RULES) {
|
|
109
144
|
const violations = [];
|
|
110
145
|
for (const [file, imports] of graph.entries()) {
|
package/lib/boundaries.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"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"}
|
package/lib/errors.d.ts
CHANGED
|
@@ -7,11 +7,17 @@
|
|
|
7
7
|
* tests/error-codes.test.js.
|
|
8
8
|
*/
|
|
9
9
|
export declare const ERROR_CODES: {
|
|
10
|
+
/** Target directory matches template repository root itself. */
|
|
10
11
|
readonly E_TARGET_IS_TEMPLATE: "Cannot scaffold into the azcodr template directory itself";
|
|
12
|
+
/** Target directory exists and already contains non-empty files without --force. */
|
|
11
13
|
readonly E_TARGET_NOT_EMPTY: "Target directory is not empty";
|
|
14
|
+
/** Target path matches protected system, home, or root directory. */
|
|
12
15
|
readonly E_TARGET_IS_PROTECTED: "Refusing to scaffold into a protected system directory";
|
|
16
|
+
/** runGit invoked with empty or missing argument array. */
|
|
13
17
|
readonly E_GIT_ARGS_INVALID: "runGit requires a non-empty argv array";
|
|
18
|
+
/** Attempted git subcommand not in the explicit allowlist. */
|
|
14
19
|
readonly E_GIT_BLOCKED: "Blocked git subcommand";
|
|
20
|
+
/** Relative path navigation escapes allowed root directory. */
|
|
15
21
|
readonly E_PATH_ESCAPE: "Path escapes allowed root";
|
|
16
22
|
};
|
|
17
23
|
/**
|
|
@@ -22,14 +28,18 @@ export type ScaffoldErrorCode = keyof typeof ERROR_CODES;
|
|
|
22
28
|
* Structural interface contract for errors thrown by the scaffolder.
|
|
23
29
|
*/
|
|
24
30
|
export interface ScaffoldErrorShape extends Error {
|
|
31
|
+
/** Error class discriminator name. */
|
|
25
32
|
name: 'ScaffoldError';
|
|
33
|
+
/** Machine-readable error code. */
|
|
26
34
|
code: ScaffoldErrorCode;
|
|
27
35
|
}
|
|
28
36
|
/**
|
|
29
37
|
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
30
38
|
*/
|
|
31
39
|
export declare class ScaffoldError extends Error implements ScaffoldErrorShape {
|
|
40
|
+
/** Error class name identifier. */
|
|
32
41
|
readonly name: 'ScaffoldError';
|
|
42
|
+
/** Machine-readable error code identifying failure cause. */
|
|
33
43
|
readonly code: ScaffoldErrorCode;
|
|
34
44
|
/**
|
|
35
45
|
* Constructs a new ScaffoldError instance.
|
|
@@ -41,11 +51,17 @@ export declare class ScaffoldError extends Error implements ScaffoldErrorShape {
|
|
|
41
51
|
}
|
|
42
52
|
declare const _default: {
|
|
43
53
|
ERROR_CODES: {
|
|
54
|
+
/** Target directory matches template repository root itself. */
|
|
44
55
|
readonly E_TARGET_IS_TEMPLATE: "Cannot scaffold into the azcodr template directory itself";
|
|
56
|
+
/** Target directory exists and already contains non-empty files without --force. */
|
|
45
57
|
readonly E_TARGET_NOT_EMPTY: "Target directory is not empty";
|
|
58
|
+
/** Target path matches protected system, home, or root directory. */
|
|
46
59
|
readonly E_TARGET_IS_PROTECTED: "Refusing to scaffold into a protected system directory";
|
|
60
|
+
/** runGit invoked with empty or missing argument array. */
|
|
47
61
|
readonly E_GIT_ARGS_INVALID: "runGit requires a non-empty argv array";
|
|
62
|
+
/** Attempted git subcommand not in the explicit allowlist. */
|
|
48
63
|
readonly E_GIT_BLOCKED: "Blocked git subcommand";
|
|
64
|
+
/** Relative path navigation escapes allowed root directory. */
|
|
49
65
|
readonly E_PATH_ESCAPE: "Path escapes allowed root";
|
|
50
66
|
};
|
|
51
67
|
ScaffoldError: typeof ScaffoldError;
|
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
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;IACtB,gEAAgE;;IAEhE,oFAAoF;;IAEpF,qEAAqE;;IAErE,2DAA2D;;IAE3D,8DAA8D;;IAE9D,+DAA+D;;CAEvD,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,WAAW,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,KAAK;IAC/C,sCAAsC;IACtC,IAAI,EAAE,eAAe,CAAC;IACtB,mCAAmC;IACnC,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAM,YAAW,kBAAkB;IACpE,mCAAmC;IACnC,SAAkB,IAAI,EAAE,eAAe,CAAmB;IAC1D,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAEjC;;;;;OAKG;gBACS,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAIrD;;;QAhDC,gEAAgE;;QAEhE,oFAAoF;;QAEpF,qEAAqE;;QAErE,2DAA2D;;QAE3D,8DAA8D;;QAE9D,+DAA+D;;;;;AAwCjE,wBAA8C"}
|
package/lib/errors.js
CHANGED
|
@@ -7,18 +7,26 @@
|
|
|
7
7
|
* tests/error-codes.test.js.
|
|
8
8
|
*/
|
|
9
9
|
export const ERROR_CODES = {
|
|
10
|
+
/** Target directory matches template repository root itself. */
|
|
10
11
|
E_TARGET_IS_TEMPLATE: 'Cannot scaffold into the azcodr template directory itself',
|
|
12
|
+
/** Target directory exists and already contains non-empty files without --force. */
|
|
11
13
|
E_TARGET_NOT_EMPTY: 'Target directory is not empty',
|
|
14
|
+
/** Target path matches protected system, home, or root directory. */
|
|
12
15
|
E_TARGET_IS_PROTECTED: 'Refusing to scaffold into a protected system directory',
|
|
16
|
+
/** runGit invoked with empty or missing argument array. */
|
|
13
17
|
E_GIT_ARGS_INVALID: 'runGit requires a non-empty argv array',
|
|
18
|
+
/** Attempted git subcommand not in the explicit allowlist. */
|
|
14
19
|
E_GIT_BLOCKED: 'Blocked git subcommand',
|
|
20
|
+
/** Relative path navigation escapes allowed root directory. */
|
|
15
21
|
E_PATH_ESCAPE: 'Path escapes allowed root'
|
|
16
22
|
};
|
|
17
23
|
/**
|
|
18
24
|
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
19
25
|
*/
|
|
20
26
|
export class ScaffoldError extends Error {
|
|
27
|
+
/** Error class name identifier. */
|
|
21
28
|
name = 'ScaffoldError';
|
|
29
|
+
/** Machine-readable error code identifying failure cause. */
|
|
22
30
|
code;
|
|
23
31
|
/**
|
|
24
32
|
* Constructs a new ScaffoldError instance.
|
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,gEAAgE;IAChE,oBAAoB,EAAE,2DAA2D;IACjF,oFAAoF;IACpF,kBAAkB,EAAE,+BAA+B;IACnD,qEAAqE;IACrE,qBAAqB,EAAE,wDAAwD;IAC/E,2DAA2D;IAC3D,kBAAkB,EAAE,wCAAwC;IAC5D,8DAA8D;IAC9D,aAAa,EAAE,wBAAwB;IACvC,+DAA+D;IAC/D,aAAa,EAAE,2BAA2B;CAClC,CAAC;AAiBX;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,mCAAmC;IACjB,IAAI,GAAoB,eAAe,CAAC;IAC1D,6DAA6D;IACpD,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/guards.d.ts
CHANGED
|
@@ -8,9 +8,13 @@ export declare function getTemplateDir(): string;
|
|
|
8
8
|
* Options for configuring protected target verification.
|
|
9
9
|
*/
|
|
10
10
|
export interface ProtectedTargetOptions {
|
|
11
|
+
/** Optional custom template directory path. */
|
|
11
12
|
templateDir?: string;
|
|
13
|
+
/** Force overwrite flag. */
|
|
12
14
|
force?: boolean;
|
|
15
|
+
/** Dry-run execution simulation flag. */
|
|
13
16
|
dryRun?: boolean;
|
|
17
|
+
/** Allow targeting protected directories (internal testing only). */
|
|
14
18
|
allowProtected?: boolean;
|
|
15
19
|
}
|
|
16
20
|
/**
|
package/lib/guards.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED;;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"}
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yCAAyC;IACzC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,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.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,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
|