@outerlayer/cli 0.15.0 → 0.17.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.
- package/CHANGELOG.md +34 -0
- package/README.md +11 -11
- package/dist/{agent-setup-CN2HUBEJ.js → agent-setup-T624CWPD.js} +8 -7
- package/dist/artifact-link-cmd-2F47LT7F.js +24 -0
- package/dist/build-info.json +1 -1
- package/dist/{check-2JSSXCKJ.js → check-5XE7XMC4.js} +22 -19
- package/dist/{chunk-HFKKFTXU.js → chunk-2MNPHL23.js} +19 -11
- package/dist/{chunk-YDSMROTB.js → chunk-3NSNIIBE.js} +8 -4
- package/dist/{chunk-FOJGZYFC.js → chunk-42ZI52JW.js} +1 -1
- package/dist/{chunk-NPQWKGUA.js → chunk-6Y5RUTHO.js} +1 -1
- package/dist/{chunk-PQUM37BK.js → chunk-BWQ66M6N.js} +1 -1
- package/dist/chunk-C5Y5ZJJZ.js +88 -0
- package/dist/{chunk-ASOSIKA4.js → chunk-G5NPRL2K.js} +27 -6
- package/dist/{chunk-QLTYTPYU.js → chunk-HGECYFEI.js} +64 -7
- package/dist/{chunk-SXWS25JC.js → chunk-KG5ECZGJ.js} +6 -6
- package/dist/{chunk-F7GBYX2P.js → chunk-LWSJQJC6.js} +18 -4
- package/dist/{chunk-UUDDPNRJ.js → chunk-MAK5LYRF.js} +33 -10
- package/dist/{chunk-MTF3PHVZ.js → chunk-NBGDBTO2.js} +3 -3
- package/dist/{chunk-KFRM23WD.js → chunk-NNRTPG7X.js} +2 -2
- package/dist/{chunk-MSASO5O4.js → chunk-NWQTTSBB.js} +1 -1
- package/dist/{chunk-2M63GG56.js → chunk-OHVJA253.js} +1 -1
- package/dist/{chunk-Z3NOIFDR.js → chunk-ONKJUM6R.js} +1 -1
- package/dist/{chunk-T5VPP6H7.js → chunk-OZGHL5Y5.js} +1 -1
- package/dist/{chunk-ZA5CHAFY.js → chunk-POJMEEJJ.js} +21 -4
- package/dist/{chunk-JR6ERP3M.js → chunk-S3NYLI2P.js} +3 -3
- package/dist/{chunk-HXLMZOKU.js → chunk-VQYBXPI7.js} +4 -4
- package/dist/{chunk-LCEXHCHD.js → chunk-WTE3MQML.js} +1 -1
- package/dist/{chunk-NXUH742G.js → chunk-WVUIRTWA.js} +10 -8
- package/dist/{chunk-JJEGKEFV.js → chunk-YU3VKZ5F.js} +1 -1
- package/dist/{chunk-3NLOVYJQ.js → chunk-YZ5F4PIS.js} +134 -38
- package/dist/{cli-RGGXQTWI.js → cli-A76AXELQ.js} +90 -79
- package/dist/{command-ETUAEXP2.js → command-R2QCVX55.js} +10 -9
- package/dist/{connect-cmd-JUAW6MU4.js → connect-cmd-JBKAQNSF.js} +1 -1
- package/dist/{context-adopt-PJUMW2EZ.js → context-adopt-NFHCLVUB.js} +5 -4
- package/dist/{context-materialize-FDHYKNDT.js → context-materialize-IV2TUUFO.js} +5 -4
- package/dist/{doctor-CORFPYY6.js → doctor-4TAIARIG.js} +15 -13
- package/dist/{emit-artifact-cmd-FOGNJXVR.js → emit-artifact-cmd-MPZVR56N.js} +4 -4
- package/dist/{emit-cmd-ZEYWLC2C.js → emit-cmd-IJ3GVRFD.js} +4 -3
- package/dist/{emit-criteria-cmd-HBP6XS5C.js → emit-criteria-cmd-EFGYI23V.js} +2 -2
- package/dist/{emit-finding-cmd-DLI4MKMN.js → emit-finding-cmd-5GF3V4LR.js} +160 -47
- package/dist/{emit-result-cmd-MUSL7GQA.js → emit-result-cmd-I4OADKMD.js} +4 -4
- package/dist/hidden-prompt-UXBFMQC5.js +68 -0
- package/dist/{hook-fast-WYQD6D7T.js → hook-fast-R4FVSZ2H.js} +1 -1
- package/dist/{import-capture-cmd-6QVCOIHK.js → import-capture-cmd-EQ35EARA.js} +3 -3
- package/dist/{import-ruler-cmd-KLRGRBCP.js → import-ruler-cmd-BGAZXCQM.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/{init-OPB7HHXO.js → init-6XPDRDTC.js} +12 -11
- package/dist/{init-MIC37V6J.js → init-PWU5YVL7.js} +54 -29
- package/dist/{init-cmd-JR3RKNFB.js → init-cmd-XAVO7HYZ.js} +11 -10
- package/dist/{init-update-O5YYFGF4.js → init-update-CVCWD6VS.js} +10 -9
- package/dist/{loop-QNSM5GXS.js → loop-FK3LPMMZ.js} +19 -18
- package/dist/{machine-IT6GG7FF.js → machine-SQXEBAM2.js} +10 -9
- package/dist/{runner-env-XTC53CHN.js → runner-env-EN7YE7QX.js} +1 -1
- package/dist/runner-key-6SLBI7PP.js +174 -0
- package/dist/{session-sender-4M247XSV.js → session-sender-FO3LCREV.js} +3 -3
- package/dist/{starter-pack-IB4UUIX3.js → starter-pack-KF66HGZR.js} +3 -3
- package/dist/{status-7ZX57OFJ.js → status-7VNQN5PW.js} +13 -12
- package/dist/{sync-cmd-UWD5JOFU.js → sync-cmd-GVPPFZ3G.js} +2 -2
- package/dist/{watch-DBNB7R6X.js → watch-23HSAEI6.js} +2 -2
- package/dist/{work-claim-cmd-A6IS6CQ7.js → work-claim-cmd-LKL3GHFQ.js} +5 -5
- package/dist/{work-cmd-EQSW5DTD.js → work-cmd-Z2WXLZPH.js} +3 -3
- package/dist/{work-comment-cmd-7VLKI7FN.js → work-comment-cmd-AWHP56M2.js} +3 -3
- package/dist/{work-open-pr-cmd-JEVD4HMQ.js → work-open-pr-cmd-IOM4AVQQ.js} +4 -4
- package/dist/{work-pr-cmd-L77K32WK.js → work-pr-cmd-HNEUIEN7.js} +3 -3
- package/package.json +1 -1
- package/skill-pack/maintained/{amend → outerlayer-amend}/SKILL.md +4 -2
- package/skill-pack/maintained/{outerlayer → outerlayer-cli}/SKILL.md +5 -3
- package/skill-pack/maintained/{emitting-evidence → outerlayer-evidence}/SKILL.md +5 -3
- package/skill-pack/maintained/{reporting-findings → outerlayer-findings}/SKILL.md +26 -30
- package/skill-pack/shipped.json +20 -4
- package/skill-pack/template/build/SKILL.md +7 -1
- package/skill-pack/template/build/references/agent-briefs.md +7 -1
- package/skill-pack/template/build/references/evidence.md +1 -1
- package/skill-pack/template/build/references/release.md +14 -12
- package/skill-pack/template/build/references/review-briefs.md +6 -0
- package/skill-pack/template/build/scripts/criterion-citations.mjs +8 -3
- package/skill-pack/template/build/scripts/record-criteria.mjs +8 -2
- package/skill-pack/template/spec/SKILL.md +2 -0
- package/skill-pack/template/writing-specs/SKILL.md +1 -1
- package/skill-pack/validators/acceptance-criteria.yaml +6 -5
- package/skill-pack/validators/code-review.yaml +6 -5
- package/dist/runner-key-7SSNMUBQ.js +0 -154
- /package/skill-pack/maintained/{outerlayer → outerlayer-cli}/references/open-pull-request.md +0 -0
- /package/skill-pack/maintained/{emitting-evidence → outerlayer-evidence}/references/agents-snippet.md +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { readPin, pinExists, readBuildHold, readContextManifest, manifestFilesPresent, writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, SOURCE_CACHE_TTL_SUCCESS_MS, isLastCheckFresh, readDegraded,
|
|
3
|
+
import { readPin, pinExists, readBuildHold, readContextManifest, manifestFilesPresent, writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, SOURCE_CACHE_TTL_SUCCESS_MS, touchLastCheck, isLastCheckFresh, readDegraded, clearDegraded, writeContextManifest, writePinIfChanged, readSourceCache, isSourceCacheFresh } from './chunk-WTE3MQML.js';
|
|
4
|
+
import { removeRetiredSkills } from './chunk-C5Y5ZJJZ.js';
|
|
4
5
|
import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
|
|
5
6
|
import { defaultFetch } from './chunk-YO4PSLVB.js';
|
|
6
7
|
import { withTokenHeader } from './chunk-BYT5O5RV.js';
|
|
7
|
-
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-
|
|
8
|
-
import { normalizeRepoName, parseGoverns, CONTEXT_SOURCE_CONFIG_PATH, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-
|
|
8
|
+
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-POJMEEJJ.js';
|
|
9
|
+
import { normalizeRepoName, parseGoverns, CONTEXT_SOURCE_CONFIG_PATH, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-OHVJA253.js';
|
|
9
10
|
import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
|
|
10
11
|
import { ensureContextExcludes, ensurePreCommitGuardHook } from './chunk-XCCLFVXM.js';
|
|
11
12
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
@@ -187,7 +188,7 @@ async function materializeContext(deps) {
|
|
|
187
188
|
if (ownRepoName === void 0) {
|
|
188
189
|
return selfOutcome();
|
|
189
190
|
}
|
|
190
|
-
const designation = await resolveDesignation({ git, fetchImpl, home, cloud: deps.cloud, now, gitCommonDir, ownRepoName, repoRoot });
|
|
191
|
+
const designation = await resolveDesignation({ git, fetchImpl, home, cloud: deps.cloud, now, gitCommonDir, ownRepoName, repoRoot, lookup: deps.designationLookup ?? { timeoutMs: 2e3, attempts: 1 } });
|
|
191
192
|
const answered = { designation: "answered" };
|
|
192
193
|
if (designation.status === "self") {
|
|
193
194
|
return { ...selfOutcome(), ...answered };
|
|
@@ -203,11 +204,12 @@ async function materializeContext(deps) {
|
|
|
203
204
|
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "designation-unverified", message });
|
|
204
205
|
}
|
|
205
206
|
writeSourceCache(gitCommonDir, { checkedAt: new Date(now()).toISOString(), status: "self", ttlMs: SOURCE_CACHE_TTL_RETRY_MS });
|
|
206
|
-
return { status: "self", sha: null, verification: "none", designation: "unknown", ...designation.authRejected ? { authRejected: true } : {} };
|
|
207
|
+
return { status: "self", sha: null, verification: "none", designation: "unknown", ...designation.authRejected ? { authRejected: true } : {}, lookupFailure: designation.lookupFailure };
|
|
207
208
|
}
|
|
208
209
|
let repository;
|
|
209
210
|
let ref;
|
|
210
211
|
let unverifiedIdentity;
|
|
212
|
+
let storedSha;
|
|
211
213
|
let preFetched;
|
|
212
214
|
let unreadableCandidates = [];
|
|
213
215
|
if (designation.status === "candidates") {
|
|
@@ -272,9 +274,10 @@ async function materializeContext(deps) {
|
|
|
272
274
|
repository = designation.repository;
|
|
273
275
|
ref = designation.ref;
|
|
274
276
|
unverifiedIdentity = designation.unverifiedIdentity;
|
|
277
|
+
storedSha = designation.sha;
|
|
275
278
|
}
|
|
276
279
|
const manifest = readContextManifest(gitCommonDir);
|
|
277
|
-
const evidenced = hasGovernedEvidence(hasPin, manifest);
|
|
280
|
+
const evidenced = hasGovernedEvidence(hasPin, manifest) || storedSha !== void 0 && !unverifiedIdentity;
|
|
278
281
|
const clearOrFlagIdentity = () => {
|
|
279
282
|
if (unverifiedIdentity) {
|
|
280
283
|
writeDegraded(gitCommonDir, {
|
|
@@ -294,7 +297,30 @@ async function materializeContext(deps) {
|
|
|
294
297
|
sha = preFetched.sha;
|
|
295
298
|
cacheRepoDir = preFetched.cacheRepoDir;
|
|
296
299
|
} else {
|
|
297
|
-
if (
|
|
300
|
+
if (storedSha !== void 0 && manifest !== void 0 && manifest.sha === storedSha && pin?.sha === storedSha && manifestFilesPresent(repoRoot, manifest)) {
|
|
301
|
+
touchLastCheck(gitCommonDir, now());
|
|
302
|
+
clearOrFlagIdentity();
|
|
303
|
+
ensureContextExcludes(gitCommonDir);
|
|
304
|
+
recordMaintainedOverlay(repoRoot, gitCommonDir, manifest);
|
|
305
|
+
const guardMessage2 = guardNotInstalledMessage(ensurePreCommitGuardHook(repoRoot, gitCommonDir));
|
|
306
|
+
writeSourceCache(gitCommonDir, {
|
|
307
|
+
checkedAt: new Date(now()).toISOString(),
|
|
308
|
+
status: "governed",
|
|
309
|
+
repository,
|
|
310
|
+
ref,
|
|
311
|
+
sha: storedSha,
|
|
312
|
+
ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS
|
|
313
|
+
});
|
|
314
|
+
const verification = unverifiedIdentity ? "unverified" : "verified";
|
|
315
|
+
record(storedSha, verification, repository, ref);
|
|
316
|
+
return {
|
|
317
|
+
status: "debounced",
|
|
318
|
+
sha: storedSha,
|
|
319
|
+
verification,
|
|
320
|
+
...guardMessage2 ? { message: guardMessage2 } : {}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (storedSha === void 0 && isLastCheckFresh(gitCommonDir, now()) && manifest !== void 0 && pin?.sha === manifest.sha && manifestFilesPresent(repoRoot, manifest)) {
|
|
298
324
|
const degraded = readDegraded(gitCommonDir);
|
|
299
325
|
const verification = degraded ? "unverified" : "verified";
|
|
300
326
|
ensureContextExcludes(gitCommonDir);
|
|
@@ -320,8 +346,8 @@ async function materializeContext(deps) {
|
|
|
320
346
|
}
|
|
321
347
|
const remoteUrl = deps.resolveControlPlaneUrl ? deps.resolveControlPlaneUrl(repository, ref, repoRoot) : buildControlPlaneUrl(git, repoRoot, repository);
|
|
322
348
|
const cacheHost = parseRemoteHost(remoteUrl).host || "unknown-host";
|
|
323
|
-
const lsRemote = git(["ls-remote", remoteUrl, ref], { cwd: repoRoot, timeoutMs: 2e3 });
|
|
324
|
-
if (lsRemote
|
|
349
|
+
const lsRemote = storedSha === void 0 ? git(["ls-remote", remoteUrl, ref], { cwd: repoRoot, timeoutMs: 2e3 }) : void 0;
|
|
350
|
+
if (lsRemote?.ok) {
|
|
325
351
|
const remoteSha = parseLsRemoteSha(lsRemote.stdout.toString("utf8"));
|
|
326
352
|
if (remoteSha && manifest !== void 0 && manifest.sha === remoteSha && pin?.sha === remoteSha && manifestFilesPresent(repoRoot, manifest)) {
|
|
327
353
|
touchLastCheck(gitCommonDir, now());
|
|
@@ -340,13 +366,21 @@ async function materializeContext(deps) {
|
|
|
340
366
|
}
|
|
341
367
|
}
|
|
342
368
|
cacheRepoDir = ensureBareCache(git, home, repository, cacheHost);
|
|
343
|
-
const localRef = `refs/outerlayer/${sanitizeRefName(ref)}`;
|
|
344
|
-
const
|
|
369
|
+
const localRef = storedSha === void 0 ? `refs/outerlayer/${sanitizeRefName(ref)}` : `refs/outerlayer/sha-${sanitizeRefName(storedSha)}`;
|
|
370
|
+
const wanted = storedSha === void 0 ? `+${ref}:${localRef}` : `+${storedSha}:${localRef}`;
|
|
371
|
+
const access = storedSha === void 0 ? void 0 : await deps.controlPlaneAccess?.([{ repository, ref }]);
|
|
372
|
+
const token = access !== void 0 && normalizeRepoName(access.repository) === normalizeRepoName(repository) ? access.token : void 0;
|
|
373
|
+
const fetchResult = git(["fetch", "--depth", "1", remoteUrl, wanted], {
|
|
374
|
+
cwd: cacheRepoDir,
|
|
375
|
+
timeoutMs: 1e4,
|
|
376
|
+
...token === void 0 ? {} : { env: (base) => withTokenHeader(base, remoteUrl, token) }
|
|
377
|
+
});
|
|
378
|
+
const commitNote = (message) => storedSha === void 0 ? message : `could not fetch commit \`${storedSha.slice(0, 7)}\` of ${repository}; ${message}`;
|
|
345
379
|
if (!fetchResult.ok) {
|
|
346
380
|
const kind = classifyGitFailure(fetchResult.stderr);
|
|
347
381
|
const lastGood = manifest?.sha ?? null;
|
|
348
382
|
const verification = lastGood ? "unverified" : "none";
|
|
349
|
-
const doctorMessage = kind === "no-access" ? noAccessMessage(lastGood) : unreachableMessage(lastGood);
|
|
383
|
+
const doctorMessage = commitNote(kind === "no-access" ? noAccessMessage(lastGood) : unreachableMessage(lastGood));
|
|
350
384
|
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind, message: doctorMessage, repository, ref, lastGoodSha: lastGood ?? void 0 });
|
|
351
385
|
if (evidenced) {
|
|
352
386
|
record(lastGood, verification, repository, ref);
|
|
@@ -355,10 +389,10 @@ async function materializeContext(deps) {
|
|
|
355
389
|
return { status: kind, sha: null, verification: "none" };
|
|
356
390
|
}
|
|
357
391
|
const fetchedSha = gitText(git, cacheRepoDir, ["rev-parse", localRef], 2e3);
|
|
358
|
-
if (fetchedSha === void 0) {
|
|
392
|
+
if (fetchedSha === void 0 || storedSha !== void 0 && fetchedSha !== storedSha) {
|
|
359
393
|
const lastGood = manifest?.sha ?? null;
|
|
360
394
|
const verification = lastGood ? "unverified" : "none";
|
|
361
|
-
const doctorMessage = unreachableMessage(lastGood);
|
|
395
|
+
const doctorMessage = commitNote(unreachableMessage(lastGood));
|
|
362
396
|
writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind: "unreachable", message: doctorMessage, repository, ref, lastGoodSha: lastGood ?? void 0 });
|
|
363
397
|
if (evidenced) {
|
|
364
398
|
record(lastGood, verification, repository, ref);
|
|
@@ -367,10 +401,12 @@ async function materializeContext(deps) {
|
|
|
367
401
|
return { status: "unreachable", sha: null, verification: "none" };
|
|
368
402
|
}
|
|
369
403
|
sha = fetchedSha;
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
404
|
+
const governed = storedSha !== void 0 || (() => {
|
|
405
|
+
const configContent = readBlobAtPath(git, cacheRepoDir, sha, CONTEXT_SOURCE_CONFIG_PATH);
|
|
406
|
+
const parsedGoverns = configContent === void 0 ? { governs: [] } : parseGoverns(configContent);
|
|
407
|
+
const governsList = "error" in parsedGoverns ? [] : parsedGoverns.governs;
|
|
408
|
+
return governsList.some((r) => normalizeRepoName(r) === normalizeRepoName(ownRepoName));
|
|
409
|
+
})();
|
|
374
410
|
if (!governed) {
|
|
375
411
|
writeSourceCache(gitCommonDir, { checkedAt: new Date(now()).toISOString(), status: "self", ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS });
|
|
376
412
|
if (hasPin) {
|
|
@@ -409,13 +445,15 @@ async function materializeContext(deps) {
|
|
|
409
445
|
return partialWrite();
|
|
410
446
|
}
|
|
411
447
|
let overlayPaths = [];
|
|
448
|
+
let retiredPaths = /* @__PURE__ */ new Set();
|
|
412
449
|
let overlayFailed = false;
|
|
413
450
|
try {
|
|
451
|
+
retiredPaths = new Set(removeRetiredSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel)));
|
|
414
452
|
overlayPaths = overlayMaintainedSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel));
|
|
415
453
|
} catch {
|
|
416
454
|
overlayFailed = true;
|
|
417
455
|
}
|
|
418
|
-
const writtenPaths = [.../* @__PURE__ */ new Set([...writeResult.writtenPaths, ...overlayPaths])];
|
|
456
|
+
const writtenPaths = [.../* @__PURE__ */ new Set([...writeResult.writtenPaths, ...overlayPaths])].filter((path) => !retiredPaths.has(path));
|
|
419
457
|
const deleteResult = manifest ? deleteRemovedFiles(repoRoot, manifest.files, writtenPaths) : { skipped: [] };
|
|
420
458
|
if (overlayFailed && deleteResult.skipped.length === 0) {
|
|
421
459
|
writeContextManifest(gitCommonDir, { schemaVersion: 1, sha, files: writtenPaths, materializedAt: new Date(now()).toISOString() });
|
|
@@ -446,7 +484,14 @@ async function materializeContext(deps) {
|
|
|
446
484
|
writePinIfChanged(repoRoot, sha);
|
|
447
485
|
touchLastCheck(gitCommonDir, now());
|
|
448
486
|
clearOrFlagIdentity();
|
|
449
|
-
writeSourceCache(gitCommonDir, {
|
|
487
|
+
writeSourceCache(gitCommonDir, {
|
|
488
|
+
checkedAt: new Date(now()).toISOString(),
|
|
489
|
+
status: "governed",
|
|
490
|
+
repository,
|
|
491
|
+
ref,
|
|
492
|
+
...storedSha === void 0 ? {} : { sha: storedSha },
|
|
493
|
+
ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS
|
|
494
|
+
});
|
|
450
495
|
record(sha, "verified", repository, ref);
|
|
451
496
|
return {
|
|
452
497
|
status: "materialized",
|
|
@@ -458,21 +503,26 @@ async function materializeContext(deps) {
|
|
|
458
503
|
}
|
|
459
504
|
function recordMaintainedOverlay(repoRoot, gitCommonDir, manifest) {
|
|
460
505
|
let overlayPaths;
|
|
506
|
+
let retired;
|
|
461
507
|
try {
|
|
508
|
+
retired = new Set(removeRetiredSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel)));
|
|
462
509
|
overlayPaths = overlayMaintainedSkills(repoRoot, (rel) => hasSymlinkComponent(repoRoot, rel));
|
|
463
510
|
} catch {
|
|
464
511
|
return;
|
|
465
512
|
}
|
|
466
513
|
const known = new Set(manifest.files);
|
|
467
514
|
const added = overlayPaths.filter((path) => !known.has(path));
|
|
468
|
-
if (added.length > 0
|
|
515
|
+
if (added.length > 0 || retired.size > 0) {
|
|
516
|
+
writeContextManifest(gitCommonDir, { ...manifest, files: [...manifest.files.filter((path) => !retired.has(path)), ...added] });
|
|
517
|
+
}
|
|
469
518
|
}
|
|
470
519
|
async function resolveDesignation(ctx) {
|
|
471
520
|
const cache = readSourceCache(ctx.gitCommonDir);
|
|
472
|
-
if (cache && isSourceCacheFresh(cache, ctx.now())) {
|
|
521
|
+
if (cache && isSourceCacheFresh(cache, ctx.now()) && !(cache.status === "governed" && cache.sha !== void 0)) {
|
|
473
522
|
return cache.status === "governed" && cache.repository && cache.ref ? { status: "governed", repository: cache.repository, ref: cache.ref } : { status: "self" };
|
|
474
523
|
}
|
|
475
524
|
let authRejected;
|
|
525
|
+
let lookupFailure;
|
|
476
526
|
const destination = resolveGatewayCredentials({
|
|
477
527
|
home: ctx.home,
|
|
478
528
|
env: {},
|
|
@@ -480,15 +530,27 @@ async function resolveDesignation(ctx) {
|
|
|
480
530
|
...ctx.cloud === void 0 ? {} : { url: ctx.cloud.url, apiKey: ctx.cloud.apiKey, appId: ctx.cloud.appId }
|
|
481
531
|
});
|
|
482
532
|
if (destination.ok) {
|
|
483
|
-
const
|
|
533
|
+
const lookup = await fetchContextSource(
|
|
484
534
|
{ url: destination.url, apiKey: destination.credential, appId: destination.appId },
|
|
485
535
|
ctx.ownRepoName,
|
|
486
536
|
ctx.fetchImpl,
|
|
487
|
-
|
|
488
|
-
authRejected = designationAuthRejectedMessage(destination.credential);
|
|
489
|
-
}
|
|
537
|
+
ctx.lookup
|
|
490
538
|
);
|
|
491
|
-
if (
|
|
539
|
+
if (lookup.kind === "rejected") authRejected = designationAuthRejectedMessage(destination.credential);
|
|
540
|
+
if (lookup.kind === "failed") lookupFailure = lookup.failure;
|
|
541
|
+
if (lookup.kind === "answered") {
|
|
542
|
+
if (lookup.source !== void 0) {
|
|
543
|
+
if (lookup.source === null) {
|
|
544
|
+
writeSourceCache(ctx.gitCommonDir, {
|
|
545
|
+
checkedAt: new Date(ctx.now()).toISOString(),
|
|
546
|
+
status: "self",
|
|
547
|
+
ttlMs: SOURCE_CACHE_TTL_SUCCESS_MS
|
|
548
|
+
});
|
|
549
|
+
return { status: "self" };
|
|
550
|
+
}
|
|
551
|
+
return { status: "governed", repository: lookup.source.repository, ref: lookup.source.ref, sha: lookup.source.sha };
|
|
552
|
+
}
|
|
553
|
+
const sources = lookup.sources ?? [];
|
|
492
554
|
if (sources.length === 0) {
|
|
493
555
|
writeSourceCache(ctx.gitCommonDir, {
|
|
494
556
|
checkedAt: new Date(ctx.now()).toISOString(),
|
|
@@ -501,32 +563,66 @@ async function resolveDesignation(ctx) {
|
|
|
501
563
|
}
|
|
502
564
|
}
|
|
503
565
|
if (cache) {
|
|
504
|
-
return cache.status === "governed" && cache.repository && cache.ref ? {
|
|
566
|
+
return cache.status === "governed" && cache.repository && cache.ref ? {
|
|
567
|
+
status: "governed",
|
|
568
|
+
repository: cache.repository,
|
|
569
|
+
ref: cache.ref,
|
|
570
|
+
unverifiedIdentity: true,
|
|
571
|
+
...cache.sha === void 0 ? {} : { sha: cache.sha }
|
|
572
|
+
} : { status: "self" };
|
|
573
|
+
}
|
|
574
|
+
return { status: "unknown", authRejected, lookupFailure };
|
|
575
|
+
}
|
|
576
|
+
async function fetchContextSource(config, ownRepoName, fetchImpl, lookup) {
|
|
577
|
+
const url = `${config.url.replace(/\/$/, "")}/v1/context/source?repo=${encodeURIComponent(ownRepoName)}`;
|
|
578
|
+
for (let attempt = 1; ; attempt++) {
|
|
579
|
+
const outcome = await askContextSource(url, config, fetchImpl, lookup.timeoutMs);
|
|
580
|
+
if (outcome.kind !== "failed" || !isRetryable(outcome.failure) || attempt >= lookup.attempts) return outcome;
|
|
505
581
|
}
|
|
506
|
-
return { status: "unknown", authRejected };
|
|
507
582
|
}
|
|
508
|
-
|
|
583
|
+
function isRetryable(failure) {
|
|
584
|
+
return failure.kind !== "status" || failure.status >= 500;
|
|
585
|
+
}
|
|
586
|
+
async function askContextSource(url, config, fetchImpl, timeoutMs) {
|
|
509
587
|
const controller = new AbortController();
|
|
510
|
-
|
|
588
|
+
let timedOut = false;
|
|
589
|
+
const timer = setTimeout(() => {
|
|
590
|
+
timedOut = true;
|
|
591
|
+
controller.abort();
|
|
592
|
+
}, timeoutMs);
|
|
511
593
|
try {
|
|
512
|
-
const url = `${config.url.replace(/\/$/, "")}/v1/context/source?repo=${encodeURIComponent(ownRepoName)}`;
|
|
513
594
|
const res = await fetchImpl(url, {
|
|
514
595
|
headers: { Authorization: `Bearer ${config.apiKey}`, "x-outerlayer-app-id": config.appId },
|
|
515
596
|
signal: controller.signal
|
|
516
597
|
});
|
|
517
598
|
if (res.status === 401 || res.status === 403) {
|
|
518
|
-
|
|
519
|
-
return void 0;
|
|
599
|
+
return { kind: "rejected" };
|
|
520
600
|
}
|
|
521
|
-
if (!res.ok) return
|
|
601
|
+
if (!res.ok) return { kind: "failed", failure: { kind: "status", status: res.status } };
|
|
522
602
|
const body = await res.json();
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
603
|
+
const data = body.data;
|
|
604
|
+
const source = validSource(data?.source);
|
|
605
|
+
if (data === void 0 || data === null || source === void 0 && !Array.isArray(data.sources)) {
|
|
606
|
+
return { kind: "failed", failure: { kind: "network", message: "the answer named no sources" } };
|
|
607
|
+
}
|
|
608
|
+
return { kind: "answered", source, sources: data.sources };
|
|
609
|
+
} catch (err) {
|
|
610
|
+
return {
|
|
611
|
+
kind: "failed",
|
|
612
|
+
failure: timedOut ? { kind: "timeout", timeoutMs } : { kind: "network", message: err instanceof Error ? err.message : String(err) }
|
|
613
|
+
};
|
|
526
614
|
} finally {
|
|
527
615
|
clearTimeout(timer);
|
|
528
616
|
}
|
|
529
617
|
}
|
|
618
|
+
function validSource(source) {
|
|
619
|
+
if (source === null) return null;
|
|
620
|
+
const candidate = source;
|
|
621
|
+
if (typeof candidate?.repository === "string" && typeof candidate.ref === "string" && typeof candidate.sha === "string") {
|
|
622
|
+
return { repository: candidate.repository, ref: candidate.ref, sha: candidate.sha };
|
|
623
|
+
}
|
|
624
|
+
return void 0;
|
|
625
|
+
}
|
|
530
626
|
function resolveGitCommonDir(git, repoRoot) {
|
|
531
627
|
const abs = gitText(git, repoRoot, ["rev-parse", "--path-format=absolute", "--git-common-dir"], 2e3);
|
|
532
628
|
if (abs !== void 0) return abs;
|