@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.9 → 0.1.12
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/git +1 -1
- package/bin/git-ado +2 -2
- package/bin/lib/bun-compile-build.sh +1 -1
- package/bin/lib/fleet-host.sh +59 -0
- package/bin/lib/lean-ctx-observe-hooks.sh +9 -9
- package/bin/reconcile +222 -249
- package/bin/reconcile-host +111 -0
- package/bin/setup +216 -0
- package/bin/sync-and-reconcile +52 -39
- package/bin/validate-manifest +15 -44
- package/package.json +1 -3
- package/packages/agent-hooks/package.json +1 -2
- package/packages/agent-hooks/src/hooks/crg/background.ts +179 -0
- package/packages/agent-hooks/src/hooks/crg/handler.ts +2 -1
- package/packages/agent-hooks/src/hooks/crg/index.ts +36 -5
- package/packages/agent-hooks/src/rules/impl/fs-trash.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/git-paths.ts +5 -6
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +8 -8
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +4 -2
- package/packages/agent-settings/src/global-surface-sweep.ts +5 -15
- package/packages/agent-skills/package.json +1 -1
- package/packages/azdo/package.json +1 -2
- package/packages/azdo/src/azdo-repo-doctor.ts +70 -75
- package/packages/fleet/manifest.json +5 -24
- package/packages/fleet/manifest.schema.json +8 -58
- package/packages/fleet/src/install-embedding-model.ts +1 -1
- package/packages/fleet/src/repo-maintain.ts +403 -0
- package/packages/fleet/src/scratch-reap.ts +1 -1
- package/packages/repo-controls/README.md +46 -8
- package/packages/repo-controls/assets/promote.ts +12 -7
- package/packages/repo-controls/assets/reconcile-guard.sh +113 -0
- package/packages/repo-controls/assets/version-bump.sh +91 -51
- package/packages/repo-controls/package.json +0 -1
- package/packages/repo-controls/src/azure-devops-governance.ts +17 -16
- package/packages/repo-controls/src/constants.ts +8 -0
- package/packages/repo-controls/src/hook.ts +3 -2
- package/packages/repo-controls/src/integrity.ts +15 -1
- package/packages/fleet/jobs/git-maintain/src/main.ts +0 -848
- package/packages/fleet/systemd/adl-azure-agent-update.service +0 -13
- package/packages/fleet/systemd/adl-azure-agent-update.timer +0 -10
|
@@ -85,13 +85,24 @@
|
|
|
85
85
|
* as its own finding. checkBuildServiceCanRelease() answers one narrow
|
|
86
86
|
* question directly, per the real failure above: can the identity that
|
|
87
87
|
* ACTUALLY RUNS THE PIPELINE (repo scope) push a `***NO_CI***` bump commit
|
|
88
|
-
* to
|
|
89
|
-
*
|
|
90
|
-
*
|
|
88
|
+
* to the PR's source (feature) branch (GenericContribute), and create/update
|
|
89
|
+
* the `integration -> main` PR and set auto-complete
|
|
90
|
+
* (PullRequestContribute) — and it FAILS loudly,
|
|
91
91
|
* naming the permission, the identity's display name and the fix path, on
|
|
92
92
|
* any of: the permission not effectively allowed, the identity not
|
|
93
93
|
* resolvable, or the ACL itself not readable by the calling agent.
|
|
94
94
|
*
|
|
95
|
+
* New release flow (Tarun, 2026-09-30): the CI pipeline runs on PRs into
|
|
96
|
+
* `integration` and its stage 1 pushes the version bump to the PR's SOURCE
|
|
97
|
+
* (feature) branch; a promote pipeline on `integration` pushes only opens the
|
|
98
|
+
* `integration -> main` PR; a CD pipeline runs on pushes to `main`. Nothing
|
|
99
|
+
* pushes directly to `integration` any more, so (a) the build service no
|
|
100
|
+
* longer needs PolicyExempt on `integration` — and, by least privilege,
|
|
101
|
+
* having it there is drift; (b) the release-identity check no longer needs
|
|
102
|
+
* PolicyExempt; (c) the promotion PR gets NO build validation (Tarun's
|
|
103
|
+
* approval is the only gate; CD runs after the merge), so `main` no longer
|
|
104
|
+
* requires a build-validation policy and an enabled one is drift.
|
|
105
|
+
*
|
|
95
106
|
* Policy type GUIDs (verified against the azure-devops-cli-extension source,
|
|
96
107
|
* packages/repo-controls already hardcodes the first three the same way):
|
|
97
108
|
* minimum reviewers fa4e907d-c16b-4a4c-9dfa-4906e5d171dd
|
|
@@ -178,7 +189,11 @@ export const REPO_STANDARD = {
|
|
|
178
189
|
forbiddenReviewerPolicies: [POLICY_TYPE.requiredReviewers] as const,
|
|
179
190
|
mergeStrategy: { allowSquash: false, allowRebase: false, allowRebaseMerge: false, allowNoFastForward: true },
|
|
180
191
|
commentRequirementsRequired: true,
|
|
181
|
-
|
|
192
|
+
// Tarun, 2026-09-30, new release flow: the integration -> main promotion
|
|
193
|
+
// PR must NOT run a build (Tarun's approval is the only gate; the CD
|
|
194
|
+
// pipeline runs after the merge, on pushes to main). An ENABLED build
|
|
195
|
+
// policy on main is drift (`main.build-validation-present`).
|
|
196
|
+
buildValidationForbidden: true,
|
|
182
197
|
},
|
|
183
198
|
// One table for every effective-permission expectation this checker reads
|
|
184
199
|
// via the Git Repositories security namespace ACL, so the standard never
|
|
@@ -216,9 +231,13 @@ export const REPO_STANDARD = {
|
|
|
216
231
|
* — Tarun, 2026-09-27, cross-checked against
|
|
217
232
|
* /Users/tarunrana/Documents/ADL-ISMS-Policies/.scratchpad/ci_build_service_grant.py,
|
|
218
233
|
* which grants exactly these bits on adl-agent-control). CI needs to push
|
|
219
|
-
* and complete PRs on the repo
|
|
220
|
-
*
|
|
221
|
-
*
|
|
234
|
+
* and complete PRs on the repo (Contribute is also what the version-bump
|
|
235
|
+
* push to the PR's SOURCE feature branch needs — Tarun, 2026-09-30, new
|
|
236
|
+
* release flow). It needs PolicyExempt NOWHERE: nothing pushes directly to
|
|
237
|
+
* `integration` any more (the bump lands on the feature branch), so
|
|
238
|
+
* PolicyExempt on `integration` is no longer required and, by least
|
|
239
|
+
* privilege, is drift (`permissions.build-service.has-policyExempt-integration`);
|
|
240
|
+
* never on `main` either (existing rule).
|
|
222
241
|
*
|
|
223
242
|
* NOT forcePush (Tarun, 2026-09-30): the bump is a plain fast-forward
|
|
224
243
|
* `git push origin HEAD:integration`; agent-identities' build service has
|
|
@@ -229,33 +248,28 @@ export const REPO_STANDARD = {
|
|
|
229
248
|
repo: { allow: ["genericContribute", "pullRequestContribute"] } as {
|
|
230
249
|
allow: readonly PermissionBitName[];
|
|
231
250
|
},
|
|
232
|
-
integrationRef: {
|
|
251
|
+
integrationRef: { deny: ["policyExempt"] } as { deny: readonly PermissionBitName[] },
|
|
233
252
|
mainRef: { deny: ["policyExempt"] } as { deny: readonly PermissionBitName[] },
|
|
234
253
|
},
|
|
235
254
|
/**
|
|
236
255
|
* checkBuildServiceCanRelease() (file header, "checkBuildServiceCanRelease()"):
|
|
237
|
-
* the
|
|
238
|
-
*
|
|
239
|
-
*
|
|
256
|
+
* the permissions the release flow needs from whichever build service
|
|
257
|
+
* identity actually runs the pipeline — the real failure this check
|
|
258
|
+
* exists for was a 403 on `pullRequestContribute`.
|
|
240
259
|
*
|
|
241
|
-
* `policyExempt` ("Bypass policies when pushing") is
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* `
|
|
249
|
-
* `
|
|
250
|
-
*
|
|
251
|
-
* contradicted this observed reality. `genericContribute` and
|
|
252
|
-
* `pullRequestContribute` stay checked at repo scope — both bits ARE
|
|
253
|
-
* present there for real, and PR operations are a repo-level, not
|
|
254
|
-
* branch-level, permission.
|
|
260
|
+
* `policyExempt` ("Bypass policies when pushing") is NOT required any
|
|
261
|
+
* more (Tarun, 2026-09-30, new release flow): the version bump now lands
|
|
262
|
+
* on the PR's SOURCE (feature) branch, not on `integration`, so nothing
|
|
263
|
+
* needs to bypass `integration`'s policies. (History: it used to be
|
|
264
|
+
* checked at the `integration` REF token, never repo scope — verified
|
|
265
|
+
* live 2026-09-30 against adl-agent-control, where the build service
|
|
266
|
+
* pushed `chore: bump version 0.1.6 to 0.1.7 ***NO_CI***` (c966e6a)
|
|
267
|
+
* straight to `integration`.) `genericContribute` (the bump push to the
|
|
268
|
+
* feature branch) and `pullRequestContribute` stay checked at repo scope
|
|
269
|
+
* — PR operations are a repo-level, not branch-level, permission.
|
|
255
270
|
*/
|
|
256
271
|
buildServiceRelease: {
|
|
257
272
|
repoScoped: ["genericContribute", "pullRequestContribute"] as const,
|
|
258
|
-
integrationRefScoped: ["policyExempt"] as const,
|
|
259
273
|
},
|
|
260
274
|
},
|
|
261
275
|
} as const;
|
|
@@ -518,11 +532,7 @@ function checkMainMergeStrategy(policies: readonly PolicyConfiguration[], drifts
|
|
|
518
532
|
});
|
|
519
533
|
}
|
|
520
534
|
|
|
521
|
-
function checkMainCommentsAndBuild(
|
|
522
|
-
policies: readonly PolicyConfiguration[],
|
|
523
|
-
hasPipeline: boolean,
|
|
524
|
-
drifts: RepoDoctorDrift[],
|
|
525
|
-
): void {
|
|
535
|
+
function checkMainCommentsAndBuild(policies: readonly PolicyConfiguration[], drifts: RepoDoctorDrift[]): void {
|
|
526
536
|
const comments = enabledPolicyOfType(policies, POLICY_TYPE.commentRequirements);
|
|
527
537
|
if (!comments) {
|
|
528
538
|
drifts.push({
|
|
@@ -531,21 +541,27 @@ function checkMainCommentsAndBuild(
|
|
|
531
541
|
});
|
|
532
542
|
}
|
|
533
543
|
|
|
534
|
-
|
|
544
|
+
// Tarun, 2026-09-30, new release flow: the promotion PR must not run a
|
|
545
|
+
// build — main no longer requires build validation, and an enabled one is
|
|
546
|
+
// drift (regardless of whether a pipeline exists).
|
|
535
547
|
const build = enabledPolicyOfType(policies, POLICY_TYPE.build);
|
|
536
|
-
if (
|
|
548
|
+
if (build) {
|
|
549
|
+
drifts.push({
|
|
550
|
+
id: "main.build-validation-present",
|
|
551
|
+
message: `main has an enabled build-validation policy (#${build.id}); the promotion PR must not run a build (CD runs after merge) — Tarun's approval is the only gate`,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
537
554
|
}
|
|
538
555
|
|
|
539
556
|
function checkMainPolicies(
|
|
540
557
|
policies: readonly PolicyConfiguration[],
|
|
541
|
-
hasPipeline: boolean,
|
|
542
558
|
strictMainBranchRules: boolean,
|
|
543
559
|
drifts: RepoDoctorDrift[],
|
|
544
560
|
): void {
|
|
545
561
|
checkMainRequiredReviewer(policies, drifts);
|
|
546
562
|
checkMainMinimumReviewers(policies, strictMainBranchRules, drifts);
|
|
547
563
|
checkMainMergeStrategy(policies, drifts);
|
|
548
|
-
checkMainCommentsAndBuild(policies,
|
|
564
|
+
checkMainCommentsAndBuild(policies, drifts);
|
|
549
565
|
}
|
|
550
566
|
|
|
551
567
|
/**
|
|
@@ -823,10 +839,11 @@ async function resolveBuildServiceDescriptor(namespaceId: string, projectId: str
|
|
|
823
839
|
}
|
|
824
840
|
|
|
825
841
|
/**
|
|
826
|
-
* CI needs to push
|
|
827
|
-
*
|
|
828
|
-
*
|
|
829
|
-
*
|
|
842
|
+
* CI needs to push (the version bump to the PR's source branch) and complete
|
|
843
|
+
* PRs on the repo itself. It needs to bypass policy NOWHERE (Tarun,
|
|
844
|
+
* 2026-09-30, new release flow: nothing pushes directly to `integration`
|
|
845
|
+
* any more, so PolicyExempt there is drift; on `main` a bypass would defeat
|
|
846
|
+
* the human-reviewer gate entirely).
|
|
830
847
|
*/
|
|
831
848
|
async function checkBuildServicePermissions(
|
|
832
849
|
namespaceId: string,
|
|
@@ -885,11 +902,14 @@ async function checkBuildServicePermissions(
|
|
|
885
902
|
drifts,
|
|
886
903
|
);
|
|
887
904
|
if (integrationEffective) {
|
|
888
|
-
|
|
889
|
-
|
|
905
|
+
// Tarun, 2026-09-30, new release flow: nothing pushes directly to
|
|
906
|
+
// integration any more, so PolicyExempt there is no longer required and
|
|
907
|
+
// is flagged when effectively allowed (least privilege).
|
|
908
|
+
for (const bitName of REPO_STANDARD.permissions.buildService.integrationRef.deny) {
|
|
909
|
+
if ((effectiveAllowBits(integrationEffective) & GIT_REPO_PERMISSION_BIT[bitName]) !== 0) {
|
|
890
910
|
drifts.push({
|
|
891
|
-
id: `permissions.build-service.
|
|
892
|
-
message: `the project build service
|
|
911
|
+
id: `permissions.build-service.has-${bitName}-integration`,
|
|
912
|
+
message: `the project build service effectively has ${bitName} on refs/heads/integration, which the standard forbids (nothing pushes directly to integration; the version bump lands on the PR's source branch)`,
|
|
893
913
|
});
|
|
894
914
|
}
|
|
895
915
|
}
|
|
@@ -941,16 +961,6 @@ function releaseFixPath(repository: string, identityDisplayName: string, bitName
|
|
|
941
961
|
return `Project settings → Repositories → \`${repository}\` → Security → \`${identityDisplayName}\` → \`${GIT_REPO_PERMISSION_UI_LABEL[bitName]}\` = Allow`;
|
|
942
962
|
}
|
|
943
963
|
|
|
944
|
-
/** Same as releaseFixPath() but for a bit that is granted per-BRANCH (verified live 2026-09-30: PolicyExempt on this org's build service lives on refs/heads/integration's own security page, never the repo-root one). */
|
|
945
|
-
function releaseFixPathForRef(
|
|
946
|
-
repository: string,
|
|
947
|
-
ref: string,
|
|
948
|
-
identityDisplayName: string,
|
|
949
|
-
bitName: PermissionBitName,
|
|
950
|
-
): string {
|
|
951
|
-
return `Repos → \`${repository}\` → Branches → \`${ref}\` → ⋯ → Branch security → \`${identityDisplayName}\` → \`${GIT_REPO_PERMISSION_UI_LABEL[bitName]}\` = Allow`;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
964
|
/**
|
|
955
965
|
* Which build service identity actually runs the pipeline, per Build —
|
|
956
966
|
* General Settings — Get's `enforceJobAuthScope` (file header) — "Limit job
|
|
@@ -973,12 +983,10 @@ async function fetchEnforceJobAuthScope(c: AdoClient): Promise<boolean | undefin
|
|
|
973
983
|
/**
|
|
974
984
|
* One identity's answer to "can it release": resolve its descriptor by exact
|
|
975
985
|
* display name (Identities — Read Identities, file header), then check
|
|
976
|
-
* `buildServiceRelease.repoScoped` on the repository token
|
|
977
|
-
*
|
|
978
|
-
*
|
|
979
|
-
* buildServiceRelease's own doc comment
|
|
980
|
-
* in this org, verified live against real bypass-on-push evidence, and
|
|
981
|
-
* checking it at repo scope produced a false "missing" finding). Every
|
|
986
|
+
* `buildServiceRelease.repoScoped` on the repository token. PolicyExempt is
|
|
987
|
+
* no longer part of what a release needs (Tarun, 2026-09-30, new release
|
|
988
|
+
* flow: the bump lands on the PR's source branch, not on integration — see
|
|
989
|
+
* REPO_STANDARD.permissions.buildServiceRelease's own doc comment). Every
|
|
982
990
|
* failure mode is its own loud, distinct drift — an unresolvable identity,
|
|
983
991
|
* an ACL the calling agent cannot read, and each missing permission named
|
|
984
992
|
* with its fix path — never a silent pass.
|
|
@@ -986,7 +994,6 @@ async function fetchEnforceJobAuthScope(c: AdoClient): Promise<boolean | undefin
|
|
|
986
994
|
async function checkOneBuildServiceCanRelease(
|
|
987
995
|
namespaceId: string,
|
|
988
996
|
repoToken: string,
|
|
989
|
-
integrationRefToken: string,
|
|
990
997
|
repository: string,
|
|
991
998
|
displayName: string,
|
|
992
999
|
drifts: RepoDoctorDrift[],
|
|
@@ -1013,8 +1020,7 @@ async function checkOneBuildServiceCanRelease(
|
|
|
1013
1020
|
}
|
|
1014
1021
|
|
|
1015
1022
|
// LOW, independent review 2026-09-30: name WHICH token failed — "the ACL"
|
|
1016
|
-
// alone left a human unable to tell
|
|
1017
|
-
// refs/heads/integration-scope one without re-running this by hand.
|
|
1023
|
+
// alone left a human unable to tell which token's read 403'd.
|
|
1018
1024
|
async function effectiveAt(token: string, tokenLabel: string): Promise<{ allow: number; deny: number } | undefined> {
|
|
1019
1025
|
let effective: EffectivePermissionsResult;
|
|
1020
1026
|
try {
|
|
@@ -1039,16 +1045,6 @@ async function checkOneBuildServiceCanRelease(
|
|
|
1039
1045
|
message: `'${displayName}' does not effectively have ${GIT_REPO_PERMISSION_UI_LABEL[bitName]} on '${repository}' — the release pipeline will 403 the way agent-identities build 4897 did. Fix: ${releaseFixPath(repository, displayName, bitName)}`,
|
|
1040
1046
|
});
|
|
1041
1047
|
}
|
|
1042
|
-
|
|
1043
|
-
const integrationEffective = await effectiveAt(integrationRefToken, "refs/heads/integration");
|
|
1044
|
-
if (!integrationEffective) return;
|
|
1045
|
-
for (const bitName of REPO_STANDARD.permissions.buildServiceRelease.integrationRefScoped) {
|
|
1046
|
-
if ((effectiveAllowBits(integrationEffective) & GIT_REPO_PERMISSION_BIT[bitName]) !== 0) continue;
|
|
1047
|
-
drifts.push({
|
|
1048
|
-
id: `permissions.release.${slug}.missing-${bitName}`,
|
|
1049
|
-
message: `'${displayName}' does not effectively have ${GIT_REPO_PERMISSION_UI_LABEL[bitName]} on 'refs/heads/integration' of '${repository}' — its own version-bump commit would be blocked by integration's own policies. Fix: ${releaseFixPathForRef(repository, "integration", displayName, bitName)}`,
|
|
1050
|
-
});
|
|
1051
|
-
}
|
|
1052
1048
|
}
|
|
1053
1049
|
|
|
1054
1050
|
/**
|
|
@@ -1079,9 +1075,8 @@ async function checkBuildServiceCanRelease(
|
|
|
1079
1075
|
: [projectScoped, collectionScoped];
|
|
1080
1076
|
|
|
1081
1077
|
const repoToken = `repoV2/${projectId}/${repositoryId}`;
|
|
1082
|
-
const integrationRefToken = `${repoToken}/refs/heads/${refNameHexUtf16Le("integration")}`;
|
|
1083
1078
|
for (const displayName of displayNames) {
|
|
1084
|
-
await checkOneBuildServiceCanRelease(namespaceId, repoToken,
|
|
1079
|
+
await checkOneBuildServiceCanRelease(namespaceId, repoToken, repository, displayName, drifts);
|
|
1085
1080
|
}
|
|
1086
1081
|
}
|
|
1087
1082
|
|
|
@@ -1140,7 +1135,7 @@ export async function repoDoctorCheck(options: RepoDoctorOptions = {}): Promise<
|
|
|
1140
1135
|
const integrationPolicies = await fetchBranchPolicies(c, repositoryId, "integration");
|
|
1141
1136
|
const mainPolicies = await fetchBranchPolicies(c, repositoryId, "main");
|
|
1142
1137
|
checkIntegrationPolicies(integrationPolicies, hasPipeline, drifts);
|
|
1143
|
-
checkMainPolicies(mainPolicies,
|
|
1138
|
+
checkMainPolicies(mainPolicies, strictMainBranchRules, drifts);
|
|
1144
1139
|
|
|
1145
1140
|
await checkAgentPermissions(projectId, repositoryId, strictMainBranchRules, drifts);
|
|
1146
1141
|
await checkBuildServicePermissions(
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"schema": 1,
|
|
4
4
|
"repository": "https://dev.azure.com/amsterdamdatalabs/Infrastructure-AzDo/_git/adl-agent-control",
|
|
5
5
|
"branch": "main",
|
|
6
|
-
"interval_seconds":
|
|
6
|
+
"interval_seconds": 43200,
|
|
7
7
|
"update_policy": "latest-stable",
|
|
8
8
|
"allow_major_updates": true,
|
|
9
9
|
"remove_deleted_entries": true,
|
|
@@ -33,12 +33,6 @@
|
|
|
33
33
|
"git_global_config": {
|
|
34
34
|
"lfs.ssh://ssh.dev.azure.com/.sshtransfer": "never",
|
|
35
35
|
"lfs.https://ssh.dev.azure.com/.locksverify": "false"
|
|
36
|
-
},
|
|
37
|
-
"azure_agents": {
|
|
38
|
-
"organization": "amsterdamdatalabs",
|
|
39
|
-
"pool_id": 1,
|
|
40
|
-
"coordinator": "hostinger-vps-1",
|
|
41
|
-
"enabled_agents": ["mac-m5-ci", "hostinger-vps-1-agent-1", "hostinger-vps-1-agent-2"]
|
|
42
36
|
}
|
|
43
37
|
},
|
|
44
38
|
"mac": {
|
|
@@ -70,21 +64,6 @@
|
|
|
70
64
|
"shfmt": {"manager": "brew", "package": "shfmt", "executable": "shfmt"},
|
|
71
65
|
"uv": {"manager": "brew", "package": "uv", "executable": "uv"},
|
|
72
66
|
"yq": {"manager": "brew", "package": "yq", "executable": "yq"}
|
|
73
|
-
},
|
|
74
|
-
"launch_agents": {
|
|
75
|
-
"git-maintain": {
|
|
76
|
-
"label": "com.adl.git-maintain",
|
|
77
|
-
"source": "packages/fleet/jobs/git-maintain",
|
|
78
|
-
"entry": "src/main.ts",
|
|
79
|
-
"start_interval_seconds": 86400,
|
|
80
|
-
"run_at_load": true,
|
|
81
|
-
"repo_scope": {"root": "Documents", "glob": "*", "recursive": true},
|
|
82
|
-
"environment": {
|
|
83
|
-
"PATH": "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
84
|
-
},
|
|
85
|
-
"log": "Library/Logs/adl/git-maintain.log",
|
|
86
|
-
"replaces": [".local/bin/git-maintain.sh"]
|
|
87
|
-
}
|
|
88
67
|
}
|
|
89
68
|
},
|
|
90
69
|
"devices": {
|
|
@@ -94,6 +73,7 @@
|
|
|
94
73
|
"home": "/Users/tarunrana",
|
|
95
74
|
"minimum_free_gib": 20,
|
|
96
75
|
"schedule_minute": 5,
|
|
76
|
+
"repo_location": "/Users/tarunrana/Documents/Repos",
|
|
97
77
|
"brew_upgrade_all": true,
|
|
98
78
|
"surface_clis": [
|
|
99
79
|
{"name": "claude", "manager": "native", "command": "claude", "update_args": ["update"]},
|
|
@@ -114,6 +94,7 @@
|
|
|
114
94
|
"home": "/Users/ranahome",
|
|
115
95
|
"minimum_free_gib": 20,
|
|
116
96
|
"schedule_minute": 35,
|
|
97
|
+
"repo_location": "/Users/ranahome/Documents",
|
|
117
98
|
"brew_upgrade_all": true,
|
|
118
99
|
"surface_clis": [
|
|
119
100
|
{"name": "claude", "manager": "native", "command": "claude", "update_args": ["update"]},
|
|
@@ -169,7 +150,7 @@
|
|
|
169
150
|
"minimum_free_gib": 25,
|
|
170
151
|
"schedule_minute": 50,
|
|
171
152
|
"scratch_repos": ["/root/enact-webview"],
|
|
172
|
-
"
|
|
153
|
+
"repo_location": "/root/workspace",
|
|
173
154
|
"brew_upgrade_all": true,
|
|
174
155
|
"surface_clis": [
|
|
175
156
|
{"name": "claude", "manager": "native", "command": "claude", "update_args": ["update"]},
|
|
@@ -190,7 +171,7 @@
|
|
|
190
171
|
"minimum_free_gib": 25,
|
|
191
172
|
"schedule_minute": 20,
|
|
192
173
|
"scratch_repos": ["/root/enact-webview"],
|
|
193
|
-
"
|
|
174
|
+
"repo_location": "/root/workspace",
|
|
194
175
|
"brew_upgrade_all": true,
|
|
195
176
|
"surface_clis": [
|
|
196
177
|
{"name": "opencode", "manager": "npm", "command": "opencode", "update_args": ["upgrade"]},
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"properties": {
|
|
9
9
|
"config": {
|
|
10
10
|
"type": "object",
|
|
11
|
-
"required": ["schema", "repository", "branch", "interval_seconds", "update_policy", "allow_major_updates", "remove_deleted_entries", "global_surface_sweep", "kimi_hooks", "surface_policy", "global_agents", "vscode_settings", "scratch_reap", "protected_tools", "git_global_config"
|
|
11
|
+
"required": ["schema", "repository", "branch", "interval_seconds", "update_policy", "allow_major_updates", "remove_deleted_entries", "global_surface_sweep", "kimi_hooks", "surface_policy", "global_agents", "vscode_settings", "scratch_reap", "protected_tools", "git_global_config"],
|
|
12
12
|
"properties": {
|
|
13
13
|
"global_surface_sweep": {
|
|
14
14
|
"type": "object",
|
|
@@ -72,20 +72,8 @@
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"mac": {
|
|
76
|
-
|
|
77
|
-
"properties": {
|
|
78
|
-
"common": {"properties": {"launch_agents": {"$ref": "#/$defs/launch_agents"}}},
|
|
79
|
-
"devices": {"additionalProperties": {"properties": {"launch_agents": {"$ref": "#/$defs/launch_agents"}}}}
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
"linux": {
|
|
83
|
-
"allOf": [{"$ref": "#/$defs/platform"}],
|
|
84
|
-
"properties": {
|
|
85
|
-
"common": {"not": {"required": ["launch_agents"]}},
|
|
86
|
-
"devices": {"additionalProperties": {"not": {"required": ["launch_agents"]}}}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
75
|
+
"mac": {"$ref": "#/$defs/platform"},
|
|
76
|
+
"linux": {"$ref": "#/$defs/platform"}
|
|
89
77
|
},
|
|
90
78
|
"$defs": {
|
|
91
79
|
"tool": {
|
|
@@ -157,7 +145,6 @@
|
|
|
157
145
|
"type": "object",
|
|
158
146
|
"additionalProperties": {"$ref": "#/$defs/tool"}
|
|
159
147
|
},
|
|
160
|
-
"relative_path": {"type": "string", "pattern": "^(?!/)(?!.*(^|/)\\.\\.(/|$)).+$"},
|
|
161
148
|
"surface_cli": {
|
|
162
149
|
"type": "object",
|
|
163
150
|
"additionalProperties": false,
|
|
@@ -197,46 +184,13 @@
|
|
|
197
184
|
}
|
|
198
185
|
]
|
|
199
186
|
},
|
|
200
|
-
"launch_agent": {
|
|
201
|
-
"type": "object",
|
|
202
|
-
"additionalProperties": false,
|
|
203
|
-
"required": ["label", "source", "entry", "start_interval_seconds", "run_at_load", "environment", "log"],
|
|
204
|
-
"properties": {
|
|
205
|
-
"label": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"},
|
|
206
|
-
"source": {"$ref": "#/$defs/relative_path", "description": "Checkout-relative job directory; reconcile compiles it to a dedicated signed binary, rebuilt when its content hash changes."},
|
|
207
|
-
"entry": {"$ref": "#/$defs/relative_path", "description": "TypeScript entry file relative to source."},
|
|
208
|
-
"start_interval_seconds": {"type": "integer", "minimum": 60},
|
|
209
|
-
"run_at_load": {"type": "boolean"},
|
|
210
|
-
"repo_scope": {
|
|
211
|
-
"type": "object",
|
|
212
|
-
"additionalProperties": false,
|
|
213
|
-
"required": ["root", "glob", "recursive"],
|
|
214
|
-
"properties": {
|
|
215
|
-
"root": {"$ref": "#/$defs/relative_path", "description": "Repository scan root relative to the device administrator's home."},
|
|
216
|
-
"glob": {"type": "string", "minLength": 1},
|
|
217
|
-
"recursive": {"const": true}
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
"environment": {
|
|
221
|
-
"type": "object",
|
|
222
|
-
"propertyNames": {"pattern": "^[A-Z_][A-Z0-9_]*$"},
|
|
223
|
-
"additionalProperties": {"type": "string"}
|
|
224
|
-
},
|
|
225
|
-
"log": {"$ref": "#/$defs/relative_path"},
|
|
226
|
-
"replaces": {"type": "array", "items": {"$ref": "#/$defs/relative_path"}}
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
"launch_agents": {
|
|
230
|
-
"description": "User LaunchAgents enact-vps installs for the device administrator (macOS only).",
|
|
231
|
-
"type": "object",
|
|
232
|
-
"additionalProperties": {"$ref": "#/$defs/launch_agent"}
|
|
233
|
-
},
|
|
234
187
|
"platform": {
|
|
235
188
|
"type": "object",
|
|
236
189
|
"required": ["common", "devices"],
|
|
237
190
|
"properties": {
|
|
238
191
|
"common": {
|
|
239
192
|
"type": "object",
|
|
193
|
+
"additionalProperties": false,
|
|
240
194
|
"required": ["tools"],
|
|
241
195
|
"properties": {
|
|
242
196
|
"os_upgrade": {"type": "boolean"},
|
|
@@ -274,14 +228,10 @@
|
|
|
274
228
|
"items": {"type": "string", "pattern": "^/[^\\s]*[^/\\s]$"},
|
|
275
229
|
"uniqueItems": true
|
|
276
230
|
},
|
|
277
|
-
"
|
|
278
|
-
"type": "
|
|
279
|
-
"description": "
|
|
280
|
-
"
|
|
281
|
-
"type": "string",
|
|
282
|
-
"pattern": "^/(?!$)(?!.*\\s)(?!.*/$)(?!.*\\.\\.)(?!.*[aA][zZ][aA][gG][eE][nN][tT])(?!.*[vV][sS][tT][sS]\\.[aA][gG][eE][nN][tT]).+$"
|
|
283
|
-
},
|
|
284
|
-
"uniqueItems": true
|
|
231
|
+
"repo_location": {
|
|
232
|
+
"type": "string",
|
|
233
|
+
"description": "One absolute directory on this host. `adl reconcile` maintains (fetch --prune, fast-forward integration and main, safe branch prune, then `adl install --repo`) every IMMEDIATE child of it that carries adl-config.toml and is a git top-level, as the device administrator. It is the entire scope of that step: nothing outside it is scanned or touched, and a child that resolves outside it is refused. A missing or unreadable location fails the run; a host that declares none skips the step with a log line. The case-insensitive azagent/vsts.agent ban keeps it away from Azure Pipelines agent installs (JSON Schema `pattern` has no case-insensitive flag, so the classes are spelled out).",
|
|
234
|
+
"pattern": "^/(?!$)(?!.*\\s)(?!.*/$)(?!.*\\.\\.)(?!.*[aA][zZ][aA][gG][eE][nN][tT])(?!.*[vV][sS][tT][sS]\\.[aA][gG][eE][nN][tT]).+$"
|
|
285
235
|
},
|
|
286
236
|
"tools": {"$ref": "#/$defs/tools"}
|
|
287
237
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
* bytes because they merely arrived over HTTPS. `revision` is then recorded
|
|
33
33
|
* in the installed `manifest.json` so the next run can skip the rebuild
|
|
34
34
|
* (network round-trip to resolve latest + a local file read) instead of
|
|
35
|
-
* re-downloading and re-verifying multi-hundred-MB files on every
|
|
35
|
+
* re-downloading and re-verifying multi-hundred-MB files on every 12-hour
|
|
36
36
|
* reconcile just to reach the same answer.
|
|
37
37
|
*
|
|
38
38
|
* `manifest.json`'s `source`, `vocab_limit`, and `dim` come from
|