@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.34 → 0.1.37
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/bin/adl +2 -2
- package/bin/reconcile +4 -3
- package/package.json +1 -1
- package/packages/agent-hooks/README.md +14 -0
- package/packages/agent-hooks/assets/opencode-plugin.template.ts +140 -104
- package/packages/agent-hooks/deploy-profile.json +1 -1
- package/packages/agent-hooks/src/deploy/opencode-template.ts +5 -18
- package/packages/agent-hooks/src/deploy/render.ts +12 -3
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-build-run-role.ts +116 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-user-override-block.ts +159 -0
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +12 -6
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +9 -9
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +6 -5
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +15 -14
- package/packages/agent-hooks/src/rules/impl/git-core.ts +4 -8
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +8 -7
- package/packages/agent-hooks/src/rules/registry.ts +11 -2
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +9 -5
- package/packages/agent-settings/README.md +10 -4
- package/packages/agent-settings/assets/TARUN-GLOBAL-AGENTS-INSTRUCTIONS.md +40 -0
- package/packages/agent-settings/src/global-agents.ts +43 -8
- package/packages/agent-skills/assets/adl-mechanics/SKILL.md +38 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +1 -1
- package/packages/agent-skills/assets/code-review/SKILL.md +84 -66
- package/packages/agent-skills/assets/diagnosing-bugs/SKILL.md +23 -2
- package/packages/agent-skills/assets/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +1 -1
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +3 -2
- package/packages/agent-skills/assets/finalize-feature/SKILL.md +63 -0
- package/packages/agent-skills/assets/fix-ci/SKILL.md +58 -0
- package/packages/agent-skills/assets/handoff/SKILL.md +1 -1
- package/packages/agent-skills/assets/implement-feature/SKILL.md +153 -0
- package/packages/agent-skills/assets/implement-feature/references/briefs.md +94 -0
- package/packages/agent-skills/assets/implement-item/SKILL.md +71 -0
- package/packages/agent-skills/assets/mechanics/SKILL.md +38 -0
- package/packages/agent-skills/assets/plan-feature/SKILL.md +141 -0
- package/packages/agent-skills/assets/prepare-promotion/SKILL.md +91 -0
- package/packages/agent-skills/assets/ralplan/SKILL.md +149 -0
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +4 -3
- package/packages/agent-skills/assets/report-bug/SKILL.md +72 -0
- package/packages/agent-skills/assets/review-change/SKILL.md +82 -0
- package/packages/agent-skills/assets/review-plan/SKILL.md +124 -0
- package/packages/agent-skills/assets/to-feature/SKILL.md +1 -1
- package/packages/agent-skills/assets/to-workitems/SKILL.md +1 -1
- package/packages/agent-skills/assets/to-workitems/references/AZURE-DEVOPS-HIERARCHY.md +3 -0
- package/packages/agent-skills/assets/triage-workitems/SKILL.md +99 -0
- package/packages/agent-skills/assets/ultragoal/SKILL.md +77 -0
- package/packages/agent-skills/assets/validate-design/SKILL.md +70 -0
- package/packages/agent-skills/assets/verify-item/SKILL.md +71 -0
- package/packages/agent-skills/assets/workitems-process/SKILL.md +147 -0
- package/packages/agent-skills/assets/workitems-process/references/ado-and-git.md +194 -0
- package/packages/agent-skills/assets/workitems-process/references/evidence.md +74 -0
- package/packages/agent-skills/assets/workitems-process/references/workitem-states.md +92 -0
- package/packages/agent-skills/assets/write-feature/SKILL.md +95 -0
- package/packages/agent-skills/dist/deploy.d.ts +7 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +52 -5
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/src/deploy.ts +48 -4
- package/packages/azdo/scripts/probe-ado-rules.ts +1 -1
- package/packages/azdo/src/activity-log.ts +118 -0
- package/packages/azdo/src/azdo-attachments.ts +108 -0
- package/packages/azdo/src/azdo-pl.ts +100 -3
- package/packages/azdo/src/azdo-pr.ts +194 -11
- package/packages/azdo/src/azdo-wit.ts +329 -18
- package/packages/azdo/src/cli.ts +42 -2
- package/packages/azdo/src/lib/agent-identity.ts +1 -1
- package/packages/azdo/src/lib/client.ts +7 -1
- package/packages/azdo/src/lib/validate-pr-metadata.ts +14 -5
- package/packages/azdo/src/mcp-server.ts +53 -5
- package/packages/azdo/src/tool-dispatch.ts +53 -4
- package/packages/azdo/src/workflow-ladder.csv +125 -107
- package/packages/azdo/src/workflow-rules.ts +254 -97
- package/packages/repo-controls/README.md +24 -11
- package/packages/repo-controls/assets/scaffold/docs/AGENTS.md +5 -5
- package/packages/repo-controls/assets/scaffold/plans/AGENTS.md +42 -13
- package/packages/repo-controls/assets/scaffold/root/AGENTS.md +60 -11
- package/packages/repo-controls/assets/scaffold/root/CONTRIBUTING.md +28 -0
- package/packages/repo-controls/assets/scaffold/root/INVARIANTS.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +4 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +1 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +3 -22
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +39 -182
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/features/az601-clean/intent.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +90 -321
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +31 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +282 -54
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/design.md +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/file-map-reference.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/intent.md +25 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +25 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/requirements.md +44 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/requirements.md +44 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +646 -53
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +1 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +1 -1
- package/packages/repo-controls/src/cli.ts +23 -5
- package/packages/repo-controls/src/constants.ts +2 -15
- package/packages/repo-controls/src/install.ts +15 -6
|
@@ -389,9 +389,9 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
389
389
|
"`root-files=STATUS.md,DRIFT.md` or `root-dirs=apps,packaging`; and "
|
|
390
390
|
"`scripts-direct-files` (LAY-014), a positive integer replacing the "
|
|
391
391
|
"default limit of 15 direct files per scripts directory, as "
|
|
392
|
-
"`scripts-direct-files=20`; `open-
|
|
393
|
-
"
|
|
394
|
-
"
|
|
392
|
+
"`scripts-direct-files=20`; `open-plans` (LAY-016), "
|
|
393
|
+
"a positive integer replacing the default cap of 10 open plans, "
|
|
394
|
+
"as `open-plans=11`; and "
|
|
395
395
|
"`markdown-roots` (LAY-006), a "
|
|
396
396
|
"comma-separated list of repository-relative directories whose "
|
|
397
397
|
"Markdown is allowed in addition to the declared docs trees "
|
package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py
CHANGED
|
@@ -6,8 +6,7 @@ this", and the answer is declared once, here, so a second docs gate does not
|
|
|
6
6
|
grow its own, independently drifting copy the way LAY-008/LAY-012 once did for
|
|
7
7
|
the repository root (see `root_shape.py`'s module docstring).
|
|
8
8
|
|
|
9
|
-
Every entry below is read off an EXISTING docs gate
|
|
10
|
-
is declared by an explicit decision (see its entry):
|
|
9
|
+
Every entry below is read off an EXISTING docs gate:
|
|
11
10
|
|
|
12
11
|
ALLOWED_DOCS_DIRS
|
|
13
12
|
architecture, research, compliance, operations
|
|
@@ -43,15 +42,6 @@ ALLOWED_DOCS_FILES
|
|
|
43
42
|
no repository in this estate ships a top-level `docs/index.md` today,
|
|
44
43
|
and declaring it costs nothing.
|
|
45
44
|
|
|
46
|
-
notes.md
|
|
47
|
-
the task ledger. Not read off a docs gate: Tarun's global agent rule
|
|
48
|
-
(decision of 2026-10-01) requires every agent to append one line to
|
|
49
|
-
`docs/notes.md` when it starts a task and one when it finishes
|
|
50
|
-
(append-only, at most 100 characters per line), so the file exists in
|
|
51
|
-
every repository an agent works in and this gate would otherwise flag
|
|
52
|
-
it as undeclared. `docs-okf-profiles.yaml` carries a matching
|
|
53
|
-
`docs/notes.md` profile so `docs.okf-profile` (DOC-006) grades it too.
|
|
54
|
-
|
|
55
45
|
These are PERMITTED, not required — the same distinction `root_shape.py`
|
|
56
46
|
draws for the repository root. A repository using only two of the five
|
|
57
47
|
directories is not missing three findings; it has simply not written those
|
|
@@ -72,5 +62,4 @@ ALLOWED_DOCS_FILES: frozenset[str] = frozenset({
|
|
|
72
62
|
"AGENTS.md",
|
|
73
63
|
"CLAUDE.md",
|
|
74
64
|
"index.md",
|
|
75
|
-
"notes.md",
|
|
76
65
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HOOK_NAMES, TOOL, VERSION } from './constants.ts'
|
|
1
|
+
import { HOOK_NAMES, SCAFFOLD_ROOT_FILES, TOOL, VERSION } from './constants.ts'
|
|
2
2
|
import { doctor } from './doctor.ts'
|
|
3
3
|
import { azdoPush } from './azdo-push.ts'
|
|
4
4
|
import { ensurePromotionPullRequest } from './promote.ts'
|
|
@@ -18,7 +18,8 @@ export interface Io {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const USAGE = `usage:
|
|
21
|
-
${TOOL} install [--repo <path>] [--dry-run] [--json] [--no-grade] [--rewire]
|
|
21
|
+
${TOOL} install [--repo <path>] [--dry-run] [--json] [--no-grade] [--rewire] [--force-templates[=<file,...>]]
|
|
22
|
+
(--force-templates: overwrite the root templates; bare = all of ${SCAFFOLD_ROOT_FILES.join(', ')}, or a comma list)
|
|
22
23
|
${TOOL} grade [--repo <path>] (prints the compliance verdict as JSON; exit 0 whatever the verdict)
|
|
23
24
|
${TOOL} uninstall [--repo <path>] [--dry-run]
|
|
24
25
|
${TOOL} doctor [--repo <path>] [--json]
|
|
@@ -40,6 +41,8 @@ interface Parsed {
|
|
|
40
41
|
flags: Set<string>
|
|
41
42
|
positional: string[]
|
|
42
43
|
rest: string[]
|
|
44
|
+
/** The raw `--force-templates=<list>` value; undefined for the bare flag. */
|
|
45
|
+
forced?: string
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
function parse(command: string, argv: string[], allowed: string[]): Parsed {
|
|
@@ -50,7 +53,11 @@ function parse(command: string, argv: string[], allowed: string[]): Parsed {
|
|
|
50
53
|
parsed.rest = argv.slice(index + 1)
|
|
51
54
|
break
|
|
52
55
|
}
|
|
53
|
-
if (arg === '--
|
|
56
|
+
if (arg === '--force-templates' || arg.startsWith('--force-templates=')) {
|
|
57
|
+
if (!allowed.includes('--force-templates')) throw new UsageError(`unknown option for ${command}: ${arg}`)
|
|
58
|
+
parsed.flags.add('--force-templates')
|
|
59
|
+
if (arg.includes('=')) parsed.forced = arg.slice(arg.indexOf('=') + 1)
|
|
60
|
+
} else if (arg === '--repo') {
|
|
54
61
|
parsed.repo = argv[++index] ?? ''
|
|
55
62
|
} else if (arg.startsWith('--')) {
|
|
56
63
|
if (!allowed.includes(arg)) throw new UsageError(`unknown option for ${command}: ${arg}`)
|
|
@@ -66,6 +73,15 @@ function parse(command: string, argv: string[], allowed: string[]): Parsed {
|
|
|
66
73
|
return parsed
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
/** The root templates named by `--force-templates[=<list>]`; the bare flag means all, an unknown or empty name is refused. */
|
|
77
|
+
function forcedTemplates(value: string | undefined): string[] {
|
|
78
|
+
if (value === undefined) return [...SCAFFOLD_ROOT_FILES]
|
|
79
|
+
const names = value.split(',')
|
|
80
|
+
const unknown = names.filter((name) => !(SCAFFOLD_ROOT_FILES as readonly string[]).includes(name))
|
|
81
|
+
if (unknown.length > 0) throw new UsageError(`unknown root template for --force-templates: ${unknown.map((n) => `'${n}'`).join(', ')} (valid: ${SCAFFOLD_ROOT_FILES.join(', ')})`)
|
|
82
|
+
return names
|
|
83
|
+
}
|
|
84
|
+
|
|
69
85
|
function printActions(io: Io, actions: Action[], dryRun: boolean): void {
|
|
70
86
|
const tag = dryRun ? '[dry-run] ' : ''
|
|
71
87
|
for (const action of actions) io.out(`${tag}${action.kind} ${action.target} (${action.reason})`)
|
|
@@ -84,10 +100,12 @@ async function dispatch(argv: string[], io: Io): Promise<number> {
|
|
|
84
100
|
io.out(USAGE)
|
|
85
101
|
return 0
|
|
86
102
|
case 'install': {
|
|
87
|
-
const parsed = parse(command, args, ['--dry-run', '--json', '--no-grade', '--rewire'])
|
|
103
|
+
const parsed = parse(command, args, ['--dry-run', '--json', '--no-grade', '--rewire', '--config-created', '--force-templates'])
|
|
88
104
|
const rewire = parsed.flags.has('--rewire')
|
|
105
|
+
const forceTemplates = parsed.flags.has('--force-templates') ? forcedTemplates(parsed.forced) : []
|
|
106
|
+
if (rewire && forceTemplates.length > 0) throw new UsageError('--force-templates cannot be combined with --rewire (a re-wire never writes root templates)')
|
|
89
107
|
const grade = parsed.flags.has('--no-grade') || rewire ? {} : { grade: { env: io.env } }
|
|
90
|
-
const result = install(parsed.repo, { dryRun: parsed.flags.has('--dry-run'), rewire, ...grade })
|
|
108
|
+
const result = install(parsed.repo, { dryRun: parsed.flags.has('--dry-run'), rewire, configCreated: parsed.flags.has('--config-created'), forceTemplates, ...grade })
|
|
91
109
|
if (parsed.flags.has('--json')) {
|
|
92
110
|
io.out(JSON.stringify(result))
|
|
93
111
|
return 0
|
|
@@ -2,16 +2,6 @@ import { readFileSync } from 'node:fs'
|
|
|
2
2
|
import { join, resolve } from 'node:path'
|
|
3
3
|
|
|
4
4
|
export const TOOL = 'adl-repo-controls'
|
|
5
|
-
/**
|
|
6
|
-
* Never published (2026-09-27): kept only as this
|
|
7
|
-
* package's own internal identity (USAGE text, error messages, the lock
|
|
8
|
-
* file's `tool` field) — none of that is a claim that `adl-repo-controls`
|
|
9
|
-
* is installable. NPM_INSTALL/PACKAGE_NAME describe a registry package that
|
|
10
|
-
* does not exist; do not point a user-facing "how do I get this on PATH"
|
|
11
|
-
* message at them (see ADL_NPM_INSTALL below for the one that is real).
|
|
12
|
-
*/
|
|
13
|
-
const PACKAGE_NAME = '@amsterdamdatalabs/adl-repo-controls'
|
|
14
|
-
const NPM_INSTALL = `npm i -g ${PACKAGE_NAME}`
|
|
15
5
|
/**
|
|
16
6
|
* How a repository's committed git-hook stubs actually get `adl` onto
|
|
17
7
|
* PATH: this package is folded into the `adl` binary's `repo controls`
|
|
@@ -72,11 +62,8 @@ export const RECONCILE_GUARD_REL = '.workflows/reconcile-guard.sh'
|
|
|
72
62
|
/** The folder skeleton `install` bootstraps for the adl standard trees; see README, "Scaffolding". */
|
|
73
63
|
export const SCAFFOLD_ROOT = join(PACKAGE_ROOT, 'assets', 'scaffold')
|
|
74
64
|
export const SCAFFOLD_TREES = ['docs', 'plans', 'workflows'] as const
|
|
75
|
-
/** Repository-root
|
|
76
|
-
export const SCAFFOLD_ROOT_FILES = ['AGENTS.md', 'CLAUDE.md'] as const
|
|
77
|
-
/** The invariants that apply to ALL repositories; install deploys it as `INVARIANTS.md` only when the target has none. */
|
|
78
|
-
export const GLOBAL_INVARIANTS_SOURCE = join(PACKAGE_ROOT, 'assets', 'GLOBAL-INVARIANTS.md')
|
|
79
|
-
export const GLOBAL_INVARIANTS_TARGET = 'INVARIANTS.md'
|
|
65
|
+
/** Repository-root templates in `assets/scaffold/root/`: written only by a run that creates adl-config.toml, overwritten only by `--force-templates`. */
|
|
66
|
+
export const SCAFFOLD_ROOT_FILES = ['AGENTS.md', 'CLAUDE.md', 'CONTRIBUTING.md', 'INVARIANTS.md'] as const
|
|
80
67
|
|
|
81
68
|
export const MANAGED_ASSETS = [
|
|
82
69
|
{ rel: PROMOTE_REL, source: join(PACKAGE_ROOT, 'assets', 'promote.ts'), mode: 0o755, doctorId: 'promote' },
|
|
@@ -24,8 +24,6 @@ import {
|
|
|
24
24
|
ADL_NPM_INSTALL,
|
|
25
25
|
CONFIG_REL,
|
|
26
26
|
GITIGNORE_REL,
|
|
27
|
-
GLOBAL_INVARIANTS_SOURCE,
|
|
28
|
-
GLOBAL_INVARIANTS_TARGET,
|
|
29
27
|
HOOK_NAMES,
|
|
30
28
|
HOOKS_PATH,
|
|
31
29
|
LOCK_REL,
|
|
@@ -234,6 +232,10 @@ export interface InstallOptions {
|
|
|
234
232
|
grade?: { env: Env }
|
|
235
233
|
/** Re-wire only: no config seeding, no scaffolding, no grading (fleet reconcile; see README, "Re-wiring"). */
|
|
236
234
|
rewire?: boolean
|
|
235
|
+
/** This run created adl-config.toml, so the root templates are written when absent; see README, "Root templates". */
|
|
236
|
+
configCreated?: boolean
|
|
237
|
+
/** Root templates to overwrite (`--force-templates`); the only way an existing template is replaced. */
|
|
238
|
+
forceTemplates?: readonly string[]
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
export interface InstallResult {
|
|
@@ -266,6 +268,7 @@ function readCentralMarker(repo: string, dryRun: boolean): string {
|
|
|
266
268
|
export function install(repoArg: string, options: InstallOptions): InstallResult {
|
|
267
269
|
const repo = resolveRepo(repoArg)
|
|
268
270
|
const dryRun = options.dryRun === true
|
|
271
|
+
const configMissing = !existsSync(join(repo, CONFIG_REL))
|
|
269
272
|
const initialConfigText = readCentralMarker(repo, dryRun)
|
|
270
273
|
// Validate only repo-controls' declared tables before deleting its root.
|
|
271
274
|
// Other owners' tables remain deliberately opaque.
|
|
@@ -336,6 +339,7 @@ export function install(repoArg: string, options: InstallOptions): InstallResult
|
|
|
336
339
|
created: complianceResult.created,
|
|
337
340
|
sha256: sha256(extractTableSpan(finalConfigText, 'controls.compliance') as string),
|
|
338
341
|
}
|
|
342
|
+
scaffoldRootTemplates(ops, options.configCreated === true || (dryRun && configMissing), options.forceTemplates ?? [])
|
|
339
343
|
scaffoldStandardTrees(finalConfigText, ops)
|
|
340
344
|
}
|
|
341
345
|
|
|
@@ -507,10 +511,6 @@ function assertComplianceTree(value: unknown): void {
|
|
|
507
511
|
/** Bootstrap the standard trees at their declared paths, only where the folder is missing; see README, "Scaffolding". */
|
|
508
512
|
function scaffoldStandardTrees(configText: string, ops: Ops): void {
|
|
509
513
|
const missing = declaredScaffoldTrees(configText).filter(({ base }) => !ops.occupied(base))
|
|
510
|
-
for (const rel of SCAFFOLD_ROOT_FILES) {
|
|
511
|
-
ops.create(rel, readFileSync(join(SCAFFOLD_ROOT, 'root', rel)), 'scaffold the repository entry files (user-owned after install)')
|
|
512
|
-
}
|
|
513
|
-
ops.create(GLOBAL_INVARIANTS_TARGET, readFileSync(GLOBAL_INVARIANTS_SOURCE), 'deploy the global invariants (user-owned after install)')
|
|
514
514
|
for (const { name, base } of missing) {
|
|
515
515
|
for (const rel of scaffoldFiles(join(SCAFFOLD_ROOT, name), '')) {
|
|
516
516
|
ops.create(`${base}/${rel}`, readFileSync(join(SCAFFOLD_ROOT, name, rel)), `scaffold the ${name} tree (user-owned after install)`)
|
|
@@ -518,6 +518,15 @@ function scaffoldStandardTrees(configText: string, ops: Ops): void {
|
|
|
518
518
|
}
|
|
519
519
|
}
|
|
520
520
|
|
|
521
|
+
/** Root templates: created when absent on a run that created adl-config.toml, overwritten only for the forced names; see README, "Root templates". */
|
|
522
|
+
function scaffoldRootTemplates(ops: Ops, created: boolean, forced: readonly string[]): void {
|
|
523
|
+
for (const rel of SCAFFOLD_ROOT_FILES) {
|
|
524
|
+
const bytes = readFileSync(join(SCAFFOLD_ROOT, 'root', rel))
|
|
525
|
+
if (forced.includes(rel)) ops.write(rel, bytes, 'overwrite the root template (--force-templates)')
|
|
526
|
+
else if (created) ops.create(rel, bytes, 'scaffold the repository root template (user-owned after install)')
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
521
530
|
/** Every file under `dir`, relative to it, sorted, depth-first. */
|
|
522
531
|
function scaffoldFiles(dir: string, prefix: string): string[] {
|
|
523
532
|
return readdirSync(join(dir, prefix), { withFileTypes: true })
|