@outerlayer/cli 0.18.0 → 0.19.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/CHANGELOG.md +33 -0
- package/README.md +21 -2
- package/dist/{agent-setup-RBTEACYU.js → agent-setup-AM42SA2D.js} +15 -16
- package/dist/{artifact-link-cmd-AVM2EKTV.js → artifact-link-cmd-OWRI5AJX.js} +2 -2
- package/dist/build-info.json +1 -1
- package/dist/{builder-DUI2ZH2H.js → builder-C4QNTYMS.js} +3 -3
- package/dist/{check-5C4YDZYV.js → check-W2JGXN3B.js} +44 -43
- package/dist/{chunk-S26M3YBJ.js → chunk-3UZTIRLF.js} +1 -1
- package/dist/{chunk-Y5MXET4M.js → chunk-3ZR7Y23Y.js} +11 -10
- package/dist/{chunk-47TTLEDX.js → chunk-5VML45HH.js} +35 -13
- package/dist/{chunk-F4XSVQJ4.js → chunk-6X4SQ5MY.js} +2 -2
- package/dist/{chunk-T4Y6SCG3.js → chunk-7UWVLZXD.js} +2 -2
- package/dist/{chunk-N3CUDFCW.js → chunk-7VUK5RFS.js} +15 -2
- package/dist/{chunk-SWCTGCSC.js → chunk-7YP7T6GV.js} +1 -1
- package/dist/{chunk-3OFZM4X6.js → chunk-B6SCN5NY.js} +151 -20
- package/dist/{chunk-KDVIU23F.js → chunk-BWSUPRDK.js} +1 -1
- package/dist/{chunk-S76AYB4M.js → chunk-CG36IONK.js} +5 -5
- package/dist/{chunk-RAZTWYZN.js → chunk-CGGPS7SI.js} +7 -8
- package/dist/chunk-CJJDJ7AT.js +56 -0
- package/dist/{chunk-W5VPCONO.js → chunk-EAEELQVQ.js} +33 -227
- package/dist/{chunk-QQM2UJ6T.js → chunk-F2KXHIFI.js} +182 -28
- package/dist/{chunk-KK4VBOH6.js → chunk-FBTGMSQF.js} +10 -11
- package/dist/{chunk-MQJSXHV7.js → chunk-G3IJ3N6F.js} +5 -3
- package/dist/{chunk-FUB7LRUE.js → chunk-GEMQLBMW.js} +5 -5
- package/dist/{chunk-Y5GE76XC.js → chunk-HOKXGFDR.js} +33 -81
- package/dist/{chunk-IP7BIBXJ.js → chunk-IF2OSI5T.js} +35 -1
- package/dist/{chunk-UYOYTKE2.js → chunk-JHGEBPLE.js} +3 -3
- package/dist/chunk-KYS3TQAG.js +296 -0
- package/dist/chunk-LLM3I5YU.js +89 -0
- package/dist/{chunk-B3UKB46N.js → chunk-LRG3ZMZD.js} +4 -5
- package/dist/{chunk-NL4XPC7W.js → chunk-LW7G5TJB.js} +1 -1
- package/dist/{chunk-MNTSH4CL.js → chunk-NNLA7LLQ.js} +1 -1
- package/dist/{chunk-GOBOJMOJ.js → chunk-PIZRPNKR.js} +4 -4
- package/dist/{chunk-ULSIJGLS.js → chunk-PSN33ERW.js} +56 -14
- package/dist/{chunk-WGAUY5LE.js → chunk-QEFKA2QD.js} +1 -1
- package/dist/{chunk-BMYGAGBJ.js → chunk-QNLX477Q.js} +155 -23
- package/dist/{chunk-JF42URPU.js → chunk-R22NZSGA.js} +33 -9
- package/dist/chunk-TUSYOL2O.js +113 -0
- package/dist/{chunk-ESC6UR76.js → chunk-TWF3RICI.js} +6 -6
- package/dist/{chunk-L2USZT6T.js → chunk-VMJPFQNE.js} +1 -1
- package/dist/{chunk-X5N6KC6V.js → chunk-WFSUUUAN.js} +2 -3
- package/dist/{chunk-6CHIYEZZ.js → chunk-XZ4H4X5F.js} +9 -83
- package/dist/{chunk-LXAY4A2G.js → chunk-YQR6E6OV.js} +34 -49
- package/dist/chunk-Z7K3L4FC.js +174 -0
- package/dist/{claude-launcher-YVXI76NX.js → claude-launcher-J5M44PFS.js} +20 -7
- package/dist/{cli-C77H54BV.js → cli-EXX2R73G.js} +206 -230
- package/dist/{command-H5CILO4S.js → command-ZQNEPDS6.js} +29 -30
- package/dist/{config-FXDG4NPJ.js → config-CLSGABD5.js} +2 -2
- package/dist/{connect-cmd-ZW5FV3ZW.js → connect-cmd-UNYKGDAL.js} +7 -7
- package/dist/context-cleanup-CHEWNYU6.js +11 -0
- package/dist/control-plane-launch-34LNRJWR.js +216 -0
- package/dist/{dist-QTX4RSCL.js → dist-WO7NOJNG.js} +2 -2
- package/dist/{docker-RC3PRX3Q.js → docker-BFU3AQGY.js} +4 -4
- package/dist/{doctor-2NQQML6P.js → doctor-DHUM5DBB.js} +32 -33
- package/dist/{emit-artifact-cmd-7MP63KXU.js → emit-artifact-cmd-XBHM647X.js} +17 -17
- package/dist/{emit-cmd-PPN4QQF2.js → emit-cmd-W55AEBCA.js} +6 -6
- package/dist/{emit-criteria-cmd-3RXPDLNK.js → emit-criteria-cmd-CRTYEF7D.js} +11 -12
- package/dist/{emit-finding-cmd-OL7JB6H3.js → emit-finding-cmd-7JHVRYOP.js} +12 -13
- package/dist/{emit-result-cmd-UZVMOCF4.js → emit-result-cmd-5NZMLCJK.js} +17 -17
- package/dist/emit-step-cmd-347XNGPQ.js +26 -0
- package/dist/{governing-source-BUU4IABS.js → governing-source-HAA4OW57.js} +21 -22
- package/dist/{hook-fast-W5MKHMJT.js → hook-fast-RL5E5OXE.js} +3 -3
- package/dist/{import-capture-cmd-ZO6KGHI2.js → import-capture-cmd-TK4XY7RD.js} +4 -4
- package/dist/{import-ruler-cmd-KJMWL5V6.js → import-ruler-cmd-T6LLO6Q7.js} +2 -2
- package/dist/index.js +4 -4
- package/dist/{init-WNXXYMO7.js → init-V6FOMD2V.js} +30 -31
- package/dist/{init-VWXIZEAN.js → init-XG47KCI4.js} +30 -31
- package/dist/{init-cmd-WS6TIRYT.js → init-cmd-Z4O4PPLZ.js} +70 -27
- package/dist/{init-update-E3J6TVIN.js → init-update-7DVAKWW3.js} +21 -22
- package/dist/{install-CBWIEF3R.js → install-4SEFIIW2.js} +3 -3
- package/dist/{login-browser-O63QZN7D.js → login-browser-DX35MARZ.js} +2 -2
- package/dist/{loop-UGI2BJOT.js → loop-TPUYUMSY.js} +44 -43
- package/dist/{machine-JOW4RNZ7.js → machine-TRHBT5NE.js} +26 -27
- package/dist/{mcp-serve-cmd-DOTY5FKY.js → mcp-serve-cmd-N3UTY6EE.js} +5 -5
- package/dist/{runner-env-4NB2GA7O.js → runner-env-FRZFFHDF.js} +4 -4
- package/dist/{runner-key-TC3NFWFV.js → runner-key-5FOWCW7J.js} +30 -31
- package/dist/{session-sender-NNVPSPY7.js → session-sender-U2BBUWNO.js} +19 -15
- package/dist/shell-function-NRD4KVUK.js +6 -0
- package/dist/{spec-cmd-OWVTBB4J.js → spec-cmd-FVLJOFGC.js} +12 -13
- package/dist/{starter-pack-OPWUDOWX.js → starter-pack-6LQVLBIA.js} +5 -5
- package/dist/{status-TKCLLKFG.js → status-BINH7MBG.js} +33 -32
- package/dist/{sync-cmd-Q6VYNPWG.js → sync-cmd-VXOUFS4I.js} +18 -14
- package/dist/{watch-ARAGADTF.js → watch-OH645CV2.js} +18 -14
- package/dist/{work-claim-cmd-34FERLYX.js → work-claim-cmd-ZRPSHMPT.js} +16 -17
- package/dist/{work-cmd-7S5B2H2P.js → work-cmd-5I3J2XQQ.js} +12 -13
- package/dist/{work-comment-cmd-SZJSPM5S.js → work-comment-cmd-UCCPWUSR.js} +12 -13
- package/dist/work-logs-cmd-7352CJPG.js +60 -0
- package/dist/{work-open-pr-cmd-RPXKCBWS.js → work-open-pr-cmd-LSH4VHJM.js} +13 -14
- package/dist/{work-pr-cmd-5LGANL32.js → work-pr-cmd-H4OQR26N.js} +12 -13
- package/package.json +2 -2
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +9 -2
- package/skill-pack/maintained/outerlayer-cli/references/find-out-why-a-build-ended.md +76 -0
- package/skill-pack/shipped.json +1 -0
- package/skill-pack/template/build/references/release.md +3 -1
- package/dist/chunk-WBT5X3NH.js +0 -40
- package/dist/chunk-XCCLFVXM.js +0 -401
- package/dist/context-adopt-O5OFXMKI.js +0 -109
- package/dist/context-materialize-Y5IJ4MQT.js +0 -23
- package/dist/{chunk-NACDBXUG.js → chunk-BM63HB2M.js} +1 -1
- package/dist/{chunk-ZRL6HKBY.js → chunk-FVMYKL6L.js} +1 -1
- package/dist/{chunk-52NC2FIU.js → chunk-NTRCK4NH.js} +1 -1
- package/dist/{chunk-XGP3VYOG.js → chunk-P53VEAOF.js} +1 -1
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { resolveGatewayCredentials } from './chunk-52NC2FIU.js';
|
|
7
|
-
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-MNTSH4CL.js';
|
|
8
|
-
import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-X5N6KC6V.js';
|
|
9
|
-
import { withTokenHeader } from './chunk-BQXFBI7T.js';
|
|
10
|
-
import { ensureContextExcludes, ensurePreCommitGuardHook } from './chunk-XCCLFVXM.js';
|
|
3
|
+
import { removeRetiredSkills } from './chunk-7UWVLZXD.js';
|
|
4
|
+
import { defaultFetch } from './chunk-FVMYKL6L.js';
|
|
5
|
+
import { resolveGatewayCredentials } from './chunk-NTRCK4NH.js';
|
|
11
6
|
import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
|
|
7
|
+
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-NNLA7LLQ.js';
|
|
12
8
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
9
|
+
import { writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, writeContextManifest, SOURCE_CACHE_TTL_SUCCESS_MS, readSourceCache, isSourceCacheFresh, clearDegraded } from './chunk-YQR6E6OV.js';
|
|
10
|
+
import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-WFSUUUAN.js';
|
|
13
11
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
12
|
+
import { withTokenHeader } from './chunk-BQXFBI7T.js';
|
|
14
13
|
import { execFileSync } from 'child_process';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
14
|
+
import { existsSync, mkdirSync, writeFileSync, chmodSync, lstatSync, readFileSync, copyFileSync } from 'fs';
|
|
15
|
+
import { isAbsolute, join, dirname } from 'path';
|
|
17
16
|
|
|
18
17
|
createRequire(import.meta.url);
|
|
19
18
|
var CONFIG_PATH = ".outerlayer/config.json";
|
|
@@ -93,29 +92,15 @@ function gitText(git, cwd, args, timeoutMs) {
|
|
|
93
92
|
return result.ok ? result.stdout.toString("utf8").trim() : void 0;
|
|
94
93
|
}
|
|
95
94
|
var GATEWAY_TOO_OLD_MESSAGE = "the OuterLayer this machine talks to is too old to name the control plane \u2014 ask whoever runs it to upgrade; context written earlier is kept";
|
|
96
|
-
var NOT_GOVERNED_MESSAGE = "this repository's control plane no longer governs it";
|
|
97
|
-
var ADOPTION_MESSAGE = "committed context files shadow the control plane \u2014 remove them in a commit";
|
|
98
95
|
var CANNOT_IDENTIFY_MESSAGE = "this repository is governed, but the control plane cannot be identified \u2014 check OuterLayer connectivity/config";
|
|
99
96
|
function designationAuthRejectedMessage(credential) {
|
|
100
97
|
return credential.startsWith("olu_") ? `the OuterLayer login was rejected (401/403) \u2014 run \`${cliInvocation()} login\` to sign in again` : "the OuterLayer API key was rejected (401/403) \u2014 check apiKey in ~/.outerlayer/config.json";
|
|
101
98
|
}
|
|
102
|
-
var PARTIAL_WRITE_MESSAGE = "control-plane content could not be fully written
|
|
103
|
-
var OVERLAY_FAILED_MESSAGE = "control-plane content was written but the maintained skills could not be refreshed
|
|
99
|
+
var PARTIAL_WRITE_MESSAGE = "control-plane content could not be fully written";
|
|
100
|
+
var OVERLAY_FAILED_MESSAGE = "control-plane content was written but the maintained skills could not be refreshed";
|
|
104
101
|
function isStagingWriteFault(message) {
|
|
105
102
|
return message === PARTIAL_WRITE_MESSAGE || message === OVERLAY_FAILED_MESSAGE;
|
|
106
103
|
}
|
|
107
|
-
var COMMIT_GUARD_FOREIGN_NOT_INSTALLED_MESSAGE = `the materialized-context commit guard is NOT installed \u2014 a pre-commit hook this clone did not write occupies that slot \u2014 resolve the conflict or run \`${cliInvocation()} hooks install-git\``;
|
|
108
|
-
var COMMIT_GUARD_HOOKSPATH_NOT_INSTALLED_MESSAGE = `the materialized-context commit guard is NOT installed \u2014 hooks are managed via core.hooksPath, which this clone never writes to automatically \u2014 adopt it yourself: \`${cliInvocation()} hooks install-git --print\``;
|
|
109
|
-
function guardNotInstalledMessage(guard) {
|
|
110
|
-
if (guard.adopted) return void 0;
|
|
111
|
-
if (guard.status === "skipped-foreign") return COMMIT_GUARD_FOREIGN_NOT_INSTALLED_MESSAGE;
|
|
112
|
-
if (guard.status === "skipped-custom-hooks-path") return COMMIT_GUARD_HOOKSPATH_NOT_INSTALLED_MESSAGE;
|
|
113
|
-
return void 0;
|
|
114
|
-
}
|
|
115
|
-
var FAILURE_DEBOUNCE_MS = 2 * 60 * 1e3;
|
|
116
|
-
function hasGovernedEvidence(hasPin, manifest) {
|
|
117
|
-
return hasPin || manifest !== void 0;
|
|
118
|
-
}
|
|
119
104
|
function hasSymlinkComponent(root, relPath) {
|
|
120
105
|
let current = root;
|
|
121
106
|
for (const segment of relPath.split("/")) {
|
|
@@ -130,13 +115,11 @@ function hasSymlinkComponent(root, relPath) {
|
|
|
130
115
|
}
|
|
131
116
|
return false;
|
|
132
117
|
}
|
|
133
|
-
function unreachableMessage(
|
|
134
|
-
return
|
|
118
|
+
function unreachableMessage() {
|
|
119
|
+
return "the control plane is unreachable";
|
|
135
120
|
}
|
|
136
|
-
function noAccessMessage(
|
|
137
|
-
|
|
138
|
-
const remedy = " \u2014 check your git credentials (SSH key or token) and org/SSO access, then retry";
|
|
139
|
-
return lastGoodSha ? `${base}; running on previously materialized context at \`${lastGoodSha.slice(0, 7)}\`${remedy}` : `${base}; running with repository defaults${remedy}`;
|
|
121
|
+
function noAccessMessage() {
|
|
122
|
+
return "you do not have access to the control plane \u2014 check your git credentials (SSH key or token) and org/SSO access, then retry";
|
|
140
123
|
}
|
|
141
124
|
function classifyGitFailure(stderr) {
|
|
142
125
|
if (/authentication failed|permission denied \(publickey\)|\b403\b|saml sso|access denied/i.test(stderr)) {
|
|
@@ -157,38 +140,17 @@ async function materializeContext(deps) {
|
|
|
157
140
|
if (gitCommonDir === void 0) {
|
|
158
141
|
return { status: "not-a-repo", sha: null, verification: "none" };
|
|
159
142
|
}
|
|
160
|
-
const pin = readPin(repoRoot);
|
|
161
|
-
const hasPin = pin !== void 0 || pinExists(repoRoot);
|
|
162
143
|
const record = (sha2, verification, repository2, ref2) => {
|
|
144
|
+
if (deps.sessionId === void 0) return;
|
|
163
145
|
appendContextProvenance(
|
|
164
146
|
{ t: new Date(now()).toISOString(), sessionId: deps.sessionId, repoRoot, repository: repository2, ref: ref2, sha: sha2, verification },
|
|
165
147
|
home
|
|
166
148
|
);
|
|
167
149
|
};
|
|
168
150
|
const selfOutcome = () => {
|
|
169
|
-
if (hasPin) {
|
|
170
|
-
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "not-governed", message: NOT_GOVERNED_MESSAGE });
|
|
171
|
-
return { status: "not-governed", message: NOT_GOVERNED_MESSAGE, sha: null, verification: "none" };
|
|
172
|
-
}
|
|
173
151
|
clearDegraded(gitCommonDir);
|
|
174
152
|
return { status: "self", sha: null, verification: "none" };
|
|
175
153
|
};
|
|
176
|
-
const hold = readBuildHold(gitCommonDir);
|
|
177
|
-
if (hold !== void 0) {
|
|
178
|
-
const heldManifest = readContextManifest(gitCommonDir);
|
|
179
|
-
if (heldManifest !== void 0 && heldManifest.sha === hold.sha && pin?.sha === hold.sha && manifestFilesPresent(repoRoot, heldManifest)) {
|
|
180
|
-
ensureContextExcludes(gitCommonDir);
|
|
181
|
-
recordMaintainedOverlay(repoRoot, gitCommonDir, heldManifest);
|
|
182
|
-
const guardMessage2 = guardNotInstalledMessage(ensurePreCommitGuardHook(repoRoot, gitCommonDir));
|
|
183
|
-
record(hold.sha, "verified", hold.repository, hold.ref);
|
|
184
|
-
return {
|
|
185
|
-
status: "debounced",
|
|
186
|
-
sha: hold.sha,
|
|
187
|
-
verification: "verified",
|
|
188
|
-
...guardMessage2 ? { message: guardMessage2 } : {}
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
154
|
const ownRepoName = deriveOwnRepoName(git, repoRoot);
|
|
193
155
|
if (ownRepoName === void 0) {
|
|
194
156
|
return selfOutcome();
|
|
@@ -196,7 +158,7 @@ async function materializeContext(deps) {
|
|
|
196
158
|
const designation = deps.pinnedSource === void 0 ? await resolveDesignation({ git, fetchImpl, home, cloud: deps.cloud, now, gitCommonDir, ownRepoName, repoRoot, lookup: deps.designationLookup ?? { timeoutMs: 2e3, attempts: 1 } }) : deps.pinnedSource === null ? { status: "self" } : { status: "governed", ...deps.pinnedSource };
|
|
197
159
|
const answered = { designation: "answered" };
|
|
198
160
|
if (designation.status === "self") {
|
|
199
|
-
if (designation.unanswered !== void 0
|
|
161
|
+
if (designation.unanswered !== void 0) {
|
|
200
162
|
const { authRejected, gatewayTooOld } = designation.unanswered;
|
|
201
163
|
const message = authRejected ?? (gatewayTooOld ? GATEWAY_TOO_OLD_MESSAGE : void 0);
|
|
202
164
|
if (message !== void 0) {
|
|
@@ -215,11 +177,6 @@ async function materializeContext(deps) {
|
|
|
215
177
|
}
|
|
216
178
|
if (designation.status === "unknown") {
|
|
217
179
|
const message = designation.authRejected ?? (designation.gatewayTooOld ? GATEWAY_TOO_OLD_MESSAGE : CANNOT_IDENTIFY_MESSAGE);
|
|
218
|
-
if (hasPin) {
|
|
219
|
-
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "designation-unverified", message });
|
|
220
|
-
record(null, "none");
|
|
221
|
-
return { status: "designation-unverified", message, sha: null, verification: "none", designation: "unknown" };
|
|
222
|
-
}
|
|
223
180
|
if (designation.authRejected || designation.gatewayTooOld) {
|
|
224
181
|
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "designation-unverified", message });
|
|
225
182
|
}
|
|
@@ -246,8 +203,6 @@ async function materializeContext(deps) {
|
|
|
246
203
|
const ref = designation.ref;
|
|
247
204
|
const unverifiedIdentity = designation.unverifiedIdentity;
|
|
248
205
|
const storedSha = designation.sha;
|
|
249
|
-
const manifest = readContextManifest(gitCommonDir);
|
|
250
|
-
const evidenced = hasGovernedEvidence(hasPin, manifest) || !unverifiedIdentity;
|
|
251
206
|
const clearOrFlagIdentity = () => {
|
|
252
207
|
if (unverifiedIdentity) {
|
|
253
208
|
writeDegraded(gitCommonDir, {
|
|
@@ -261,39 +216,6 @@ async function materializeContext(deps) {
|
|
|
261
216
|
clearDegraded(gitCommonDir);
|
|
262
217
|
}
|
|
263
218
|
};
|
|
264
|
-
if (manifest !== void 0 && manifest.sha === storedSha && pin?.sha === storedSha && manifestFilesPresent(repoRoot, manifest)) {
|
|
265
|
-
touchLastCheck(gitCommonDir, now());
|
|
266
|
-
clearOrFlagIdentity();
|
|
267
|
-
ensureContextExcludes(gitCommonDir);
|
|
268
|
-
recordMaintainedOverlay(repoRoot, gitCommonDir, manifest);
|
|
269
|
-
const guardMessage2 = guardNotInstalledMessage(ensurePreCommitGuardHook(repoRoot, gitCommonDir));
|
|
270
|
-
writeSourceCache(gitCommonDir, {
|
|
271
|
-
checkedAt: new Date(now()).toISOString(),
|
|
272
|
-
status: "governed",
|
|
273
|
-
repository,
|
|
274
|
-
ref,
|
|
275
|
-
sha: storedSha,
|
|
276
|
-
ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS
|
|
277
|
-
});
|
|
278
|
-
const verification = unverifiedIdentity ? "unverified" : "verified";
|
|
279
|
-
record(storedSha, verification, repository, ref);
|
|
280
|
-
return {
|
|
281
|
-
status: "debounced",
|
|
282
|
-
sha: storedSha,
|
|
283
|
-
verification,
|
|
284
|
-
...guardMessage2 ? { message: guardMessage2 } : {}
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
const recentFailure = readDegraded(gitCommonDir);
|
|
288
|
-
if (recentFailure && (recentFailure.kind === "unreachable" || recentFailure.kind === "no-access") && recentFailure.repository === repository && recentFailure.ref === ref && now() - Date.parse(recentFailure.at) < FAILURE_DEBOUNCE_MS) {
|
|
289
|
-
const lastGood = manifest?.sha ?? null;
|
|
290
|
-
const verification = lastGood ? "unverified" : "none";
|
|
291
|
-
if (evidenced) {
|
|
292
|
-
record(lastGood, verification, repository, ref);
|
|
293
|
-
return { status: recentFailure.kind, message: recentFailure.message, sha: lastGood, verification };
|
|
294
|
-
}
|
|
295
|
-
return { status: recentFailure.kind, sha: null, verification: "none" };
|
|
296
|
-
}
|
|
297
219
|
const remoteUrl = deps.resolveControlPlaneUrl ? deps.resolveControlPlaneUrl(repository, ref, repoRoot) : buildControlPlaneUrl(git, repoRoot, repository);
|
|
298
220
|
const cacheHost = parseRemoteHost(remoteUrl).host || "unknown-host";
|
|
299
221
|
const cacheRepoDir = ensureBareCache(git, home, repository, cacheHost);
|
|
@@ -309,52 +231,25 @@ async function materializeContext(deps) {
|
|
|
309
231
|
const commitNote = (message) => `could not fetch commit \`${storedSha.slice(0, 7)}\` of ${repository}; ${message}`;
|
|
310
232
|
if (!fetchResult.ok) {
|
|
311
233
|
const kind = classifyGitFailure(fetchResult.stderr);
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (evidenced) {
|
|
317
|
-
record(lastGood, verification, repository, ref);
|
|
318
|
-
return { status: kind, message: doctorMessage, sha: lastGood, verification };
|
|
319
|
-
}
|
|
320
|
-
return { status: kind, sha: null, verification: "none" };
|
|
234
|
+
const doctorMessage = commitNote(kind === "no-access" ? noAccessMessage() : unreachableMessage());
|
|
235
|
+
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind, message: doctorMessage, repository, ref });
|
|
236
|
+
record(null, "none", repository, ref);
|
|
237
|
+
return { status: kind, message: doctorMessage, sha: null, verification: "none" };
|
|
321
238
|
}
|
|
322
239
|
const fetchedSha = gitText(git, cacheRepoDir, ["rev-parse", localRef], 2e3);
|
|
323
240
|
if (fetchedSha !== storedSha) {
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if (evidenced) {
|
|
329
|
-
record(lastGood, verification, repository, ref);
|
|
330
|
-
return { status: "unreachable", message: doctorMessage, sha: lastGood, verification };
|
|
331
|
-
}
|
|
332
|
-
return { status: "unreachable", sha: null, verification: "none" };
|
|
241
|
+
const doctorMessage = commitNote(unreachableMessage());
|
|
242
|
+
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "unreachable", message: doctorMessage, repository, ref });
|
|
243
|
+
record(null, "none", repository, ref);
|
|
244
|
+
return { status: "unreachable", message: doctorMessage, sha: null, verification: "none" };
|
|
333
245
|
}
|
|
334
246
|
const sha = fetchedSha;
|
|
335
|
-
const tracked = git(["ls-files", "-z", "--", "AGENTS.md", ".claude", ".outerlayer"], { cwd: repoRoot, timeoutMs: 2e3 });
|
|
336
|
-
if (tracked.ok && tracked.stdout.length > 0) {
|
|
337
|
-
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "adoption-conflict", message: ADOPTION_MESSAGE, repository, ref });
|
|
338
|
-
const lastGood = manifest?.sha ?? null;
|
|
339
|
-
record(lastGood, lastGood ? "unverified" : "none", repository, ref);
|
|
340
|
-
return { status: "adoption-conflict", message: ADOPTION_MESSAGE, sha: lastGood, verification: lastGood ? "unverified" : "none" };
|
|
341
|
-
}
|
|
342
247
|
const files = listMaterializedFiles(git, cacheRepoDir, sha);
|
|
343
248
|
const writeResult = writeFilesVerbatim(git, cacheRepoDir, files, repoRoot);
|
|
344
249
|
const partialWrite = () => {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
at: new Date(now()).toISOString(),
|
|
349
|
-
kind: "unreachable",
|
|
350
|
-
message: PARTIAL_WRITE_MESSAGE,
|
|
351
|
-
repository,
|
|
352
|
-
ref,
|
|
353
|
-
lastGoodSha: lastGood ?? void 0
|
|
354
|
-
});
|
|
355
|
-
if (!evidenced) return { status: "unreachable", sha: null, verification: "none" };
|
|
356
|
-
record(lastGood, verification, repository, ref);
|
|
357
|
-
return { status: "unreachable", message: PARTIAL_WRITE_MESSAGE, sha: lastGood, verification };
|
|
250
|
+
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "unreachable", message: PARTIAL_WRITE_MESSAGE, repository, ref });
|
|
251
|
+
record(null, "none", repository, ref);
|
|
252
|
+
return { status: "unreachable", message: PARTIAL_WRITE_MESSAGE, sha: null, verification: "none" };
|
|
358
253
|
};
|
|
359
254
|
if (!writeResult.ok) {
|
|
360
255
|
return partialWrite();
|
|
@@ -369,35 +264,12 @@ async function materializeContext(deps) {
|
|
|
369
264
|
overlayFailed = true;
|
|
370
265
|
}
|
|
371
266
|
const writtenPaths = [.../* @__PURE__ */ new Set([...writeResult.writtenPaths, ...overlayPaths])].filter((path) => !retiredPaths.has(path));
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
writeContextManifest(gitCommonDir, { schemaVersion: 1, sha, files: writtenPaths, materializedAt: new Date(now()).toISOString() });
|
|
375
|
-
writeDegraded(gitCommonDir, {
|
|
376
|
-
at: new Date(now()).toISOString(),
|
|
377
|
-
kind: "unreachable",
|
|
378
|
-
message: OVERLAY_FAILED_MESSAGE,
|
|
379
|
-
repository,
|
|
380
|
-
ref,
|
|
381
|
-
lastGoodSha: sha
|
|
382
|
-
});
|
|
383
|
-
if (!evidenced) return { status: "unreachable", sha: null, verification: "none" };
|
|
267
|
+
if (overlayFailed) {
|
|
268
|
+
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "unreachable", message: OVERLAY_FAILED_MESSAGE, repository, ref });
|
|
384
269
|
record(sha, "unverified", repository, ref);
|
|
385
270
|
return { status: "unreachable", message: OVERLAY_FAILED_MESSAGE, sha, verification: "unverified" };
|
|
386
271
|
}
|
|
387
|
-
|
|
388
|
-
return partialWrite();
|
|
389
|
-
}
|
|
390
|
-
const newManifest = {
|
|
391
|
-
schemaVersion: 1,
|
|
392
|
-
sha,
|
|
393
|
-
files: writtenPaths,
|
|
394
|
-
materializedAt: new Date(now()).toISOString()
|
|
395
|
-
};
|
|
396
|
-
writeContextManifest(gitCommonDir, newManifest);
|
|
397
|
-
ensureContextExcludes(gitCommonDir);
|
|
398
|
-
const guardMessage = guardNotInstalledMessage(ensurePreCommitGuardHook(repoRoot, gitCommonDir));
|
|
399
|
-
writePinIfChanged(repoRoot, sha);
|
|
400
|
-
touchLastCheck(gitCommonDir, now());
|
|
272
|
+
writeContextManifest(gitCommonDir, { schemaVersion: 1, sha, files: writtenPaths, materializedAt: new Date(now()).toISOString() });
|
|
401
273
|
clearOrFlagIdentity();
|
|
402
274
|
writeSourceCache(gitCommonDir, {
|
|
403
275
|
checkedAt: new Date(now()).toISOString(),
|
|
@@ -408,27 +280,7 @@ async function materializeContext(deps) {
|
|
|
408
280
|
ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS
|
|
409
281
|
});
|
|
410
282
|
record(sha, "verified", repository, ref);
|
|
411
|
-
return {
|
|
412
|
-
status: "materialized",
|
|
413
|
-
sha,
|
|
414
|
-
verification: "verified",
|
|
415
|
-
...guardMessage ? { message: guardMessage } : {}
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
function recordMaintainedOverlay(repoRoot, gitCommonDir, manifest) {
|
|
419
|
-
let overlayPaths;
|
|
420
|
-
let retired;
|
|
421
|
-
try {
|
|
422
|
-
retired = new Set(removeRetiredSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel)));
|
|
423
|
-
overlayPaths = overlayMaintainedSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel));
|
|
424
|
-
} catch {
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
const known = new Set(manifest.files);
|
|
428
|
-
const added = overlayPaths.filter((path) => !known.has(path));
|
|
429
|
-
if (added.length > 0 || retired.size > 0) {
|
|
430
|
-
writeContextManifest(gitCommonDir, { ...manifest, files: [...manifest.files.filter((path) => !retired.has(path)), ...added] });
|
|
431
|
-
}
|
|
283
|
+
return { status: "materialized", sha, verification: "verified" };
|
|
432
284
|
}
|
|
433
285
|
async function resolveDesignation(ctx) {
|
|
434
286
|
const cache = readSourceCache(ctx.gitCommonDir);
|
|
@@ -646,51 +498,5 @@ function writeFilesVerbatim(git, cacheRepoDir, files, workpieceRoot) {
|
|
|
646
498
|
}
|
|
647
499
|
return { writtenPaths, ok: !anySkipped };
|
|
648
500
|
}
|
|
649
|
-
function isDeletableManifestPath(rel) {
|
|
650
|
-
if (isAbsolute(rel)) return false;
|
|
651
|
-
if (rel.split("/").some((segment) => segment === "..")) return false;
|
|
652
|
-
return rel === "AGENTS.md" || rel.startsWith(".claude/") || rel.startsWith(".outerlayer/");
|
|
653
|
-
}
|
|
654
|
-
function deleteRemovedFiles(workpieceRoot, oldFiles, newFiles) {
|
|
655
|
-
const keep = new Set(newFiles);
|
|
656
|
-
const dirsToPrune = /* @__PURE__ */ new Set();
|
|
657
|
-
const skipped = [];
|
|
658
|
-
for (const rel of oldFiles) {
|
|
659
|
-
if (keep.has(rel)) continue;
|
|
660
|
-
if (!isDeletableManifestPath(rel)) continue;
|
|
661
|
-
if (hasSymlinkComponent(workpieceRoot, rel)) {
|
|
662
|
-
skipped.push(rel);
|
|
663
|
-
continue;
|
|
664
|
-
}
|
|
665
|
-
const abs = join(workpieceRoot, rel);
|
|
666
|
-
try {
|
|
667
|
-
unlinkSync(abs);
|
|
668
|
-
dirsToPrune.add(dirname(abs));
|
|
669
|
-
} catch {
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
for (const dir of dirsToPrune) {
|
|
673
|
-
pruneEmptyDirs(dir, workpieceRoot);
|
|
674
|
-
}
|
|
675
|
-
return { skipped };
|
|
676
|
-
}
|
|
677
|
-
function pruneEmptyDirs(dir, stopAt) {
|
|
678
|
-
let current = dir;
|
|
679
|
-
while (current !== stopAt && current.startsWith(stopAt) && relative(stopAt, current) !== "") {
|
|
680
|
-
let entries;
|
|
681
|
-
try {
|
|
682
|
-
entries = readdirSync(current);
|
|
683
|
-
} catch {
|
|
684
|
-
return;
|
|
685
|
-
}
|
|
686
|
-
if (entries.length > 0) return;
|
|
687
|
-
try {
|
|
688
|
-
rmSync(current, { recursive: false });
|
|
689
|
-
} catch {
|
|
690
|
-
return;
|
|
691
|
-
}
|
|
692
|
-
current = dirname(current);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
501
|
|
|
696
|
-
export { defaultGitRunner,
|
|
502
|
+
export { defaultGitRunner, isStagingWriteFault, lookupGoverningSource, materializeContext, parseOwnerRepo, resolveGitCommonDir };
|