wicked-crew 0.9.2 → 0.9.4
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/dist/api/delivery-assurance.d.ts +22 -1
- package/dist/api/delivery-assurance.d.ts.map +1 -1
- package/dist/api/delivery-assurance.js +66 -2
- package/dist/api/delivery-assurance.js.map +1 -1
- package/dist/api/routes.d.ts +148 -8
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +59 -19
- package/dist/api/routes.js.map +1 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +31 -31
- package/dist/api/server.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +32 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/service.js +1 -1
- package/dist/cli/service.js.map +1 -1
- package/dist/core/adapter.d.ts +21 -3
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +72 -18
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/ado-deliver-helper.d.ts +5 -0
- package/dist/core/ado-deliver-helper.d.ts.map +1 -1
- package/dist/core/ado-deliver-helper.js +50 -2
- package/dist/core/ado-deliver-helper.js.map +1 -1
- package/dist/core/deliver-credentials.d.ts +8 -4
- package/dist/core/deliver-credentials.d.ts.map +1 -1
- package/dist/core/deliver-credentials.js +25 -7
- package/dist/core/deliver-credentials.js.map +1 -1
- package/dist/core/deliver-text.d.ts +8 -0
- package/dist/core/deliver-text.d.ts.map +1 -1
- package/dist/core/deliver-text.js +16 -0
- package/dist/core/deliver-text.js.map +1 -1
- package/dist/core/deliver.d.ts +22 -18
- package/dist/core/deliver.d.ts.map +1 -1
- package/dist/core/deliver.js +168 -79
- package/dist/core/deliver.js.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/interactive/chat-events.d.ts +11 -20
- package/dist/interactive/chat-events.d.ts.map +1 -1
- package/dist/interactive/chat-events.js +69 -108
- package/dist/interactive/chat-events.js.map +1 -1
- package/dist/interactive/draft-events.d.ts +13 -46
- package/dist/interactive/draft-events.d.ts.map +1 -1
- package/dist/interactive/draft-events.js +81 -130
- package/dist/interactive/draft-events.js.map +1 -1
- package/dist/interactive/draft-skill.d.ts +11 -19
- package/dist/interactive/draft-skill.d.ts.map +1 -1
- package/dist/interactive/draft-skill.js +16 -31
- package/dist/interactive/draft-skill.js.map +1 -1
- package/dist/interactive/edit-events.d.ts +11 -21
- package/dist/interactive/edit-events.d.ts.map +1 -1
- package/dist/interactive/edit-events.js +70 -83
- package/dist/interactive/edit-events.js.map +1 -1
- package/dist/interactive/run-units.d.ts +91 -0
- package/dist/interactive/run-units.d.ts.map +1 -0
- package/dist/interactive/run-units.js +149 -0
- package/dist/interactive/run-units.js.map +1 -0
- package/dist/skills/core-closure.d.ts +26 -0
- package/dist/skills/core-closure.d.ts.map +1 -1
- package/dist/skills/core-closure.js +45 -0
- package/dist/skills/core-closure.js.map +1 -1
- package/dist/skills/phase-skill-gaps.d.ts +16 -71
- package/dist/skills/phase-skill-gaps.d.ts.map +1 -1
- package/dist/skills/phase-skill-gaps.js +16 -145
- package/dist/skills/phase-skill-gaps.js.map +1 -1
- package/dist/studio/assets/{index-BLYKfepE.css → index-BGfFmWw4.css} +1 -1
- package/dist/studio/assets/{index-BbXtfDnB.js → index-BMRUMU4X.js} +112 -112
- package/dist/studio/editors/wicked-page/editor.json +1 -1
- package/dist/studio/editors/wicked-page/index.html +1 -1
- package/dist/studio/index.html +2 -2
- package/dist/studio/testid-inventory.json +83 -5
- package/endpoint-manifest.json +1 -1
- package/package.json +3 -3
package/dist/core/deliver.js
CHANGED
|
@@ -40,11 +40,13 @@
|
|
|
40
40
|
* (f) the PR URL is the last line of the phase output.
|
|
41
41
|
*
|
|
42
42
|
* One deliberate change from the field version: NO gh account is baked into crew code (the
|
|
43
|
-
* overlay guarded a personal account). Instead
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
43
|
+
* overlay guarded a personal account). Instead the push identity is CONFIGURED (the deliver
|
|
44
|
+
* identity setting, the repository's pin, or the `GH_ACCOUNT` env var) and chosen PER COMMAND
|
|
45
|
+
* (crew#940): on a github.com origin the script reads that account's own token from gh's keyring
|
|
46
|
+
* and hands it to its gh calls and its git fetch/push alone, so gh's machine-wide active account
|
|
47
|
+
* never decides who pushes; an exported `GH_TOKEN` wins, and one that authenticates as another
|
|
48
|
+
* login is refused. It is disclosed on the deliver gate card and never switched at push time.
|
|
49
|
+
* Unset ⇒ whatever gh holds, said aloud.
|
|
48
50
|
*
|
|
49
51
|
* REVISION mode (DES-L9 / crew#550, `POST /runs {revisesPr}`): the run was based on an OPEN pull
|
|
50
52
|
* request's head branch; the script pushes `wicked/<run>` onto `refs/heads/<that branch>` (the PR
|
|
@@ -89,7 +91,7 @@ import { childEnvWithBootEstateDb } from './governance-store.js';
|
|
|
89
91
|
import { ADO_HELPER_JS } from './ado-deliver-helper.js';
|
|
90
92
|
import { ADO_PAT_ENV, ADO_SP_ENV, DELIVER_CREDENTIALS_MISSING_MARKER, adoRepoOf } from './deliver-credentials.js';
|
|
91
93
|
import { DELIVER_NOT_SHIPPED_HEADING, DELIVER_STRANDED_SENTINEL, ENV_TEMPLATE_SAFE_LINE_ERE, SCRATCH_DIRS, TOOL_ARTIFACT_DIRS } from './deliver-exclusions.js';
|
|
92
|
-
import { composeEmbeddedDeliverText, factsFromWorkflow, framedDeliverText, runUrlFor, configuredPublicOrigin, commitSubject, urlPathSegment, } from './deliver-text.js';
|
|
94
|
+
import { adoWorkItemIds, composeEmbeddedDeliverText, factsFromWorkflow, framedDeliverText, runUrlFor, configuredPublicOrigin, commitSubject, urlPathSegment, } from './deliver-text.js';
|
|
93
95
|
/**
|
|
94
96
|
* The content-address of wicked-core's built-in evidence floor (`builtin_floors::EVIDENCE_FLOOR_PIN`,
|
|
95
97
|
* criterion "the run left a change in its worktree (done is re-derived from the diff, never
|
|
@@ -190,21 +192,14 @@ export function deliverIdentityFor(settings, repoRef) {
|
|
|
190
192
|
return { login: pinned.trim(), source: 'repo' };
|
|
191
193
|
return { login: (settings.deliverIdentityLogin ?? '').trim(), source: 'setting' };
|
|
192
194
|
}
|
|
193
|
-
/**
|
|
194
|
-
*
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const spawnFailed = err !== null && typeof err.code !== 'number';
|
|
202
|
-
resolve({ out: `${String(stdout ?? '')}\n${String(stderr ?? '')}`, ok: !spawnFailed });
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
if (!res.ok)
|
|
206
|
-
return null;
|
|
207
|
-
return parseGhAuthStatusLogins(res.out);
|
|
195
|
+
/** (crew#940) The push identity a delivery pins: the configured login (the repository's pin or the
|
|
196
|
+
* setting), else `GH_ACCOUNT`; `null` = none. Pure over `env`. */
|
|
197
|
+
export function pushIdentityOf(configured, env = process.env) {
|
|
198
|
+
const c = (configured ?? '').trim();
|
|
199
|
+
if (c !== '')
|
|
200
|
+
return c;
|
|
201
|
+
const g = (env['GH_ACCOUNT'] ?? '').trim();
|
|
202
|
+
return g === '' ? null : g;
|
|
208
203
|
}
|
|
209
204
|
/** The logins in `gh auth status` text: "Logged in to <host> account <login>" (gh ≥ 2.40) or
|
|
210
205
|
* "Logged in to <host> as <login>" (older). Pure, for the tests. */
|
|
@@ -230,13 +225,34 @@ export function isSafeRefName(name) {
|
|
|
230
225
|
}
|
|
231
226
|
/** The one shape a PR URL may take before it is baked into the script and printed as the phase's
|
|
232
227
|
* last line (crew re-derives "delivered" from that line — `prUrlFrom`). */
|
|
233
|
-
const SAFE_PR_URL = /^https:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+\/pull\/[0-9]+$/;
|
|
228
|
+
const SAFE_PR_URL = /^https:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+\/pull\/[0-9]+$|^https:\/\/dev\.azure\.com\/[A-Za-z0-9._~%()-]+\/[A-Za-z0-9._~%()-]+\/_git\/[A-Za-z0-9._~%()-]+\/pullrequest\/[0-9]+$/;
|
|
234
229
|
/** The `bug` def's `fix` phase instructions — the SAME literal wicked-core's `bug_def()` carries
|
|
235
230
|
* (`BUG_FIX_SWEEP_INSTRUCTIONS`, DES-L9 BC-60 / core#432): both carriers are live (`deliver:pr`
|
|
236
231
|
* plans from this mirror, `deliver:none` from core's def), so one string, pinned by a test. Short
|
|
237
232
|
* (≤ 90 ASCII bytes) on purpose — the PTY carrier's whole prompt is 1000 B and core's budget test
|
|
238
233
|
* keeps ≥ 300 B of intent headroom. */
|
|
239
234
|
export const BUG_FIX_SWEEP_INSTRUCTIONS = 'Update every consumer of behaviour this fix retires or changes: tests, docs, comments.';
|
|
235
|
+
/** The helper written to a private temp dir and run with the node that runs crew; the credential
|
|
236
|
+
* stays in the daemon's environment and is read by the helper alone. */
|
|
237
|
+
export const defaultAdoHelperExec = async (args, opts) => {
|
|
238
|
+
const { mkdtemp, writeFile, rm } = await import('node:fs/promises');
|
|
239
|
+
const { tmpdir } = await import('node:os');
|
|
240
|
+
const { join } = await import('node:path');
|
|
241
|
+
const dir = await mkdtemp(join(tmpdir(), 'crew-ado-'));
|
|
242
|
+
try {
|
|
243
|
+
const file = join(dir, 'ado.mjs');
|
|
244
|
+
await writeFile(file, ADO_HELPER_JS, { mode: 0o600 });
|
|
245
|
+
return await new Promise((resolve) => {
|
|
246
|
+
execFile(process.execPath, [file, ...args], { timeout: opts.timeoutMs, encoding: 'utf8', env: childEnvWithBootEstateDb(process.env) }, (err, stdout, stderr) => {
|
|
247
|
+
const code = err === null ? 0 : typeof err.code === 'number' ? err.code : null;
|
|
248
|
+
resolve({ stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), code });
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
await rm(dir, { recursive: true, force: true });
|
|
254
|
+
}
|
|
255
|
+
};
|
|
240
256
|
export const defaultGhExec = (args, opts) => new Promise((resolve) => {
|
|
241
257
|
// The daemon's governance-store variables never ride into a child (crew#495): the boot value is
|
|
242
258
|
// restored and the exported store URL is stripped, the same helper every other spawn site uses.
|
|
@@ -287,33 +303,40 @@ export async function readDeliverOriginUrl(rootPath) {
|
|
|
287
303
|
* - a head branch name the script cannot splice safely;
|
|
288
304
|
* - `gh` unavailable, unauthenticated, timed out or answering anything but the JSON asked for.
|
|
289
305
|
*/
|
|
290
|
-
export async function resolvePullRequest(repoRoot, number, exec = defaultGhExec) {
|
|
306
|
+
export async function resolvePullRequest(repoRoot, number, exec = defaultGhExec, adoExec = defaultAdoHelperExec) {
|
|
291
307
|
if (!Number.isInteger(number) || number <= 0)
|
|
292
308
|
return { ok: false, error: `revisesPr must be a positive pull request number (got ${number})` };
|
|
309
|
+
// (crew#933) An Azure DevOps origin is asked through its REST API with the daemon's own
|
|
310
|
+
// credential (the deliver helper's `view`); the answer has gh's shape, so one parse serves both.
|
|
311
|
+
const ado = adoRepoOf(await readDeliverOriginUrl(repoRoot).catch(() => null));
|
|
312
|
+
const who = ado === null ? 'gh' : 'Azure DevOps';
|
|
293
313
|
let out;
|
|
294
314
|
try {
|
|
295
|
-
out =
|
|
315
|
+
out =
|
|
316
|
+
ado === null
|
|
317
|
+
? await exec(['pr', 'view', String(number), '--json', 'headRefName,state,isCrossRepository,url'], { cwd: repoRoot, timeoutMs: 5000 })
|
|
318
|
+
: await adoExec(['view', ado.loginBase, ado.apiBase, ado.webUrl, String(number)], { timeoutMs: 30_000 });
|
|
296
319
|
}
|
|
297
320
|
catch (err) {
|
|
298
|
-
return { ok: false, error:
|
|
321
|
+
return { ok: false, error: `${who} could not read PR #${number}: ${err instanceof Error ? err.message : String(err)}` };
|
|
299
322
|
}
|
|
300
323
|
if (out.code !== 0) {
|
|
301
324
|
const why = (out.stderr || out.stdout).trim().split('\n').slice(-2).join(' ').slice(0, 300);
|
|
302
|
-
return { ok: false, error:
|
|
325
|
+
return { ok: false, error: `${who} could not read PR #${number}: ${why || (out.code === null ? `${who} timed out or could not be spawned` : `exit ${out.code}`)}` };
|
|
303
326
|
}
|
|
304
327
|
let parsed;
|
|
305
328
|
try {
|
|
306
329
|
parsed = JSON.parse(out.stdout);
|
|
307
330
|
}
|
|
308
331
|
catch {
|
|
309
|
-
return { ok: false, error:
|
|
332
|
+
return { ok: false, error: `${who} could not read PR #${number}: its answer was not the JSON asked for` };
|
|
310
333
|
}
|
|
311
334
|
const r = (parsed ?? {});
|
|
312
335
|
const headRef = r['headRefName'];
|
|
313
336
|
const state = r['state'];
|
|
314
337
|
const url = r['url'];
|
|
315
338
|
if (typeof headRef !== 'string' || typeof state !== 'string' || typeof url !== 'string') {
|
|
316
|
-
return { ok: false, error:
|
|
339
|
+
return { ok: false, error: `${who} could not read PR #${number}: headRefName / state / url missing from its answer` };
|
|
317
340
|
}
|
|
318
341
|
if (state !== 'OPEN')
|
|
319
342
|
return { ok: false, error: `revisesPr #${number} is ${state} — only an open pull request can be revised` };
|
|
@@ -323,7 +346,7 @@ export async function resolvePullRequest(repoRoot, number, exec = defaultGhExec)
|
|
|
323
346
|
if (!isSafeRefName(headRef))
|
|
324
347
|
return { ok: false, error: `revisesPr #${number}'s head branch name cannot be used as a push target: ${JSON.stringify(headRef)}` };
|
|
325
348
|
if (!SAFE_PR_URL.test(url))
|
|
326
|
-
return { ok: false, error: `revisesPr #${number}:
|
|
349
|
+
return { ok: false, error: `revisesPr #${number}: ${who} answered a URL that is not a pull request URL (${url.slice(0, 120)})` };
|
|
327
350
|
return { ok: true, pr: { number, headRef, url, state } };
|
|
328
351
|
}
|
|
329
352
|
/**
|
|
@@ -507,11 +530,19 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
507
530
|
if (!/^[0-9a-fA-F]{16,64}$/.test(nonce))
|
|
508
531
|
throw new Error(`deliver nonce: not 16-64 hex digits: ${JSON.stringify(nonce)}`);
|
|
509
532
|
// (crew#720) AN AZURE DEVOPS ORIGIN: the push and the pull request go through the REST API with
|
|
510
|
-
// the daemon's own credential.
|
|
511
|
-
//
|
|
533
|
+
// the daemon's own credential. (crew#933) A revision pushes onto the PR's head branch and comments
|
|
534
|
+
// the run record as a thread, as on GitHub; the intent's Azure Boards work items (`AB#<id>`) are
|
|
535
|
+
// linked on the PR it opens. Digits only, so the literal is safe.
|
|
512
536
|
const ado = opts.adoTarget !== undefined ? opts.adoTarget : adoRepoOf(opts.originUrl);
|
|
513
|
-
|
|
514
|
-
|
|
537
|
+
const adoWorkItems = ado === null ? '' : adoWorkItemIds(intent ?? '').join(',');
|
|
538
|
+
// The revised PR must be THIS delivery's pull request: on Azure DevOps its URL names the target
|
|
539
|
+
// repository and the number (an origin re-pointed between resolution and composition must not
|
|
540
|
+
// push and comment on another organisation's PR); on GitHub it is never an Azure DevOps URL.
|
|
541
|
+
if (revises !== null) {
|
|
542
|
+
const isAdoUrl = revises.url.startsWith('https://dev.azure.com/');
|
|
543
|
+
if (ado !== null ? revises.url.toLowerCase() !== `${ado.webUrl}/pullrequest/${revises.number}`.toLowerCase() : isAdoUrl) {
|
|
544
|
+
throw new Error(`revisesPr #${revises.number}: ${revises.url} is not pull request #${revises.number} of the repository this delivery pushes to`);
|
|
545
|
+
}
|
|
515
546
|
}
|
|
516
547
|
return [
|
|
517
548
|
'set -euo pipefail',
|
|
@@ -561,12 +592,28 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
561
592
|
// can never hand the header to another program (codex r1 + r2).
|
|
562
593
|
`ADOPROTO=${shellSingleQuote(ado === null ? '' : new URL(ado.gitUrl).protocol.replace(':', ''))}`,
|
|
563
594
|
"ADOHDR=''",
|
|
595
|
+
`ADOWI='${adoWorkItems}'`,
|
|
596
|
+
// (crew#940) THE PINNED GITHUB TOKEN lives in an UNEXPORTED shell variable and reaches each gh
|
|
597
|
+
// and git network call one command at a time (`GH_TOKEN=… gh`, a one-command credential
|
|
598
|
+
// helper for git) — never argv, disk or the log, and no child that does not talk to GitHub
|
|
599
|
+
// inherits it. GHGIT is the canonical https URL a pinned github.com delivery fetches from and
|
|
600
|
+
// pushes to; NETGIT is that URL or the Azure DevOps one, '' for a plain `origin` delivery.
|
|
601
|
+
// An ambient `http.extraHeader` (actions/checkout writes one per host) would authenticate
|
|
602
|
+
// before any helper is asked, and a `url.*.insteadOf` could rewrite the canonical URL to ssh
|
|
603
|
+
// (whose key is another identity), so the GitHub arm of `_gnet` resets the header, allows only
|
|
604
|
+
// https and refuses redirects, as the ADO arm does.
|
|
605
|
+
"GHT=''",
|
|
606
|
+
"GHPIN=''",
|
|
607
|
+
"GHGIT=''",
|
|
608
|
+
"NETGIT=''",
|
|
609
|
+
// Pinned, gh talks to github.com whatever GH_HOST / GH_REPO the daemon inherited (codex r2).
|
|
610
|
+
'_gh() { if [ -n "$GHT" ]; then GH_TOKEN="$GHT" GH_HOST=github.com GH_REPO="github.com/$GHREPO" gh "$@"; else gh "$@"; fi; }',
|
|
564
611
|
// Plain `git` outside Azure DevOps mode; in it, the network calls carry the auth header ONE-SHOT
|
|
565
612
|
// in the child's environment, scoped to the exact repository URL (`http.<url>.extraHeader`),
|
|
566
613
|
// after an empty entry resets any ambient extra header; redirects are refused, hooks and
|
|
567
614
|
// credential helpers are off. The header lives in an UNEXPORTED shell variable: no file, no
|
|
568
615
|
// argv, no log, and no other child of this script inherits it.
|
|
569
|
-
`_gnet() { if [ -n "$ADOHDR" ]; then GIT_CONFIG_COUNT=4 GIT_CONFIG_KEY_0=http.extraHeader GIT_CONFIG_VALUE_0= GIT_CONFIG_KEY_1="http.$ADOGIT.extraHeader" GIT_CONFIG_VALUE_1= GIT_CONFIG_KEY_2="http.$ADOGIT.extraHeader" GIT_CONFIG_VALUE_2="Authorization: $ADOHDR" GIT_CONFIG_KEY_3=http.followRedirects GIT_CONFIG_VALUE_3=false GIT_TERMINAL_PROMPT=0 GIT_ALLOW_PROTOCOL="$ADOPROTO" git -c core.hooksPath=/dev/null -c credential.helper= "$@"; else git "$@"; fi; }`,
|
|
616
|
+
`_gnet() { if [ -n "$ADOHDR" ]; then GIT_CONFIG_COUNT=4 GIT_CONFIG_KEY_0=http.extraHeader GIT_CONFIG_VALUE_0= GIT_CONFIG_KEY_1="http.$ADOGIT.extraHeader" GIT_CONFIG_VALUE_1= GIT_CONFIG_KEY_2="http.$ADOGIT.extraHeader" GIT_CONFIG_VALUE_2="Authorization: $ADOHDR" GIT_CONFIG_KEY_3=http.followRedirects GIT_CONFIG_VALUE_3=false GIT_TERMINAL_PROMPT=0 GIT_ALLOW_PROTOCOL="$ADOPROTO" git -c core.hooksPath=/dev/null -c credential.helper= "$@"; elif [ -n "$GHGIT" ]; then GIT_CONFIG_COUNT=4 GIT_CONFIG_KEY_0=http.extraHeader GIT_CONFIG_VALUE_0= GIT_CONFIG_KEY_1="http.$GHGIT.extraHeader" GIT_CONFIG_VALUE_1= GIT_CONFIG_KEY_2=http.followRedirects GIT_CONFIG_VALUE_2=false GIT_CONFIG_KEY_3="http.$GHGIT.followRedirects" GIT_CONFIG_VALUE_3=false GIT_ALLOW_PROTOCOL=https GH_TOKEN="$GHT" GIT_TERMINAL_PROMPT=0 git -c credential.helper= -c 'credential.https://github.com.helper=!f() { test "$1" = get && echo username=x-access-token && echo "password=$GH_TOKEN"; }; f' "$@"; else git "$@"; fi; }`,
|
|
570
617
|
'if [ -n "$ADOGIT" ]; then',
|
|
571
618
|
' echo "deliver: Azure DevOps origin — $ADOWEB (the push and the pull request use the daemon\'s Azure DevOps credential; gh is not used)"',
|
|
572
619
|
` if ! { [ -n "\${${ADO_PAT_ENV}:-}" ] || { ${ADO_SP_ENV.map((n) => `[ -n "\${${n}:-}" ]`).join(' && ')}; }; }; then _credmissing azure_devops "Azure DevOps credentials not configured: set ${ADO_SP_ENV.join(', ')} (a service principal) or ${ADO_PAT_ENV} in the daemon's environment and restart it."; fi`,
|
|
@@ -585,35 +632,67 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
585
632
|
// The raw credential leaves the environment now: nothing this script runs later (the crew#426
|
|
586
633
|
// npm preflight, git's commit machinery) can read it.
|
|
587
634
|
` unset ${[ADO_PAT_ENV, ...ADO_SP_ENV].join(' ')}`,
|
|
635
|
+
' NETGIT="$ADOGIT"',
|
|
588
636
|
'else',
|
|
589
637
|
`CFG='${identity}'`,
|
|
590
638
|
'if [ -n "$CFG" ]; then GH_ACCOUNT="$CFG"; fi',
|
|
591
|
-
|
|
592
|
-
//
|
|
593
|
-
//
|
|
594
|
-
//
|
|
595
|
-
// `gh auth
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
'
|
|
599
|
-
|
|
600
|
-
'
|
|
639
|
+
`GHREPO='${ghRepo}'`,
|
|
640
|
+
// (crew#940, operator ruling 2026-10-10) THE PUSH IDENTITY IS CHOSEN PER COMMAND. On a github.com
|
|
641
|
+
// origin an exported GH_TOKEN still wins; else, with an identity configured (the setting, the
|
|
642
|
+
// repository's pin, or GH_ACCOUNT), the script reads THAT account's token from gh's keyring
|
|
643
|
+
// itself (`gh auth token --user`) and hands it to its own gh calls and to its git fetch/push —
|
|
644
|
+
// so gh's machine-wide ACTIVE account (which other tools switch) never decides who pushes.
|
|
645
|
+
// An identity gh holds no token for is the shared "credentials not configured" refusal
|
|
646
|
+
// (crew#720's shape): before anything is staged, recoverable, said on the gate card too. Off
|
|
647
|
+
// github.com (GitHub Enterprise, GitLab, a local path) the github.com identity does not apply.
|
|
648
|
+
'if [ -n "$GHREPO" ]; then',
|
|
649
|
+
' if [ -n "${GH_TOKEN:-}" ]; then GHT="$GH_TOKEN"; GHPIN=exported',
|
|
650
|
+
' elif [ -n "${GH_ACCOUNT:-}" ]; then',
|
|
651
|
+
` command -v gh >/dev/null 2>&1 || _credmissing github "GitHub credentials not configured: gh is not installed and no GH_TOKEN is exported, so $GH_ACCOUNT's token cannot be read. Install gh and run gh auth login as $GH_ACCOUNT, or export GH_TOKEN in the daemon's environment."`,
|
|
652
|
+
` GHT=$(gh auth token --hostname github.com --user "$GH_ACCOUNT" 2>/dev/null || true); [ -n "$GHT" ] || _credmissing github "GitHub credentials not configured: gh holds no token for $GH_ACCOUNT on this machine and no GH_TOKEN is exported. Run gh auth login as $GH_ACCOUNT on this machine (gh 2.40 or newer), or export GH_TOKEN in the daemon's environment."`,
|
|
653
|
+
' GHPIN=keyring',
|
|
654
|
+
' else',
|
|
655
|
+
// (crew#720) Unpinned: gh's own login is the credential, so gh absent or signed out is the
|
|
656
|
+
// same credentials-missing refusal.
|
|
657
|
+
` if ! command -v gh >/dev/null 2>&1; then _credmissing github "GitHub credentials not configured: gh is not installed and no GH_TOKEN is exported. Install gh and run gh auth login, or export GH_TOKEN in the daemon's environment."; fi`,
|
|
658
|
+
` gh auth status --hostname github.com >/dev/null 2>&1 || _credmissing github "GitHub credentials not configured: gh is not signed in to github.com and no GH_TOKEN is exported. Run gh auth login on this machine, or export GH_TOKEN in the daemon's environment."`,
|
|
659
|
+
' fi',
|
|
660
|
+
' if [ -n "$GHT" ]; then GHGIT="https://github.com/$GHREPO.git"; NETGIT="$GHGIT"; fi',
|
|
661
|
+
// A `url.<base>.insteadOf` / `pushInsteadOf` that rewrites the canonical URL would send the
|
|
662
|
+
// fetch or push somewhere the pin does not reach (ssh, or https carrying its own credential):
|
|
663
|
+
// refuse before anything is staged rather than push under that identity (codex r1/r2).
|
|
664
|
+
' if [ -n "$GHGIT" ]; then while IFS= read -r RW; do RWV=${RW#* }; [ -n "$RW" ] && [ -n "$RWV" ] || continue; case "$GHGIT" in "$RWV"*) echo "deliver: git config rewrites $RWV (a url.*.insteadOf), so the push would not go to $GHGIT with the pinned token; nothing was staged, committed or pushed. Remove the rewrite for this repository, then approve to retry the deliver phase"; exit 1;; esac; done <<GHRW_EOF',
|
|
665
|
+
'$(git config --get-regexp \'^url\\..*\\.(push)?insteadof$\' 2>/dev/null || true)',
|
|
666
|
+
'GHRW_EOF',
|
|
601
667
|
' fi',
|
|
668
|
+
// The token now lives only in GHT; nothing this script runs that is not a gh or git network
|
|
669
|
+
// call (the npm preflight, git's commit machinery) inherits it.
|
|
670
|
+
' if [ -n "$GHT" ]; then unset GH_TOKEN; fi',
|
|
671
|
+
'elif [ -n "${GH_ACCOUNT:-}" ]; then',
|
|
672
|
+
// An origin the composer could not read (GHREPO empty) that IS a github.com remote cannot be
|
|
673
|
+
// pinned: refuse rather than push under whatever credential git holds. The glob is loose on
|
|
674
|
+
// purpose — a look-alike host only refuses, it never pins.
|
|
675
|
+
' case "$(git remote get-url --push --all origin 2>/dev/null | tr \'A-Z\' \'a-z\' || true)" in *github.com[:/]*) echo "deliver: origin is a github.com remote, but this delivery was composed without reading it, so the push identity $GH_ACCOUNT cannot be pinned; nothing was staged, committed or pushed. Approve to retry once the origin can be read, or reject and relaunch"; exit 1;; esac',
|
|
676
|
+
' echo "deliver: the push identity $GH_ACCOUNT applies to github.com origins only; this origin is not one, so gh and git use their own credentials"',
|
|
602
677
|
'fi',
|
|
603
|
-
//
|
|
604
|
-
//
|
|
605
|
-
//
|
|
606
|
-
|
|
607
|
-
'
|
|
608
|
-
|
|
609
|
-
|
|
678
|
+
// WHO PUSHES, said once. A keyring pin IS its account (the token was read for that login), so
|
|
679
|
+
// there is nothing to compare. An exported GH_TOKEN is the one credential that can belong to
|
|
680
|
+
// someone other than the configured identity: that mismatch is still refused.
|
|
681
|
+
'if [ "$GHPIN" = keyring ]; then L="$GH_ACCOUNT"; echo "deliver: pushing as $GH_ACCOUNT with its own gh token, pinned for this phase (gh\'s active account is not used)"',
|
|
682
|
+
'else',
|
|
683
|
+
' L=$(_gh api user -q .login 2>/dev/null || true)',
|
|
684
|
+
' if [ "$GHPIN" = exported ] && [ -n "${GH_ACCOUNT:-}" ]; then',
|
|
685
|
+
' [ "$L" = "$GH_ACCOUNT" ] || { echo "deliver: identity mismatch — the push identity is $GH_ACCOUNT but the exported GH_TOKEN authenticates as ${L:-unreadable}; nothing was staged, committed or pushed. Export $GH_ACCOUNT\'s token as GH_TOKEN in the daemon environment (or unset GH_TOKEN so the phase reads $GH_ACCOUNT\'s own gh token), then approve to retry the deliver phase"; exit 1; }',
|
|
686
|
+
' echo "deliver: pushing as $L (pinned by GH_TOKEN)"',
|
|
687
|
+
' elif [ "$GHPIN" = exported ]; then echo "deliver: pushing as ${L:-an unknown login} (pinned by GH_TOKEN)"',
|
|
688
|
+
' elif [ -n "$L" ]; then echo "deliver: pushing as $L (no push identity configured — not pinned)"',
|
|
689
|
+
' else echo "deliver: pushing as an unknown login (gh not authenticated; no push identity configured — not pinned)"; fi',
|
|
610
690
|
'fi',
|
|
611
|
-
|
|
612
|
-
'
|
|
613
|
-
|
|
614
|
-
'
|
|
615
|
-
'
|
|
616
|
-
'else echo "deliver: pushing as an unknown login (gh not authenticated; GH_ACCOUNT not set — not pinned)"; fi',
|
|
691
|
+
// A pinned github.com delivery fetches from and pushes to GHGIT with the pinned token as git's
|
|
692
|
+
// only credential, so git's configured helpers cannot hand it another account: the cross-check
|
|
693
|
+
// below applies to every OTHER delivery, where git still picks its own credential.
|
|
694
|
+
'if [ -n "$GHGIT" ]; then echo "deliver: git fetches and pushes https://github.com/$GHREPO with the same token (git\'s configured credential helpers are not used)"',
|
|
695
|
+
'else',
|
|
617
696
|
// (crew#549 / F-RC1-010) THE CREDENTIAL CROSS-CHECK. `gh api user` says who gh is; it says
|
|
618
697
|
// NOTHING about the credential `git push` will use. On the RC1 rig those two disagreed —
|
|
619
698
|
// `git credential fill` handed git one account while `gh api user` reported another — and the
|
|
@@ -657,6 +736,7 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
657
736
|
' *) echo "deliver: origin is not an https remote — no git credential applies (ssh keys or a local path authenticate the push)";;',
|
|
658
737
|
'esac',
|
|
659
738
|
'fi',
|
|
739
|
+
'fi',
|
|
660
740
|
// REVISION MODE inputs (DES-L9 / crew#550) — baked at compose time from the resolved PR, each
|
|
661
741
|
// validated against a strict charset before it is spliced into a single-quoted literal. Empty
|
|
662
742
|
// TARGET ⇒ today's new-PR delivery.
|
|
@@ -701,7 +781,7 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
701
781
|
// default is trunk/develop/anything, not just main/master (Copilot on #303).
|
|
702
782
|
// (crew#720) Azure DevOps: fetched from the validated canonical URL with the scoped header, into
|
|
703
783
|
// origin's own tracking refs — never through origin's configured URLs (an ssh origin included).
|
|
704
|
-
`if [ -n "$ADOGIT" ]; then _gnet fetch -q "$ADOGIT" '+refs/heads/*:refs/remotes/origin/*' || { VERDICT=rejected; : > ${DELIVER_STRANDED_SENTINEL} || true; echo "deliver: Azure DevOps refused the fetch of $ADOWEB (above) — check that the credential can read the repository; nothing was staged, committed or pushed; approve to retry the deliver phase; ${DELIVER_PUSH_REJECTED_MARKER}"; exit 1; }; else git fetch origin; fi`,
|
|
784
|
+
`if [ -n "$ADOGIT" ]; then _gnet fetch -q "$ADOGIT" '+refs/heads/*:refs/remotes/origin/*' || { VERDICT=rejected; : > ${DELIVER_STRANDED_SENTINEL} || true; echo "deliver: Azure DevOps refused the fetch of $ADOWEB (above) — check that the credential can read the repository; nothing was staged, committed or pushed; approve to retry the deliver phase; ${DELIVER_PUSH_REJECTED_MARKER}"; exit 1; }; elif [ -n "$GHGIT" ]; then _gnet fetch -q "$GHGIT" '+refs/heads/*:refs/remotes/origin/*' || { VERDICT=rejected; : > ${DELIVER_STRANDED_SENTINEL} || true; echo "deliver: GitHub refused the fetch of https://github.com/$GHREPO as $L (above) — check that the credential can read the repository; nothing was staged, committed or pushed; approve to retry the deliver phase; ${DELIVER_PUSH_REJECTED_MARKER}"; exit 1; }; else git fetch origin; fi`,
|
|
705
785
|
// …the way the ENGINE derives it (wicked-core `deliver_lift.rs`, review F-527-003): origin/HEAD
|
|
706
786
|
// when it resolves to a commit — a DANGLING origin/HEAD (the remote's default branch renamed or
|
|
707
787
|
// deleted since the clone) is tolerated — else origin/main, else origin/master, else origin/main
|
|
@@ -729,7 +809,7 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
729
809
|
// Asked of the REMOTE (`ls-remote`), not of the clone's `origin/*` refs — a plain fetch never
|
|
730
810
|
// prunes a branch deleted after the PR merged, so the local ref would still resolve and the
|
|
731
811
|
// push would silently RE-CREATE the branch under a closed PR.
|
|
732
|
-
'
|
|
812
|
+
' _gnet ls-remote --exit-code --heads "${NETGIT:-origin}" "$TARGET" >/dev/null 2>&1 && git rev-parse --verify -q "origin/$TARGET^{commit}" >/dev/null || { echo "deliver: pull request #$PRNUM\'s branch origin/$TARGET no longer exists on the remote; nothing was staged, committed or pushed"; exit 1; }',
|
|
733
813
|
' git merge-base --is-ancestor "origin/$TARGET" "$B" || { echo "deliver: pull request #$PRNUM\'s branch moved since this run based on it (origin/$TARGET is no longer an ancestor of $B); nothing was staged, committed or pushed — launch a new revision on the current head, or rebase $B onto origin/$TARGET by hand and approve to retry"; echo "deliver: pull request #$PRNUM\'s branch moved — refused; nothing was pushed"; exit 1; }',
|
|
734
814
|
'fi',
|
|
735
815
|
// (a2) VERIFIED-BASE PIN (wicked-core#431 / #433). Before this script runs, the engine LIFTED the
|
|
@@ -1070,7 +1150,10 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
1070
1150
|
// A revision pushes the run branch ONTO the PR's head branch (`$B:refs/heads/$TARGET`) — the
|
|
1071
1151
|
// PR gains exactly the run's commits; a rejection there is the same recoverable strand.
|
|
1072
1152
|
// (crew#720) Azure DevOps pushes to the validated canonical URL with the scoped header.
|
|
1073
|
-
|
|
1153
|
+
// (crew#940) A pinned github.com delivery pushes to its canonical URL the same way, and both
|
|
1154
|
+
// re-fetch the pushed ref into origin's tracking ref (a push to a URL updates none) so the
|
|
1155
|
+
// done checks below read the remote.
|
|
1156
|
+
'_push() { if [ -n "$NETGIT" ]; then _gnet push "$NETGIT" "$B:refs/heads/${TARGET:-$B}" && _gnet fetch -q "$NETGIT" "+refs/heads/${TARGET:-$B}:refs/remotes/origin/${TARGET:-$B}"; elif [ -n "$TARGET" ]; then git push origin "$B:refs/heads/$TARGET"; else git push -u origin "$B"; fi; }',
|
|
1074
1157
|
// (crew#739) The branch-pushed fact is said in the script's own words, so a later failure (a gh
|
|
1075
1158
|
// error on `gh pr create`) still records that the branch reached the remote.
|
|
1076
1159
|
'if PUSHOUT=$(_push 2>&1); then echo "$PUSHOUT"; echo "deliver: pushed $B to origin"; else',
|
|
@@ -1102,12 +1185,12 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
1102
1185
|
// rides `gh pr comment` (the body the PR-create path would have used); a comment failure is
|
|
1103
1186
|
// printed, not fatal — the commit message carries the same record.
|
|
1104
1187
|
'if [ -n "$TARGET" ]; then',
|
|
1105
|
-
'
|
|
1188
|
+
' _gnet fetch -q "${NETGIT:-origin}" "+refs/heads/$TARGET:refs/remotes/origin/$TARGET"',
|
|
1106
1189
|
' RT=$(git rev-parse "origin/$TARGET"); LT=$(git rev-parse "$B")',
|
|
1107
1190
|
' [ "$RT" = "$LT" ] || { echo "deliver: origin/$TARGET is at ${RT:0:10} after the push, not at $B (${LT:0:10}) — refusing to report a delivery the remote does not show"; exit 1; }',
|
|
1108
|
-
' ST=$(
|
|
1191
|
+
' if [ -n "$ADOGIT" ]; then ST=$(WICKED_ADO_AUTH="$ADOHDR" "$ADONODE" "$TD/ado.mjs" state "$ADOAPI" "$PRNUM" 2>/dev/null || true); else ST=$(_gh pr view "$PRNUM" ${GHREPO:+--repo "github.com/$GHREPO"} --json state -q .state 2>/dev/null || true); fi',
|
|
1109
1192
|
' if [ "$ST" = "OPEN" ]; then echo "deliver: pull request #$PRNUM is OPEN and its branch $TARGET is at $B"; else echo "deliver: warning — pull request #$PRNUM reads ${ST:-unknown} (not OPEN) after the push; the commits landed on origin/$TARGET"; fi',
|
|
1110
|
-
' if COUT=$(
|
|
1193
|
+
' if COUT=$(if [ -n "$ADOGIT" ]; then WICKED_ADO_AUTH="$ADOHDR" "$ADONODE" "$TD/ado.mjs" comment "$ADOAPI" "$PRNUM" "$TD/body"; else _gh pr comment "$PRNUM" ${GHREPO:+--repo "github.com/$GHREPO"} --body-file "$TD/body"; fi 2>&1); then echo "deliver: run record commented on pull request #$PRNUM"; else echo "$COUT"; echo "deliver: could not comment on pull request #$PRNUM — the commits landed; the record is in the commit message"; fi',
|
|
1111
1194
|
' URL="$PRURL"',
|
|
1112
1195
|
'else',
|
|
1113
1196
|
// (e2) A NON-GITHUB ORIGIN DELIVERS THE BRANCH (F2). `gh pr create` failing used to be
|
|
@@ -1134,9 +1217,8 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
1134
1217
|
// branch is adopted (a retry after the push landed). Done is re-derived as on GitHub: a PR URL
|
|
1135
1218
|
// AND the remote branch (re-fetched from the canonical URL) ahead of the base.
|
|
1136
1219
|
' if [ -n "$ADOGIT" ]; then',
|
|
1137
|
-
' _gnet fetch -q "$ADOGIT" "+refs/heads/$B:refs/remotes/origin/$B"',
|
|
1138
1220
|
` printf '%s\\n' "$TITLE" > "$TD/title"`,
|
|
1139
|
-
' if ! OUT=$(WICKED_ADO_AUTH="$ADOHDR" "$ADONODE" "$TD/ado.mjs" pr "$ADOAPI" "$ADOWEB" "$B" "$DEF" "$TD/title" "$TD/body"); then echo "deliver: the Azure DevOps pull request for $B was not opened (above) — the branch is pushed; approve to retry the deliver phase (it re-pushes $B and opens or adopts the pull request)"; exit 1; fi',
|
|
1221
|
+
' if ! OUT=$(WICKED_ADO_AUTH="$ADOHDR" "$ADONODE" "$TD/ado.mjs" pr "$ADOAPI" "$ADOWEB" "$B" "$DEF" "$TD/title" "$TD/body" "$ADOWI"); then echo "deliver: the Azure DevOps pull request for $B was not opened (above) — the branch is pushed; approve to retry the deliver phase (it re-pushes $B and opens or adopts the pull request)"; exit 1; fi',
|
|
1140
1222
|
' echo "$OUT"',
|
|
1141
1223
|
' case "$OUT" in "deliver: ADO-PR-EXISTS "*) EXISTING=1;; esac',
|
|
1142
1224
|
" URL=$(printf '%s\\n' \"$OUT\" | grep -Eo 'https://[^[:space:]]+/pullrequest/[0-9]+' | tail -1 || true)",
|
|
@@ -1145,7 +1227,7 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
1145
1227
|
' [ "$P" -ge 1 ] || { echo "deliver: $B is not ahead of $D on the remote after the push — refusing to report a delivery with no commits"; exit 1; }',
|
|
1146
1228
|
' if [ -n "${EXISTING:-}" ]; then echo "deliver: pull request $URL already exists for $B (an earlier attempt of this run opened it); the push updated it with $P commit(s) on top of $D — recorded as this run\'s delivery"; fi',
|
|
1147
1229
|
' else',
|
|
1148
|
-
' if ! OUT=$(
|
|
1230
|
+
' if ! OUT=$(_gh pr create ${GHREPO:+--repo "$GHREPO"} --head "$B" --title "$TITLE" --body-file "$TD/body" 2>&1); then',
|
|
1149
1231
|
' echo "$OUT"',
|
|
1150
1232
|
' case "$OUT" in',
|
|
1151
1233
|
' *"git remotes configured for this repository"*"known GitHub host"*)',
|
|
@@ -1180,7 +1262,7 @@ export function deliverPrScript(intent, opts = {}) {
|
|
|
1180
1262
|
' [ "$P" -ge 1 ] || { echo "deliver: $B is not ahead of $D on the remote after the push — refusing to report a delivery with no commits"; exit 1; }',
|
|
1181
1263
|
' if [ -n "${EXISTING:-}" ]; then',
|
|
1182
1264
|
' echo "deliver: pull request $URL already exists for $B (an earlier attempt of this run opened it); the push updated it with $P commit(s) on top of $D — recorded as this run\'s delivery"',
|
|
1183
|
-
' if COUT=$(
|
|
1265
|
+
' if COUT=$(_gh pr comment "$URL" --body-file "$TD/body" 2>&1); then echo "deliver: run record commented on $URL"; else echo "$COUT"; echo "deliver: could not comment on $URL — the commits landed; the record is in the commit message"; fi',
|
|
1184
1266
|
' fi',
|
|
1185
1267
|
' fi',
|
|
1186
1268
|
'fi',
|
|
@@ -1414,13 +1496,22 @@ export function deliverGateInstructions(opts) {
|
|
|
1414
1496
|
const configured = (opts.deliverIdentity ?? '').trim();
|
|
1415
1497
|
const account = configured !== '' ? configured : (opts.ghAccount ?? null);
|
|
1416
1498
|
const source = configured !== '' ? (opts.deliverIdentitySource === 'repo' ? "this repository's push identity" : 'the deliver identity setting') : 'GH_ACCOUNT';
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1499
|
+
const configuredAccount = account !== null && account !== '';
|
|
1500
|
+
// (crew#940) The identity is pinned per command on a github.com origin: the token is the
|
|
1501
|
+
// account's own (or an exported GH_TOKEN), and git pushes with that same token.
|
|
1502
|
+
const github = githubRepoOf(opts.originUrl) !== null;
|
|
1503
|
+
const pinned = github && (configuredAccount || opts.ghTokenPinned === true);
|
|
1504
|
+
const who = !github
|
|
1505
|
+
? configuredAccount
|
|
1506
|
+
? `Push identity: ${account} (${source}) applies to github.com origins only; this push uses whatever credential the remote's host takes.`
|
|
1507
|
+
: 'Push identity: none configured — pushes as whatever login gh holds (set the deliver identity in system settings, or this repository\'s push identity, to pin it).'
|
|
1508
|
+
: configuredAccount
|
|
1509
|
+
? opts.ghTokenPinned === true
|
|
1510
|
+
? `Push identity: ${account} (${source}), pinned by GH_TOKEN — the phase refuses if that token authenticates as anyone else.`
|
|
1511
|
+
: `Push identity: ${account} (${source}) — the phase pushes and opens the pull request with ${account}'s own gh token, whatever account gh has active.`
|
|
1420
1512
|
: opts.ghTokenPinned === true
|
|
1421
|
-
?
|
|
1422
|
-
:
|
|
1423
|
-
: 'Push identity: none configured — pushes as whatever login gh holds (set the deliver identity in system settings, or this repository\'s push identity, to pin it).';
|
|
1513
|
+
? 'Push identity: the login of the exported GH_TOKEN (no push identity configured).'
|
|
1514
|
+
: 'Push identity: none configured — pushes as whatever login gh holds (set the deliver identity in system settings, or this repository\'s push identity, to pin it).';
|
|
1424
1515
|
// (crew#720) The provider credential preflight read at compose time: a missing credential is said
|
|
1425
1516
|
// BEFORE approval, on the card, in the same words the phase refuses with.
|
|
1426
1517
|
const cred = opts.credentials ?? null;
|
|
@@ -1435,10 +1526,10 @@ export function deliverGateInstructions(opts) {
|
|
|
1435
1526
|
: '';
|
|
1436
1527
|
return `${target} ${credSentence}${how}It refuses if origin no longer points at that repository.`.replace(/\s+$/, '');
|
|
1437
1528
|
}
|
|
1438
|
-
//
|
|
1439
|
-
// remote's host and refuses when the two logins disagree
|
|
1440
|
-
|
|
1441
|
-
return `${target} ${credSentence}${who}
|
|
1529
|
+
// Pinned, git pushes with the same token; otherwise the phase asks git which credential IT would
|
|
1530
|
+
// use for the remote's host and refuses when the two logins disagree (F-RC1-010).
|
|
1531
|
+
const git = pinned ? 'git pushes with the same token, not its own configured credential.' : "It refuses if gh's login and git's credential for the remote disagree.";
|
|
1532
|
+
return `${target} ${credSentence}${who} ${git}`;
|
|
1442
1533
|
}
|
|
1443
1534
|
/**
|
|
1444
1535
|
* The `deliver` PLAN STEP a delivering PRESET launch hands the engine (DES-TEAMING-002 T3,
|
|
@@ -1474,7 +1565,6 @@ presetName, phases, runId, intent, launch = {}) {
|
|
|
1474
1565
|
originUrl: launch.originUrl ?? null,
|
|
1475
1566
|
deliverIdentity: launch.deliverIdentity ?? null,
|
|
1476
1567
|
...(launch.deliverIdentitySource !== undefined ? { deliverIdentitySource: launch.deliverIdentitySource } : {}),
|
|
1477
|
-
...(launch.deliverIdentitySignedIn !== undefined ? { deliverIdentitySignedIn: launch.deliverIdentitySignedIn } : {}),
|
|
1478
1568
|
credentials: launch.credentials ?? null,
|
|
1479
1569
|
});
|
|
1480
1570
|
return {
|
|
@@ -1520,7 +1610,6 @@ export function composeDeliverWorkflow(base, runId, intent, launch = {}) {
|
|
|
1520
1610
|
originUrl: launch.originUrl ?? null,
|
|
1521
1611
|
deliverIdentity: launch.deliverIdentity ?? null,
|
|
1522
1612
|
...(launch.deliverIdentitySource !== undefined ? { deliverIdentitySource: launch.deliverIdentitySource } : {}),
|
|
1523
|
-
...(launch.deliverIdentitySignedIn !== undefined ? { deliverIdentitySignedIn: launch.deliverIdentitySignedIn } : {}),
|
|
1524
1613
|
credentials: launch.credentials ?? null,
|
|
1525
1614
|
});
|
|
1526
1615
|
return {
|