azcodr 2.7.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/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/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 +3 -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/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 +21 -7
- package/src/validate.ts +17 -0
package/src/agent-guard-tdd.ts
CHANGED
|
@@ -1,18 +1,36 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Persistent state tracking test-first TDD progress across an agent session.
|
|
6
|
+
*/
|
|
4
7
|
export interface SessionTddState {
|
|
8
|
+
/** Whether a failing test execution (RED phase) has been recorded in the session. */
|
|
5
9
|
lastFailingTestRecorded: boolean;
|
|
10
|
+
/** Unix timestamp in milliseconds when the last test execution occurred. */
|
|
6
11
|
lastTestRunTime?: number;
|
|
12
|
+
/** File path of the most recently executed test file. */
|
|
7
13
|
lastTestPath?: string;
|
|
8
14
|
}
|
|
9
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Result of evaluating a file edit against RED-before-GREEN TDD rules.
|
|
18
|
+
*/
|
|
10
19
|
export interface TddCheckResult {
|
|
20
|
+
/** Whether the file edit is blocked due to missing failing test. */
|
|
11
21
|
blocked: boolean;
|
|
22
|
+
/** Explanatory reason if the operation is blocked. */
|
|
12
23
|
reason?: string;
|
|
24
|
+
/** Whether the target file was identified as production source code. */
|
|
13
25
|
isProductionFile: boolean;
|
|
14
26
|
}
|
|
15
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Identifies whether a given path is a unit or integration test file.
|
|
30
|
+
*
|
|
31
|
+
* @param filePath - File path to inspect.
|
|
32
|
+
* @returns True if path matches test directory or file extension patterns.
|
|
33
|
+
*/
|
|
16
34
|
export function isTestFile(filePath: string): boolean {
|
|
17
35
|
const norm = filePath.replace(/\\/g, '/').toLowerCase();
|
|
18
36
|
if (/(^|\/)(tests?|__tests__)(\/|$)/i.test(norm)) {
|
|
@@ -21,12 +39,24 @@ export function isTestFile(filePath: string): boolean {
|
|
|
21
39
|
return /\.(test|spec)\.[a-z0-9]+$/i.test(norm);
|
|
22
40
|
}
|
|
23
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Identifies whether a given path is a non-code file (markdown, json, yaml, images).
|
|
44
|
+
*
|
|
45
|
+
* @param filePath - File path to inspect.
|
|
46
|
+
* @returns True if file extension indicates non-code asset or configuration.
|
|
47
|
+
*/
|
|
24
48
|
export function isNonCodeFile(filePath: string): boolean {
|
|
25
49
|
const ext = path.extname(filePath).toLowerCase();
|
|
26
50
|
const nonCodeExts = new Set(['.md', '.json', '.yml', '.yaml', '.txt', '.toml', '.lock', '.svg', '.png']);
|
|
27
51
|
return nonCodeExts.has(ext);
|
|
28
52
|
}
|
|
29
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Identifies whether a given file path corresponds to production code under src/, lib/, or app/.
|
|
56
|
+
*
|
|
57
|
+
* @param filePath - File path to inspect.
|
|
58
|
+
* @returns True if path is production source code subject to RED-before-GREEN discipline.
|
|
59
|
+
*/
|
|
30
60
|
export function isProductionFile(filePath: string): boolean {
|
|
31
61
|
if (isNonCodeFile(filePath)) return false;
|
|
32
62
|
if (isTestFile(filePath)) return false;
|
|
@@ -34,6 +64,12 @@ export function isProductionFile(filePath: string): boolean {
|
|
|
34
64
|
return norm.includes('src/') || norm.includes('lib/') || norm.includes('app/');
|
|
35
65
|
}
|
|
36
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Loads session TDD tracking state from disk, defaulting to unrecorded state if missing.
|
|
69
|
+
*
|
|
70
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
71
|
+
* @returns Parsed SessionTddState object.
|
|
72
|
+
*/
|
|
37
73
|
export function readTddState(stateFile: string): SessionTddState {
|
|
38
74
|
if (!fs.existsSync(stateFile)) {
|
|
39
75
|
return { lastFailingTestRecorded: false };
|
|
@@ -46,6 +82,12 @@ export function readTddState(stateFile: string): SessionTddState {
|
|
|
46
82
|
}
|
|
47
83
|
}
|
|
48
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Persists session TDD state to disk with fail-safe error handling to avoid disrupting execution.
|
|
87
|
+
*
|
|
88
|
+
* @param stateFile - Path to the persistent session state JSON file.
|
|
89
|
+
* @param state - SessionTddState object to record.
|
|
90
|
+
*/
|
|
49
91
|
export function writeTddState(stateFile: string, state: SessionTddState): void {
|
|
50
92
|
try {
|
|
51
93
|
const dir = path.dirname(stateFile);
|
package/src/agent-guard.ts
CHANGED
|
@@ -10,20 +10,37 @@ import {
|
|
|
10
10
|
} from './agent-guard-tdd.js';
|
|
11
11
|
import type { SessionTddState } from './agent-guard-tdd.js';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Verdict returned by agent-runtime safety and architecture inspection guards.
|
|
15
|
+
*/
|
|
13
16
|
export interface GuardDecision {
|
|
17
|
+
/** Whether the requested tool operation is permitted. */
|
|
14
18
|
allowed: boolean;
|
|
19
|
+
/** Explanatory failure reason when the action is blocked. */
|
|
15
20
|
reason?: string;
|
|
21
|
+
/** Subsystem that produced the decision ('command', 'file', or 'tdd'). */
|
|
16
22
|
source?: 'command' | 'file' | 'tdd';
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Normalized representation of an agent tool invocation payload.
|
|
27
|
+
*/
|
|
19
28
|
export interface ToolEnvelope {
|
|
29
|
+
/** Name of the tool invoked by the agent. */
|
|
20
30
|
tool_name?: string;
|
|
31
|
+
/** Parameter payload passed to the tool invocation. */
|
|
21
32
|
tool_input?: Record<string, unknown>;
|
|
22
33
|
}
|
|
23
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Configuration options governing agent guard enforcement behavior.
|
|
37
|
+
*/
|
|
24
38
|
export interface GuardOptions {
|
|
39
|
+
/** Target workspace root directory (defaults to process.cwd()). */
|
|
25
40
|
workspaceRoot?: string;
|
|
41
|
+
/** When true, strictly mandates RED failing test before modifying production code. */
|
|
26
42
|
enforceTestFirst?: boolean;
|
|
43
|
+
/** Maximum non-overflow file line threshold before Refactor-Before-Add triggers. */
|
|
27
44
|
maxFileLines?: number;
|
|
28
45
|
}
|
|
29
46
|
|
package/src/boundaries.ts
CHANGED
|
@@ -1,25 +1,47 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Defines an architectural layer boundary rule disallowing imports from foreign layers.
|
|
6
|
+
*/
|
|
4
7
|
export interface BoundaryRule {
|
|
8
|
+
/** Name of the architectural layer (e.g., 'domain', 'core'). */
|
|
5
9
|
fromLayer: string;
|
|
10
|
+
/** Array of layer names that fromLayer is forbidden from importing. */
|
|
6
11
|
disallowImportsFrom: readonly string[];
|
|
7
12
|
}
|
|
8
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Represents an architectural boundary violation where a module imported a prohibited layer.
|
|
16
|
+
*/
|
|
9
17
|
export interface BoundaryViolation {
|
|
18
|
+
/** Path of the file containing the illegal import. */
|
|
10
19
|
file: string;
|
|
20
|
+
/** Path of the imported file that violates the rule. */
|
|
11
21
|
importedFile: string;
|
|
22
|
+
/** Origin layer of the importing file. */
|
|
12
23
|
fromLayer: string;
|
|
24
|
+
/** Target layer that was forbidden to import. */
|
|
13
25
|
toLayer: string;
|
|
14
26
|
}
|
|
15
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Report summarizing module count, detected circular cycles, and boundary violations.
|
|
30
|
+
*/
|
|
16
31
|
export interface BoundaryReport {
|
|
32
|
+
/** Total number of source modules scanned. */
|
|
17
33
|
moduleCount: number;
|
|
34
|
+
/** List of detected circular dependency cycles. */
|
|
18
35
|
cycles: string[][];
|
|
36
|
+
/** List of detected boundary violations. */
|
|
19
37
|
violations: BoundaryViolation[];
|
|
38
|
+
/** Whether the architecture is completely compliant (no cycles and no violations). */
|
|
20
39
|
ok: boolean;
|
|
21
40
|
}
|
|
22
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Canonical architectural boundary rules enforcing Hexagonal / Clean Architecture layer constraints.
|
|
44
|
+
*/
|
|
23
45
|
export const DEFAULT_BOUNDARY_RULES: readonly BoundaryRule[] = [
|
|
24
46
|
{
|
|
25
47
|
fromLayer: 'domain',
|
|
@@ -41,6 +63,13 @@ function isEligibleSource(name: string): boolean {
|
|
|
41
63
|
return !name.includes('.test.') && !name.includes('.spec.');
|
|
42
64
|
}
|
|
43
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Recursively discovers all eligible source files (.ts and .js) within a directory,
|
|
68
|
+
* ignoring skipped directories (e.g. node_modules, lib) and test files.
|
|
69
|
+
*
|
|
70
|
+
* @param dir - Root directory to search.
|
|
71
|
+
* @returns Sorted array of absolute file paths.
|
|
72
|
+
*/
|
|
44
73
|
export function findSourceFiles(dir: string): string[] {
|
|
45
74
|
if (!fs.existsSync(dir)) return [];
|
|
46
75
|
const results: string[] = [];
|
|
@@ -71,6 +100,12 @@ function resolveImportTarget(sourceFile: string, specifier: string): string | nu
|
|
|
71
100
|
return null;
|
|
72
101
|
}
|
|
73
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Scans a source file and extracts all local relative import and export paths.
|
|
105
|
+
*
|
|
106
|
+
* @param filePath - Absolute or relative path to the source file.
|
|
107
|
+
* @returns Sorted array of resolved local file paths imported or re-exported.
|
|
108
|
+
*/
|
|
74
109
|
export function extractLocalImports(filePath: string): string[] {
|
|
75
110
|
if (!fs.existsSync(filePath)) return [];
|
|
76
111
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
@@ -90,6 +125,12 @@ export function extractLocalImports(filePath: string): string[] {
|
|
|
90
125
|
return imports.sort();
|
|
91
126
|
}
|
|
92
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Constructs a dependency graph mapping each source file to its imported local files.
|
|
130
|
+
*
|
|
131
|
+
* @param files - Array of source file paths.
|
|
132
|
+
* @returns Map where keys are source file paths and values are arrays of imported local file paths.
|
|
133
|
+
*/
|
|
93
134
|
export function buildDependencyGraph(files: readonly string[]): Map<string, string[]> {
|
|
94
135
|
const graph = new Map<string, string[]>();
|
|
95
136
|
for (const file of files) {
|
|
@@ -98,6 +139,12 @@ export function buildDependencyGraph(files: readonly string[]): Map<string, stri
|
|
|
98
139
|
return graph;
|
|
99
140
|
}
|
|
100
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Analyzes a dependency graph using depth-first search to detect circular import cycles.
|
|
144
|
+
*
|
|
145
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
146
|
+
* @returns Array of cycle paths, where each cycle path is an array of file paths.
|
|
147
|
+
*/
|
|
101
148
|
export function detectDependencyCycles(graph: Map<string, string[]>): string[][] {
|
|
102
149
|
const cycles: string[][] = [];
|
|
103
150
|
const visited = new Set<string>();
|
|
@@ -135,6 +182,13 @@ function hasLayerSegment(pathStr: string, segment: string): boolean {
|
|
|
135
182
|
return new RegExp(`(^|[/\\\\])${segment}([/\\\\]|$)`, 'i').test(pathStr);
|
|
136
183
|
}
|
|
137
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Evaluates a dependency graph against architectural boundary rules to detect prohibited cross-layer imports.
|
|
187
|
+
*
|
|
188
|
+
* @param graph - Map of file paths to their imported dependency file paths.
|
|
189
|
+
* @param rules - Architectural boundary rules to enforce (defaults to DEFAULT_BOUNDARY_RULES).
|
|
190
|
+
* @returns Array of detected boundary violations.
|
|
191
|
+
*/
|
|
138
192
|
export function detectBoundaryViolations(
|
|
139
193
|
graph: Map<string, string[]>,
|
|
140
194
|
rules: readonly BoundaryRule[] = DEFAULT_BOUNDARY_RULES
|
package/src/errors.ts
CHANGED
|
@@ -7,11 +7,17 @@
|
|
|
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
|
} as const;
|
|
17
23
|
|
|
@@ -24,7 +30,9 @@ export type ScaffoldErrorCode = keyof typeof ERROR_CODES;
|
|
|
24
30
|
* Structural interface contract for errors thrown by the scaffolder.
|
|
25
31
|
*/
|
|
26
32
|
export interface ScaffoldErrorShape extends Error {
|
|
33
|
+
/** Error class discriminator name. */
|
|
27
34
|
name: 'ScaffoldError';
|
|
35
|
+
/** Machine-readable error code. */
|
|
28
36
|
code: ScaffoldErrorCode;
|
|
29
37
|
}
|
|
30
38
|
|
|
@@ -32,7 +40,9 @@ export interface ScaffoldErrorShape extends Error {
|
|
|
32
40
|
* Custom error class thrown by scaffolding operations, carrying a machine-readable code.
|
|
33
41
|
*/
|
|
34
42
|
export class ScaffoldError extends Error implements ScaffoldErrorShape {
|
|
43
|
+
/** Error class name identifier. */
|
|
35
44
|
override readonly name: 'ScaffoldError' = 'ScaffoldError';
|
|
45
|
+
/** Machine-readable error code identifying failure cause. */
|
|
36
46
|
readonly code: ScaffoldErrorCode;
|
|
37
47
|
|
|
38
48
|
/**
|
package/src/guards.ts
CHANGED
|
@@ -19,9 +19,13 @@ export function getTemplateDir(): string {
|
|
|
19
19
|
* Options for configuring protected target verification.
|
|
20
20
|
*/
|
|
21
21
|
export interface ProtectedTargetOptions {
|
|
22
|
+
/** Optional custom template directory path. */
|
|
22
23
|
templateDir?: string;
|
|
24
|
+
/** Force overwrite flag. */
|
|
23
25
|
force?: boolean;
|
|
26
|
+
/** Dry-run execution simulation flag. */
|
|
24
27
|
dryRun?: boolean;
|
|
28
|
+
/** Allow targeting protected directories (internal testing only). */
|
|
25
29
|
allowProtected?: boolean;
|
|
26
30
|
}
|
|
27
31
|
|
package/src/links.ts
CHANGED
|
@@ -5,9 +5,13 @@ import path from 'node:path';
|
|
|
5
5
|
* Configuration options for symlink and pointer creation.
|
|
6
6
|
*/
|
|
7
7
|
export interface EnsureSymlinkOptions {
|
|
8
|
+
/** Target directory containing the files and proposed link. */
|
|
8
9
|
targetDir: string;
|
|
10
|
+
/** Name of the symbolic link or alias pointer file to create. */
|
|
9
11
|
linkName: string;
|
|
12
|
+
/** Name of the target file that the symlink or pointer points to. */
|
|
10
13
|
targetFileName: string;
|
|
14
|
+
/** When true, simulate link creation without disk mutations. */
|
|
11
15
|
dryRun?: boolean;
|
|
12
16
|
}
|
|
13
17
|
|
package/src/repo.ts
CHANGED
|
@@ -9,7 +9,9 @@ const INITIAL_COMMIT_MESSAGE = 'chore: initial scaffold from azcodr template';
|
|
|
9
9
|
* Options controlling git repository initialization.
|
|
10
10
|
*/
|
|
11
11
|
export interface InitGitOptions {
|
|
12
|
+
/** If true, skip git repository initialization entirely. */
|
|
12
13
|
noGit?: boolean;
|
|
14
|
+
/** If true, simulate git repository initialization without invoking git. */
|
|
13
15
|
dryRun?: boolean;
|
|
14
16
|
}
|
|
15
17
|
|
package/src/scaffold.ts
CHANGED
|
@@ -34,11 +34,17 @@ export const TEMPLATE_ITEMS: readonly string[] = [
|
|
|
34
34
|
* Configuration options for the primary scaffold orchestration function.
|
|
35
35
|
*/
|
|
36
36
|
export interface ScaffoldOptions {
|
|
37
|
+
/** Target directory path where project will be scaffolded (defaults to process.cwd()). */
|
|
37
38
|
targetDir?: string;
|
|
39
|
+
/** Force overwrite if target directory exists and is non-empty. */
|
|
38
40
|
force?: boolean;
|
|
41
|
+
/** Skip git repository initialization. */
|
|
39
42
|
noGit?: boolean;
|
|
43
|
+
/** Optional custom template directory path. */
|
|
40
44
|
templateDir?: string;
|
|
45
|
+
/** Simulate scaffolding without writing files to disk. */
|
|
41
46
|
dryRun?: boolean;
|
|
47
|
+
/** Suppress non-error console output. */
|
|
42
48
|
silent?: boolean;
|
|
43
49
|
}
|
|
44
50
|
|
|
@@ -46,10 +52,15 @@ export interface ScaffoldOptions {
|
|
|
46
52
|
* Result object returned upon completion of a scaffold operation.
|
|
47
53
|
*/
|
|
48
54
|
export interface ScaffoldResult {
|
|
55
|
+
/** Whether the scaffolding operation completed successfully. */
|
|
49
56
|
success: boolean;
|
|
57
|
+
/** Absolute filesystem path of the scaffolded target directory. */
|
|
50
58
|
targetDir: string;
|
|
59
|
+
/** Whether a git repository was initialized and committed. */
|
|
51
60
|
gitInitialized: boolean;
|
|
61
|
+
/** Whether execution was a dry-run simulation without disk mutations. */
|
|
52
62
|
dryRun: boolean;
|
|
63
|
+
/** List of recorded scaffolding action descriptions taken. */
|
|
53
64
|
actions: string[];
|
|
54
65
|
}
|
|
55
66
|
|
|
@@ -57,9 +68,13 @@ export interface ScaffoldResult {
|
|
|
57
68
|
* Options controlling pre-scaffold target directory validation.
|
|
58
69
|
*/
|
|
59
70
|
export interface ValidateTargetOptions {
|
|
71
|
+
/** Custom template root directory path. */
|
|
60
72
|
templateDir?: string;
|
|
73
|
+
/** Allow non-empty directory when force is true. */
|
|
61
74
|
force?: boolean;
|
|
75
|
+
/** Simulate validation checks without erroring on non-empty targets. */
|
|
62
76
|
dryRun?: boolean;
|
|
77
|
+
/** Allow targeting protected directories (internal testing only). */
|
|
63
78
|
allowProtected?: boolean;
|
|
64
79
|
}
|
|
65
80
|
|
|
@@ -67,10 +82,10 @@ export interface ValidateTargetOptions {
|
|
|
67
82
|
* Options controlling template file copying and file generation.
|
|
68
83
|
*/
|
|
69
84
|
export interface CopyTemplateOptions {
|
|
85
|
+
/** Simulate copying without disk mutations. */
|
|
70
86
|
dryRun?: boolean;
|
|
71
87
|
}
|
|
72
88
|
|
|
73
|
-
|
|
74
89
|
function rejectTemplateSelf(resolvedTarget: string, resolvedTemplate: string): void {
|
|
75
90
|
if (resolvedTarget !== resolvedTemplate) return;
|
|
76
91
|
throw new ScaffoldError(
|
|
@@ -253,11 +268,8 @@ export function copyTemplate(
|
|
|
253
268
|
*/
|
|
254
269
|
export function scaffold(options: ScaffoldOptions = {}): ScaffoldResult {
|
|
255
270
|
const {
|
|
256
|
-
targetDir = process.cwd(),
|
|
257
|
-
|
|
258
|
-
noGit = false,
|
|
259
|
-
templateDir = getTemplateDir(),
|
|
260
|
-
dryRun = false
|
|
271
|
+
targetDir = process.cwd(), force = false,
|
|
272
|
+
noGit = false, templateDir = getTemplateDir(), dryRun = false
|
|
261
273
|
} = options;
|
|
262
274
|
const resolvedTarget = path.resolve(targetDir);
|
|
263
275
|
validateTarget(resolvedTarget, { templateDir, force, dryRun });
|
|
@@ -272,9 +284,11 @@ export {
|
|
|
272
284
|
makeScriptsExecutable, isInsideGitWorkTree, initGit, runGit,
|
|
273
285
|
assertInside, ScaffoldError, ERROR_CODES, isProtectedTarget
|
|
274
286
|
};
|
|
275
|
-
|
|
276
287
|
export type { EnsureSymlinkOptions, InitGitOptions, ScaffoldErrorCode, ScaffoldErrorShape };
|
|
277
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Unified azcodr scaffolding functions, guards, utilities, and constants module.
|
|
291
|
+
*/
|
|
278
292
|
export default {
|
|
279
293
|
scaffold, validateTarget, copyTemplate, ensureSymlink,
|
|
280
294
|
ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable,
|
package/src/validate.ts
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Tally and results returned by the architecture governance validator.
|
|
6
|
+
*/
|
|
4
7
|
export interface ValidationResult {
|
|
8
|
+
/** Total count of fatal governance errors encountered. */
|
|
5
9
|
errors: number;
|
|
10
|
+
/** Total count of non-fatal governance warnings encountered. */
|
|
6
11
|
warnings: number;
|
|
12
|
+
/** Number of progressive disclosure domain rule files verified. */
|
|
7
13
|
validatedRules: number;
|
|
14
|
+
/** Number of agent skills verified under .agents/skills/. */
|
|
8
15
|
validatedSkills: number;
|
|
16
|
+
/** Total count of internal markdown links verified. */
|
|
9
17
|
totalLinks: number;
|
|
18
|
+
/** List of broken link targets detected across workspace markdown files. */
|
|
10
19
|
brokenLinks: string[];
|
|
11
20
|
}
|
|
12
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Pluggable reporter interface receiving live validation events.
|
|
24
|
+
*/
|
|
13
25
|
export interface ValidationReporter {
|
|
26
|
+
/** Called when a check passes. */
|
|
14
27
|
pass: (msg: string) => void;
|
|
28
|
+
/** Called when a non-fatal warning is raised. */
|
|
15
29
|
warn: (msg: string) => void;
|
|
30
|
+
/** Called when a validation check fails. */
|
|
16
31
|
fail: (msg: string) => void;
|
|
32
|
+
/** Called for informative messages and section spacing. */
|
|
17
33
|
log: (msg: string) => void;
|
|
34
|
+
/** Called when a new validation phase begins. */
|
|
18
35
|
heading: (msg: string) => void;
|
|
19
36
|
}
|
|
20
37
|
|