azcodr 1.5.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.agents/hooks.json +42 -42
  2. package/.agents/hooks.json.example +42 -42
  3. package/.agents/mcp_config.json.example +29 -29
  4. package/.agents/scripts/safety_guard.sh +143 -34
  5. package/.agents/scripts/verify_completion.sh +90 -27
  6. package/.agents/skills/agentic-architect/SKILL.md +125 -125
  7. package/.agents/skills/agentic-architect/references/agents_md_template.md +62 -62
  8. package/.agents/skills/agentic-architect/references/refinement_workflow.md +32 -32
  9. package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +63 -63
  10. package/.agents/skills/agentic-architect/references/skill_template.md +56 -56
  11. package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +402 -402
  12. package/.agents/skills/clean-code-refactor/SKILL.md +91 -91
  13. package/.agents/skills/clean-code-refactor/references/clean_code_smells.md +27 -27
  14. package/.agents/skills/clean-code-refactor/references/design_patterns_ts.md +65 -65
  15. package/.agents/skills/compliance-audit/SKILL.md +120 -120
  16. package/.agents/skills/compliance-audit/references/owasp_top10_controls.md +16 -16
  17. package/.agents/skills/compliance-audit/references/soc2_iso_controls.md +28 -28
  18. package/.agents/skills/lets-build/SKILL.md +173 -173
  19. package/.agents/skills/lets-build/references/architecture_interview_matrix.md +115 -115
  20. package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +160 -160
  21. package/.agents/skills/lets-build/references/project_readme_template.md +79 -79
  22. package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +419 -255
  23. package/.agents/skills/product-analyst/SKILL.md +154 -154
  24. package/.agents/skills/product-analyst/references/backlog_ordering_techniques.md +107 -107
  25. package/.agents/skills/product-analyst/references/gherkin_patterns.md +46 -46
  26. package/.agents/skills/product-analyst/references/invest_checklist.md +38 -38
  27. package/.agents/skills/product-analyst/references/okr_alignment_guide.md +76 -76
  28. package/.agents/skills/product-analyst/references/smart_tasks.md +59 -59
  29. package/.agents/skills/relentless-questioner/SKILL.md +128 -128
  30. package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +102 -102
  31. package/.editorconfig +19 -19
  32. package/.github/workflows/ci.yml +167 -78
  33. package/.github/workflows/publish.yml +196 -0
  34. package/.gitignore +40 -25
  35. package/AGENTS.md +103 -102
  36. package/LICENSE +21 -21
  37. package/README.md +168 -165
  38. package/bin/azcodr.js +19 -228
  39. package/docs/knowledge/ubiquitous_language.md +31 -18
  40. package/docs/rules/agentic_configuration.md +259 -259
  41. package/docs/rules/api_architecture.md +179 -179
  42. package/docs/rules/authentication.md +76 -76
  43. package/docs/rules/authorization.md +75 -75
  44. package/docs/rules/caching.md +69 -69
  45. package/docs/rules/clean_code.md +62 -62
  46. package/docs/rules/cloud_native.md +41 -41
  47. package/docs/rules/cqrs.md +203 -203
  48. package/docs/rules/database_design.md +125 -125
  49. package/docs/rules/database_operations.md +69 -69
  50. package/docs/rules/design_patterns.md +98 -98
  51. package/docs/rules/devops_ci_cd.md +76 -76
  52. package/docs/rules/domain_driven_design.md +122 -122
  53. package/docs/rules/error_handling.md +54 -52
  54. package/docs/rules/feature_flags.md +59 -59
  55. package/docs/rules/frontend_architecture.md +157 -157
  56. package/docs/rules/multitenancy_architecture.md +98 -98
  57. package/docs/rules/product_ownership.md +127 -127
  58. package/docs/rules/project_management.md +49 -49
  59. package/docs/rules/relentless_questioning.md +52 -52
  60. package/docs/rules/requirements_engineering.md +98 -98
  61. package/docs/rules/security_compliance.md +53 -53
  62. package/docs/rules/server_driven_ui.md +88 -88
  63. package/docs/rules/test_driven_development.md +185 -185
  64. package/docs/rules/transactional_email.md +27 -27
  65. package/docs/rules/type_safety.md +65 -65
  66. package/docs/rules/ui_ux_architecture.md +150 -150
  67. package/docs/rules/workflow_state_machines.md +117 -117
  68. package/lib/cli-parse.d.ts +32 -0
  69. package/lib/cli-parse.d.ts.map +1 -0
  70. package/lib/cli-parse.js +55 -0
  71. package/lib/cli-parse.js.map +1 -0
  72. package/lib/cli-target.d.ts +66 -0
  73. package/lib/cli-target.d.ts.map +1 -0
  74. package/lib/cli-target.js +102 -0
  75. package/lib/cli-target.js.map +1 -0
  76. package/lib/cli.d.ts +40 -0
  77. package/lib/cli.d.ts.map +1 -0
  78. package/lib/cli.js +166 -0
  79. package/lib/cli.js.map +1 -0
  80. package/lib/errors.d.ts +39 -0
  81. package/lib/errors.d.ts.map +1 -0
  82. package/lib/errors.js +26 -0
  83. package/lib/errors.js.map +1 -0
  84. package/lib/git.d.ts +15 -0
  85. package/lib/git.d.ts.map +1 -0
  86. package/lib/git.js +32 -0
  87. package/lib/git.js.map +1 -0
  88. package/lib/guards.d.ts +35 -0
  89. package/lib/guards.d.ts.map +1 -0
  90. package/lib/guards.js +95 -0
  91. package/lib/guards.js.map +1 -0
  92. package/lib/index.d.ts +6 -134
  93. package/lib/index.d.ts.map +1 -0
  94. package/lib/index.js +4 -5
  95. package/lib/index.js.map +1 -0
  96. package/lib/links.d.ts +28 -0
  97. package/lib/links.d.ts.map +1 -0
  98. package/lib/links.js +129 -0
  99. package/lib/links.js.map +1 -0
  100. package/lib/permissions.d.ts +9 -0
  101. package/lib/permissions.d.ts.map +1 -0
  102. package/lib/permissions.js +44 -0
  103. package/lib/permissions.js.map +1 -0
  104. package/lib/repo.d.ts +20 -0
  105. package/lib/repo.d.ts.map +1 -0
  106. package/lib/repo.js +92 -0
  107. package/lib/repo.js.map +1 -0
  108. package/lib/scaffold.d.ts +80 -0
  109. package/lib/scaffold.d.ts.map +1 -0
  110. package/lib/scaffold.js +201 -448
  111. package/lib/scaffold.js.map +1 -0
  112. package/memory.md +135 -36
  113. package/package.json +75 -62
  114. package/scripts/test_coverage.js +66 -38
  115. package/scripts/validate/adr.js +155 -0
  116. package/scripts/validate/io.js +82 -0
  117. package/scripts/validate/links.js +166 -0
  118. package/scripts/validate/parity.js +122 -0
  119. package/scripts/validate/root.js +183 -0
  120. package/scripts/validate/rules.js +42 -0
  121. package/scripts/validate/skills.js +94 -0
  122. package/scripts/validate/text.js +27 -0
  123. package/scripts/validate-cli.js +12 -0
  124. package/scripts/validate.js +158 -258
  125. package/src/cli-parse.ts +77 -0
  126. package/src/cli-target.ts +167 -0
  127. package/src/cli.ts +240 -0
  128. package/src/errors.ts +35 -0
  129. package/src/git.ts +34 -0
  130. package/src/guards.ts +101 -0
  131. package/src/index.ts +39 -0
  132. package/src/links.ts +139 -0
  133. package/src/permissions.ts +42 -0
  134. package/src/repo.ts +94 -0
  135. package/src/scaffold.ts +273 -0
  136. package/.github/copilot-instructions.md +0 -1
package/lib/guards.js ADDED
@@ -0,0 +1,95 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import process from 'node:process';
5
+ import { ScaffoldError, ERROR_CODES } from './errors.js';
6
+ import { getTemplateDir } from './scaffold.js';
7
+ /**
8
+ * Filesystem scope guard (Supply Chain: filesystem access).
9
+ * Constrains all reads/writes to targetDir / templateDir.
10
+ */
11
+ export function assertInside(root, candidate, message) {
12
+ const resolvedRoot = path.resolve(root);
13
+ const resolvedCandidate = path.resolve(root, candidate);
14
+ const relative = path.relative(resolvedRoot, resolvedCandidate);
15
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
16
+ throw new ScaffoldError('E_PATH_ESCAPE', message || `${ERROR_CODES.E_PATH_ESCAPE}: ${candidate}`);
17
+ }
18
+ }
19
+ /**
20
+ * Normalizes a path for protected-target comparison. On Windows the filesystem
21
+ * is case-insensitive, so `C:\Users\Name` and `c:\users\name` are the same
22
+ * directory and must compare equal.
23
+ */
24
+ export function normalizeForComparison(p) {
25
+ const resolved = path.resolve(p);
26
+ return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
27
+ }
28
+ function readHomeDir() {
29
+ try {
30
+ return os.homedir();
31
+ }
32
+ catch {
33
+ return '';
34
+ }
35
+ }
36
+ function isFilesystemRoot(resolvedTarget) {
37
+ return resolvedTarget === path.parse(resolvedTarget).root;
38
+ }
39
+ function isHomeOrParent(normalizedTarget, home) {
40
+ if (!home)
41
+ return false;
42
+ if (normalizedTarget === normalizeForComparison(home))
43
+ return true;
44
+ const parent = path.dirname(path.resolve(home));
45
+ return normalizedTarget === normalizeForComparison(parent);
46
+ }
47
+ function isTemplateAncestor(resolvedTarget, templateDir) {
48
+ const resolvedTemplate = path.resolve(templateDir);
49
+ const relative = path.relative(resolvedTarget, resolvedTemplate);
50
+ return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);
51
+ }
52
+ function resolvesToProtectedLocation(resolvedTarget, home) {
53
+ // Symlink alias: a symlink to / or ~ must not bypass the lexical checks.
54
+ let real = '';
55
+ try {
56
+ if (!fs.existsSync(resolvedTarget))
57
+ return false;
58
+ real = fs.realpathSync(resolvedTarget);
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ if (real === path.parse(real).root)
64
+ return true;
65
+ return Boolean(home) && normalizeForComparison(real) === normalizeForComparison(home);
66
+ }
67
+ /**
68
+ * Returns true when `targetDir` is a location the scaffolder must never write
69
+ * into: the filesystem root, the user's home directory, the home directory's
70
+ * parent (e.g. /home, C:\Users -- scaffolding there affects every user), or an
71
+ * ancestor of the template itself (scaffolding into D:\projects would merge
72
+ * the template into its own parent).
73
+ *
74
+ * Lexical comparison is not enough: a symlink pointing at home must also be
75
+ * caught, so an existing target is resolved with realpath before comparing.
76
+ */
77
+ export function isProtectedTarget(targetDir, options = {}) {
78
+ const resolvedTarget = path.resolve(targetDir);
79
+ const normalizedTarget = normalizeForComparison(resolvedTarget);
80
+ if (isFilesystemRoot(resolvedTarget))
81
+ return true;
82
+ const home = readHomeDir();
83
+ if (isHomeOrParent(normalizedTarget, home))
84
+ return true;
85
+ const { templateDir = getTemplateDir() } = options;
86
+ if (isTemplateAncestor(resolvedTarget, templateDir))
87
+ return true;
88
+ return resolvesToProtectedLocation(resolvedTarget, home);
89
+ }
90
+ export default {
91
+ assertInside,
92
+ normalizeForComparison,
93
+ isProtectedTarget
94
+ };
95
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -1,134 +1,6 @@
1
- /**
2
- * Enterprise Multi-Tenant Architecture & Agentic Engineering Starter Template
3
- * Programmatic API Definitions
4
- */
5
-
6
- export interface ScaffoldOptions {
7
- /** Target directory path where template should be scaffolded (default: process.cwd()) */
8
- targetDir?: string;
9
- /** Force overwrite if target directory is non-empty (default: false) */
10
- force?: boolean;
11
- /** Skip git repository initialization (default: false) */
12
- noGit?: boolean;
13
- /** Custom template root directory (default: azcodr root) */
14
- templateDir?: string;
15
- /** Simulate scaffolding without writing files or running git (default: false) */
16
- dryRun?: boolean;
17
- /** Suppress console output messages (default: false) */
18
- silent?: boolean;
19
- }
20
-
21
- export interface ScaffoldResult {
22
- /** Whether the scaffolding succeeded */
23
- success: boolean;
24
- /** Absolute resolved path of the target directory */
25
- targetDir: string;
26
- /** Whether git init was successfully executed */
27
- gitInitialized: boolean;
28
- /** Whether execution ran in dry-run simulation mode */
29
- dryRun: boolean;
30
- /** List of files, directories, and symlinks created or simulated */
31
- actions: string[];
32
- }
33
-
34
- export interface ValidateTargetOptions {
35
- /** Custom template root directory */
36
- templateDir?: string;
37
- /** Force allow non-empty directory */
38
- force?: boolean;
39
- }
40
-
41
- export interface InitGitOptions {
42
- /** If true, skips git initialization */
43
- noGit?: boolean;
44
- /** If true, simulates git initialization without executing */
45
- dryRun?: boolean;
46
- }
47
-
48
- export interface CopyTemplateOptions {
49
- /** If true, simulates copy without writing to disk */
50
- dryRun?: boolean;
51
- }
52
-
53
- /**
54
- * High-level orchestration function to scaffold the azcodr workspace into targetDir.
55
- */
56
- export function scaffold(options?: ScaffoldOptions): ScaffoldResult;
57
-
58
- /**
59
- * Validates the target directory to ensure it is suitable for scaffolding.
60
- */
61
- export function validateTarget(targetDir: string, options?: ValidateTargetOptions): void;
62
-
63
- /**
64
- * Copies template items into target directory and sets up symlinks and permissions.
65
- */
66
- export function copyTemplate(
67
- targetDir: string,
68
- templateDir?: string,
69
- options?: CopyTemplateOptions
70
- ): string[];
71
-
72
- /**
73
- * Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
74
- */
75
- export function ensureSymlink(
76
- targetDir: string,
77
- linkName: string,
78
- targetFileName: string,
79
- dryRun?: boolean
80
- ): boolean;
81
-
82
- /**
83
- * Creates a symlink, falling back to a text pointer (not a full copy).
84
- */
85
- export function ensureSymlinkOrPointer(
86
- targetDir: string,
87
- linkName: string,
88
- targetFileName: string,
89
- dryRun?: boolean
90
- ): boolean;
91
-
92
- /**
93
- * Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
94
- */
95
- export function isSameCaseInsensitiveFile(
96
- targetDir: string,
97
- linkName: string,
98
- targetFileName: string
99
- ): boolean;
100
-
101
- /**
102
- * Ensures all bash scripts in skill directories have executable permissions (0o755).
103
- */
104
- export function makeScriptsExecutable(targetDir: string, dryRun?: boolean): string[];
105
-
106
- /**
107
- * Initializes a git repository in the target directory if not already inside one.
108
- */
109
- export function initGit(targetDir: string, options?: InitGitOptions): boolean;
110
-
111
- /**
112
- * Returns the root path to the azcodr template files.
113
- */
114
- export function getTemplateDir(): string;
115
-
116
- /**
117
- * Array of essential template files and directories copied during scaffolding.
118
- */
119
- export const TEMPLATE_ITEMS: readonly string[];
120
-
121
- declare const defaultExport: {
122
- scaffold: typeof scaffold;
123
- validateTarget: typeof validateTarget;
124
- copyTemplate: typeof copyTemplate;
125
- ensureSymlink: typeof ensureSymlink;
126
- ensureSymlinkOrPointer: typeof ensureSymlinkOrPointer;
127
- isSameCaseInsensitiveFile: typeof isSameCaseInsensitiveFile;
128
- makeScriptsExecutable: typeof makeScriptsExecutable;
129
- initGit: typeof initGit;
130
- getTemplateDir: typeof getTemplateDir;
131
- TEMPLATE_ITEMS: typeof TEMPLATE_ITEMS;
132
- };
133
-
134
- export default defaultExport;
1
+ 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';
2
+ export { scaffold, validateTarget, copyTemplate, ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, initGit, isInsideGitWorkTree, runGit, assertInside, isProtectedTarget, getTemplateDir, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES } from './scaffold.js';
3
+ export type { ScaffoldOptions, ScaffoldResult, ValidateTargetOptions, CopyTemplateOptions, EnsureSymlinkOptions, InitGitOptions, ScaffoldErrorShape } from './scaffold.js';
4
+ import scaffoldModule from './scaffold.js';
5
+ export default scaffoldModule;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAC3C,eAAe,cAAc,CAAC"}
package/lib/index.js CHANGED
@@ -1,5 +1,4 @@
1
- 'use strict';
2
-
3
- const scaffold = require('./scaffold.js');
4
-
5
- module.exports = scaffold;
1
+ export { scaffold, validateTarget, copyTemplate, ensureSymlink, ensureSymlinkOrPointer, isSameCaseInsensitiveFile, makeScriptsExecutable, initGit, isInsideGitWorkTree, runGit, assertInside, isProtectedTarget, getTemplateDir, TEMPLATE_ITEMS, ScaffoldError, ERROR_CODES } from './scaffold.js';
2
+ import scaffoldModule from './scaffold.js';
3
+ export default scaffoldModule;
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,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;AAYvB,OAAO,cAAc,MAAM,eAAe,CAAC;AAC3C,eAAe,cAAc,CAAC"}
package/lib/links.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ export interface EnsureSymlinkOptions {
2
+ targetDir: string;
3
+ linkName: string;
4
+ targetFileName: string;
5
+ dryRun?: boolean;
6
+ }
7
+ /**
8
+ * Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
9
+ * Uses exact directory listing (not existsSync, which lies on case-insensitive systems).
10
+ */
11
+ export declare function isSameCaseInsensitiveFile(targetDir: string, linkName: string, targetFileName: string): boolean;
12
+ /**
13
+ * Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
14
+ */
15
+ export declare function ensureSymlink(options: EnsureSymlinkOptions): boolean;
16
+ /**
17
+ * Creates a symlink, falling back to a text pointer (not a full copy).
18
+ * Used for .github/copilot-instructions.md where a full AGENTS.md copy would
19
+ * break relative markdown links (they resolve from .github/, not root).
20
+ */
21
+ export declare function ensureSymlinkOrPointer(options: EnsureSymlinkOptions): boolean;
22
+ declare const _default: {
23
+ isSameCaseInsensitiveFile: typeof isSameCaseInsensitiveFile;
24
+ ensureSymlink: typeof ensureSymlink;
25
+ ensureSymlinkOrPointer: typeof ensureSymlinkOrPointer;
26
+ };
27
+ export default _default;
28
+ //# sourceMappingURL=links.d.ts.map
@@ -0,0 +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;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,OAAO,CAWT;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAapE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAmB7E;;;;;;AAED,wBAIE"}
package/lib/links.js ADDED
@@ -0,0 +1,129 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ function namesDifferOnlyByCase(linkName, targetFileName) {
4
+ if (linkName.toLowerCase() !== targetFileName.toLowerCase())
5
+ return false;
6
+ return linkName !== targetFileName;
7
+ }
8
+ function readDirEntries(targetDir) {
9
+ try {
10
+ return fs.readdirSync(targetDir);
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ }
16
+ function bothEntriesExist(options) {
17
+ const { targetDir, linkName, targetFileName, entries } = options;
18
+ if (!entries.includes(targetFileName) || !entries.includes(linkName))
19
+ return false;
20
+ try {
21
+ fs.lstatSync(path.join(targetDir, targetFileName));
22
+ fs.lstatSync(path.join(targetDir, linkName));
23
+ return true;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ function accessiblePair(targetPath, linkPath) {
30
+ if (!fs.existsSync(targetPath) || !fs.existsSync(linkPath))
31
+ return false;
32
+ try {
33
+ fs.lstatSync(targetPath);
34
+ fs.lstatSync(linkPath);
35
+ return true;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ function removeIfExists(linkPath) {
42
+ try {
43
+ fs.lstatSync(linkPath);
44
+ fs.rmSync(linkPath, { force: true });
45
+ }
46
+ catch {
47
+ // Path does not exist, proceed
48
+ }
49
+ }
50
+ function copyFallback(targetDir, linkName, targetFileName) {
51
+ const sourceFile = path.resolve(targetDir, targetFileName);
52
+ if (fs.existsSync(sourceFile)) {
53
+ fs.copyFileSync(sourceFile, path.join(targetDir, linkName));
54
+ }
55
+ }
56
+ /**
57
+ * Detects whether linkName and targetFileName refer to the same entry on a case-insensitive filesystem.
58
+ * Uses exact directory listing (not existsSync, which lies on case-insensitive systems).
59
+ */
60
+ export function isSameCaseInsensitiveFile(targetDir, linkName, targetFileName) {
61
+ if (linkName === targetFileName)
62
+ return true;
63
+ if (!namesDifferOnlyByCase(linkName, targetFileName))
64
+ return false;
65
+ const entries = readDirEntries(targetDir);
66
+ if (entries === null)
67
+ return false;
68
+ if (bothEntriesExist({ targetDir, linkName, targetFileName, entries })) {
69
+ return !fs.lstatSync(path.join(targetDir, linkName)).isSymbolicLink();
70
+ }
71
+ const targetPath = path.join(targetDir, targetFileName);
72
+ const linkPath = path.join(targetDir, linkName);
73
+ return accessiblePair(targetPath, linkPath);
74
+ }
75
+ /**
76
+ * Safely creates or updates a symbolic link, falling back to a file copy if symlinks are unsupported.
77
+ */
78
+ export function ensureSymlink(options) {
79
+ const { targetDir, linkName, targetFileName, dryRun = false } = options;
80
+ if (dryRun)
81
+ return true;
82
+ if (isSameCaseInsensitiveFile(targetDir, linkName, targetFileName))
83
+ return true;
84
+ const linkPath = path.join(targetDir, linkName);
85
+ removeIfExists(linkPath);
86
+ try {
87
+ fs.symlinkSync(targetFileName, linkPath, 'file');
88
+ return true;
89
+ }
90
+ catch {
91
+ copyFallback(targetDir, linkName, targetFileName);
92
+ return true;
93
+ }
94
+ }
95
+ /**
96
+ * Creates a symlink, falling back to a text pointer (not a full copy).
97
+ * Used for .github/copilot-instructions.md where a full AGENTS.md copy would
98
+ * break relative markdown links (they resolve from .github/, not root).
99
+ */
100
+ export function ensureSymlinkOrPointer(options) {
101
+ const { targetDir, linkName, targetFileName, dryRun = false } = options;
102
+ if (dryRun)
103
+ return true;
104
+ const linkPath = path.join(targetDir, linkName);
105
+ try {
106
+ try {
107
+ fs.lstatSync(linkPath);
108
+ const existing = fs.existsSync(linkPath) ? fs.readFileSync(linkPath, 'utf-8') : '';
109
+ if (existing.trim() === targetFileName)
110
+ return true;
111
+ fs.rmSync(linkPath, { force: true });
112
+ }
113
+ catch {
114
+ // Path does not exist, proceed
115
+ }
116
+ fs.symlinkSync(targetFileName, linkPath, 'file');
117
+ return true;
118
+ }
119
+ catch {
120
+ fs.writeFileSync(linkPath, `${targetFileName}\n`, 'utf-8');
121
+ return true;
122
+ }
123
+ }
124
+ export default {
125
+ isSameCaseInsensitiveFile,
126
+ ensureSymlink,
127
+ ensureSymlinkOrPointer
128
+ };
129
+ //# sourceMappingURL=links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Ensures all bash scripts in agent and skill directories have executable permissions (0o755).
3
+ */
4
+ export declare function makeScriptsExecutable(targetDir: string, dryRun?: boolean): string[];
5
+ declare const _default: {
6
+ makeScriptsExecutable: typeof makeScriptsExecutable;
7
+ };
8
+ export default _default;
9
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAyBA;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,EAAE,CAWjF;;;;AAED,wBAAyC"}
@@ -0,0 +1,44 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ function chmodShFile(filePath, dryRun) {
4
+ if (dryRun)
5
+ return;
6
+ try {
7
+ fs.chmodSync(filePath, 0o755);
8
+ }
9
+ catch {
10
+ // Non-critical if filesystem does not support POSIX permissions
11
+ }
12
+ }
13
+ function chmodShFilesIn(scriptsDir, dryRun) {
14
+ const modified = [];
15
+ if (!fs.existsSync(scriptsDir) || !fs.statSync(scriptsDir).isDirectory())
16
+ return modified;
17
+ const files = fs.readdirSync(scriptsDir);
18
+ for (const file of files) {
19
+ if (!file.endsWith('.sh'))
20
+ continue;
21
+ const filePath = path.join(scriptsDir, file);
22
+ modified.push(filePath);
23
+ chmodShFile(filePath, dryRun);
24
+ }
25
+ return modified;
26
+ }
27
+ /**
28
+ * Ensures all bash scripts in agent and skill directories have executable permissions (0o755).
29
+ */
30
+ export function makeScriptsExecutable(targetDir, dryRun = false) {
31
+ const agentScriptsDir = path.join(targetDir, '.agents', 'scripts');
32
+ const modified = chmodShFilesIn(agentScriptsDir, dryRun);
33
+ const skillsDir = path.join(targetDir, '.agents', 'skills');
34
+ if (!fs.existsSync(skillsDir))
35
+ return modified;
36
+ const skills = fs.readdirSync(skillsDir);
37
+ for (const skill of skills) {
38
+ const scriptsDir = path.join(skillsDir, skill, 'scripts');
39
+ modified.push(...chmodShFilesIn(scriptsDir, dryRun));
40
+ }
41
+ return modified;
42
+ }
43
+ export default { makeScriptsExecutable };
44
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +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;;GAEG;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 ADDED
@@ -0,0 +1,20 @@
1
+ export interface InitGitOptions {
2
+ noGit?: boolean;
3
+ dryRun?: boolean;
4
+ }
5
+ /**
6
+ * Detects whether targetDir is already inside an existing Git worktree.
7
+ * Socket note: shell access is limited to `git rev-parse` via runGit (no shell).
8
+ */
9
+ export declare function isInsideGitWorkTree(targetDir: string): boolean;
10
+ /**
11
+ * Initializes a git repository in the target directory if not already inside one.
12
+ * Socket note: only allowlisted `git init/branch/add/commit` via execFileSync, cwd scoped.
13
+ */
14
+ export declare function initGit(targetDir: string, options?: InitGitOptions): boolean;
15
+ declare const _default: {
16
+ isInsideGitWorkTree: typeof isInsideGitWorkTree;
17
+ initGit: typeof initGit;
18
+ };
19
+ export default _default;
20
+ //# sourceMappingURL=repo.d.ts.map
@@ -0,0 +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;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAW9D;AA8CD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAchF;;;;;AAED,wBAAgD"}
package/lib/repo.js ADDED
@@ -0,0 +1,92 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import process from 'node:process';
4
+ import { runGit } from './git.js';
5
+ const INITIAL_COMMIT_MESSAGE = 'chore: initial scaffold from azcodr template';
6
+ /**
7
+ * Detects whether targetDir is already inside an existing Git worktree.
8
+ * Socket note: shell access is limited to `git rev-parse` via runGit (no shell).
9
+ */
10
+ export function isInsideGitWorkTree(targetDir) {
11
+ try {
12
+ const checkDir = fs.existsSync(targetDir) ? targetDir : path.dirname(targetDir);
13
+ const out = runGit(['rev-parse', '--is-inside-work-tree'], {
14
+ cwd: checkDir,
15
+ stdio: ['ignore', 'pipe', 'ignore']
16
+ });
17
+ return String(out).trim() === 'true';
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ function renameBranchMain(targetDir) {
24
+ try {
25
+ runGit(['branch', '-m', 'main'], { cwd: targetDir, stdio: 'ignore' });
26
+ }
27
+ catch {
28
+ // Non-critical if branch rename fails
29
+ }
30
+ }
31
+ function initRepository(targetDir) {
32
+ try {
33
+ runGit(['init', '-b', 'main', '-q'], { cwd: targetDir, stdio: 'ignore' });
34
+ }
35
+ catch {
36
+ runGit(['init', '-q'], { cwd: targetDir, stdio: 'ignore' });
37
+ renameBranchMain(targetDir);
38
+ }
39
+ }
40
+ function commitWithFallbackIdentity(targetDir) {
41
+ const options = { cwd: targetDir, stdio: 'ignore' };
42
+ try {
43
+ runGit(['commit', '-q', '-m', INITIAL_COMMIT_MESSAGE], options);
44
+ }
45
+ catch {
46
+ runGit(['commit', '-q', '-m', INITIAL_COMMIT_MESSAGE], {
47
+ ...options,
48
+ env: {
49
+ ...process.env,
50
+ GIT_AUTHOR_NAME: 'Subodh Khanal',
51
+ GIT_AUTHOR_EMAIL: 'prosubodh@gmail.com',
52
+ GIT_COMMITTER_NAME: 'Subodh Khanal',
53
+ GIT_COMMITTER_EMAIL: 'prosubodh@gmail.com'
54
+ }
55
+ });
56
+ }
57
+ }
58
+ function initialCommit(targetDir) {
59
+ try {
60
+ runGit(['add', '-A'], { cwd: targetDir, stdio: 'ignore' });
61
+ commitWithFallbackIdentity(targetDir);
62
+ }
63
+ catch {
64
+ // Non-critical if initial commit fails
65
+ }
66
+ }
67
+ /**
68
+ * Initializes a git repository in the target directory if not already inside one.
69
+ * Socket note: only allowlisted `git init/branch/add/commit` via execFileSync, cwd scoped.
70
+ */
71
+ export function initGit(targetDir, options = {}) {
72
+ const { noGit = false, dryRun = false } = options;
73
+ if (noGit)
74
+ return false;
75
+ const gitDir = path.join(targetDir, '.git');
76
+ if (fs.existsSync(gitDir))
77
+ return false;
78
+ if (isInsideGitWorkTree(targetDir))
79
+ return false;
80
+ if (dryRun)
81
+ return true;
82
+ try {
83
+ initRepository(targetDir);
84
+ initialCommit(targetDir);
85
+ return true;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ export default { isInsideGitWorkTree, initGit };
92
+ //# sourceMappingURL=repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"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"}