halfcycle 0.4.1 → 0.4.2
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/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/bin/bin.bundle.mjs +26 -19
- package/dist/cli.js +67 -40
- package/dist/cli.js.map +1 -1
- package/dist/confirm-identity.d.ts +4 -19
- package/dist/confirm-identity.d.ts.map +1 -1
- package/dist/create-engagement.d.ts +6 -4
- package/dist/create-engagement.d.ts.map +1 -1
- package/dist/device-signin.d.ts +35 -2
- package/dist/device-signin.d.ts.map +1 -1
- package/dist/identity.d.ts +7 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/index.js +20 -7
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +21 -2
- package/dist/install.d.ts.map +1 -1
- package/dist/pre-create-checks.d.ts +27 -0
- package/dist/pre-create-checks.d.ts.map +1 -1
- package/dist/uninstall.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -75,9 +75,10 @@
|
|
|
75
75
|
* wrong-identity install is then discoverable afterwards, from the repository, by the
|
|
76
76
|
* person whose repository it is. Printing is not recording.
|
|
77
77
|
*
|
|
78
|
-
* The measurement is a TTY plus the absence of a CI marker
|
|
79
|
-
* one home is `device-signin.ts
|
|
80
|
-
*
|
|
78
|
+
* The measurement is `isInteractiveRun` (a TTY plus the absence of a CI marker), whose
|
|
79
|
+
* one home is `device-signin.ts`. It is never inferred from anything else. (The
|
|
80
|
+
* browser handoff does NOT ask it: that refuses only a CI run, since the person
|
|
81
|
+
* finishes in the browser, not at this terminal.)
|
|
81
82
|
*
|
|
82
83
|
* ---------------------------------------------------------------------------
|
|
83
84
|
* ASKING IS BEST-EFFORT ABOUT THE LABEL AND NEVER ABOUT THE GATE. `GET /account` may be
|
|
@@ -245,22 +246,6 @@ export declare function describeAccount(serviceUrl: string, credential: string,
|
|
|
245
246
|
* neither branch below and says plainly that this run could not confirm who signed in.
|
|
246
247
|
*/
|
|
247
248
|
export declare function accountLabel(identity: AccountIdentity | undefined, storedAccountId: string | undefined, verbose?: boolean, confirmed?: boolean): string;
|
|
248
|
-
/**
|
|
249
|
-
* Whether this run has a human at a keyboard to ask — the ONE measurement this module
|
|
250
|
-
* uses, so a caller outside `confirmActingIdentity` reads the same fact rather than
|
|
251
|
-
* assuming one.
|
|
252
|
-
*
|
|
253
|
-
* A TTY plus the absence of a CI marker (`isNonInteractive`, whose one home is
|
|
254
|
-
* `device-signin.ts` — the same question the browser handoff already asks). Never
|
|
255
|
-
* inferred from anything else — see this module's own docblock. Walk 5 (2026-09-08)
|
|
256
|
-
* found `identitySwitchRemedy` called with no measurement at all (an implicit "assume
|
|
257
|
-
* interactive"), printing "answer \"s\" when asked" into a run that had, moments
|
|
258
|
-
* earlier in the SAME output, already told the reader there was no terminal to ask at.
|
|
259
|
-
* Exported so `identitySwitchRemedy`'s callers outside `confirmActingIdentity` compute
|
|
260
|
-
* the same fact this function's own `interactive` local does, rather than a second,
|
|
261
|
-
* possibly drifting copy of this expression.
|
|
262
|
-
*/
|
|
263
|
-
export declare function isInteractiveRun(env?: NodeJS.ProcessEnv): boolean;
|
|
264
249
|
/**
|
|
265
250
|
* Read one line from the terminal. Kept out of the decision so the decision is testable.
|
|
266
251
|
* Also the Git for Windows offer's prompt (`pre-create-checks.ts`), so the terminal is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm-identity.d.ts","sourceRoot":"","sources":["../src/confirm-identity.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"confirm-identity.d.ts","sourceRoot":"","sources":["../src/confirm-identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -343,10 +343,12 @@ export declare function joinEngagement(baseUrl: string, engagementId: string, cr
|
|
|
343
343
|
* A project that belongs to another account is a `CreateEngagementRefused` carrying
|
|
344
344
|
* the declared not-this-account `reason`; telling it apart is `own-engagement.ts`'s.
|
|
345
345
|
*
|
|
346
|
-
* Its failure sentences say
|
|
347
|
-
* created: an answer lost after control created the project is exactly
|
|
348
|
-
* route makes recoverable, so "nothing was created" could be false.
|
|
349
|
-
* that
|
|
346
|
+
* Its failure sentences say Halfcycle did not finish setting up the folder, never that
|
|
347
|
+
* no project was created: an answer lost after control created the project is exactly
|
|
348
|
+
* the case this route makes recoverable, so "nothing was created" could be false. Nor
|
|
349
|
+
* that the folder "was not set up" (FW-1): its id file is already on disk, and the
|
|
350
|
+
* walks read that sentence as false. A re-run gets that project back, which `bin.ts`
|
|
351
|
+
* says once after every stopped install (`KEPT_FOLDER_ID_LINE`).
|
|
350
352
|
*
|
|
351
353
|
* @param derivedName The guessed name (`deriveProjectName`), or `''` when there is none —
|
|
352
354
|
* the field is required, and control names an empty one by default.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-engagement.d.ts","sourceRoot":"","sources":["../src/create-engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAKH;;oCAEoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAE9C,6CAA6C;aAC7B,MAAM,EAAE,MAAM;IAC9B,8DAA8D;aAC9C,aAAa,EAAE,MAAM;IACrC,+DAA+D;aAC/C,SAAS,EAAE,MAAM,GAAG,SAAS;IAC7C;;;;;;;;;;;;OAYG;aACa,MAAM,EAAE,MAAM,GAAG,SAAS;;IAnB1C,6CAA6C;IAC7B,MAAM,EAAE,MAAM;IAC9B,8DAA8D;IAC9C,aAAa,EAAE,MAAM;IACrC,+DAA+D;IAC/C,SAAS,EAAE,MAAM,GAAG,SAAS;IAC7C;;;;;;;;;;;;OAYG;IACa,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM;IAMjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,WAAW,IAAI,OAAO,CAGzB;CACF;AA8ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAgB5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAa5B;AAED
|
|
1
|
+
{"version":3,"file":"create-engagement.d.ts","sourceRoot":"","sources":["../src/create-engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAKH;;oCAEoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAE9C,6CAA6C;aAC7B,MAAM,EAAE,MAAM;IAC9B,8DAA8D;aAC9C,aAAa,EAAE,MAAM;IACrC,+DAA+D;aAC/C,SAAS,EAAE,MAAM,GAAG,SAAS;IAC7C;;;;;;;;;;;;OAYG;aACa,MAAM,EAAE,MAAM,GAAG,SAAS;;IAnB1C,6CAA6C;IAC7B,MAAM,EAAE,MAAM;IAC9B,8DAA8D;IAC9C,aAAa,EAAE,MAAM;IACrC,+DAA+D;IAC/C,SAAS,EAAE,MAAM,GAAG,SAAS;IAC7C;;;;;;;;;;;;OAYG;IACa,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM;IAMjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,WAAW,IAAI,OAAO,CAGzB;CACF;AA8ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAgB5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAa5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAgB5B"}
|
package/dist/device-signin.d.ts
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* ---------------------------------------------------------------------------
|
|
40
40
|
* FOUR WAYS THIS ENDS, and each is a different sentence and a non-zero exit:
|
|
41
41
|
*
|
|
42
|
-
* `declined` — a human refused at the page.
|
|
42
|
+
* `declined` — a human refused at the page.
|
|
43
43
|
* `expired` — the code's window closed on CONTROL's clock before anyone acted.
|
|
44
44
|
* `unknown` — the server is not waiting on this code (never minted, or spent).
|
|
45
45
|
* unreachable — the plane stopped answering mid-poll. This one is OURS to word,
|
|
@@ -95,6 +95,15 @@ export declare const SIGN_IN_TIMEOUT_MESSAGE: string;
|
|
|
95
95
|
* burns the job's time and then reports something that reads like a platform
|
|
96
96
|
* outage. It refuses immediately instead, and names the ONE thing a workflow can
|
|
97
97
|
* actually do.
|
|
98
|
+
*
|
|
99
|
+
* "Non-interactive" here is a CI run (`isNonInteractive`), not `isInteractiveRun`: a
|
|
100
|
+
* piped stdin with no `CI` still gets the browser sign-in, because that is how an
|
|
101
|
+
* agent runs the first install (its shell has no terminal; the person at the screen
|
|
102
|
+
* finishes in the browser). Onboarding fix wave FW-1 tried gating this on
|
|
103
|
+
* `isInteractiveRun` and reverted it (FW-1a). The sentence says nothing about what
|
|
104
|
+
* was or was not created: on the create arm the folder id is already on disk, and
|
|
105
|
+
* `bin.ts` says the one true thing about that after every refusal
|
|
106
|
+
* (`KEPT_FOLDER_ID_LINE`).
|
|
98
107
|
*/
|
|
99
108
|
export declare const SIGN_IN_NON_INTERACTIVE_MESSAGE: string;
|
|
100
109
|
/** Everything this module touches that a test may need to hold still. */
|
|
@@ -274,8 +283,32 @@ export interface BrowserOpenAttempt {
|
|
|
274
283
|
* unchanged.
|
|
275
284
|
*/
|
|
276
285
|
export declare function openBrowser(url: string, env?: NodeJS.ProcessEnv, os?: string, spawnImpl?: typeof spawn): Promise<BrowserOpenAttempt>;
|
|
277
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* True iff the environment marks this as a CI run — the browser sign-in's gate, and one
|
|
288
|
+
* half of `isInteractiveRun`.
|
|
289
|
+
*/
|
|
278
290
|
export declare function isNonInteractive(env?: NodeJS.ProcessEnv): boolean;
|
|
291
|
+
/**
|
|
292
|
+
* Whether this run has a human at a keyboard to ask — THE ONE MEASUREMENT, read by
|
|
293
|
+
* every caller that needs to ASK a question: the identity confirmation
|
|
294
|
+
* (`confirm-identity.ts`) and the Git for Windows offer (`pre-create-checks.ts`).
|
|
295
|
+
*
|
|
296
|
+
* A TTY plus the absence of a CI marker (`isNonInteractive`). Never inferred from
|
|
297
|
+
* anything else. Walk 5 (2026-09-08) found `identitySwitchRemedy` called with no
|
|
298
|
+
* measurement at all (an implicit "assume interactive"), printing "answer \"s\" when
|
|
299
|
+
* asked" into a run that had, moments earlier in the SAME output, already told the
|
|
300
|
+
* reader there was no terminal to ask at.
|
|
301
|
+
*
|
|
302
|
+
* NOT the browser sign-in's gate. `signIn` asks nothing at the terminal — the person
|
|
303
|
+
* finishes in the browser — so it refuses only a CI run (`isNonInteractive`). An agent
|
|
304
|
+
* running the first install through its shell has no terminal on stdin, and its
|
|
305
|
+
* person signs in at the browser; gating `signIn` on this would refuse that install
|
|
306
|
+
* (onboarding fix wave FW-1a reverted exactly that).
|
|
307
|
+
*
|
|
308
|
+
* It lives here, beside `isNonInteractive`, so `confirm-identity.ts` (which imports
|
|
309
|
+
* this module) and `pre-create-checks.ts` read one definition, not two copies.
|
|
310
|
+
*/
|
|
311
|
+
export declare function isInteractiveRun(env?: NodeJS.ProcessEnv): boolean;
|
|
279
312
|
/** `POST /auth/device/start` — mint a code. Throws `SignInRefused` on a refusal. */
|
|
280
313
|
export declare function startDeviceAuth(serviceUrl: string): Promise<DeviceAuthStartResponse>;
|
|
281
314
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-signin.d.ts","sourceRoot":"","sources":["../src/device-signin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAExB,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;GAQG;AACH,qBAAa,aAAc,SAAQ,KAAK;aAEpB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;CAKlB;AAED,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"device-signin.d.ts","sourceRoot":"","sources":["../src/device-signin.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.d.ts
CHANGED
|
@@ -74,6 +74,13 @@ export declare function readRootCommit(targetRepoRoot: string): string | null;
|
|
|
74
74
|
* AC8) — outside a repository there is nothing to commit them to.
|
|
75
75
|
*/
|
|
76
76
|
export declare function isGitWorkTree(targetRepoRoot: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Can this machine run `git` at all? Asked only once `isGitWorkTree` has said no,
|
|
79
|
+
* because `git()` above answers `null` for "not a repository" and for "no git" alike —
|
|
80
|
+
* and the advice differs: `git init` cannot help someone who has no Git (the macOS and
|
|
81
|
+
* Linux walks' B5, onboarding fix wave FW-1).
|
|
82
|
+
*/
|
|
83
|
+
export declare function gitIsInstalled(): boolean;
|
|
77
84
|
/** Read the `origin` remote URL. */
|
|
78
85
|
export declare function readRemote(targetRepoRoot: string): string | null;
|
|
79
86
|
/**
|
package/dist/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,qBAAqB,QAGF,CAAC;AAEjC,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAE9D,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AA6BD,gFAAgF;AAChF,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,UAAU,CAItD;AAqBD,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,oCAAoC;AACpC,wBAAgB,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrE;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,CAyBvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAazG;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAE1E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAiBtE"}
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,qBAAqB,QAGF,CAAC;AAEjC,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAE9D,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AA6BD,gFAAgF;AAChF,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,UAAU,CAItD;AAqBD,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAOxC;AAED,oCAAoC;AACpC,wBAAgB,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrE;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,CAyBvG;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAazG;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAE1E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAiBtE"}
|
package/dist/index.js
CHANGED
|
@@ -1867,6 +1867,11 @@ function sha256OfWhatThisVersionWrites(commands) {
|
|
|
1867
1867
|
fromFile(CAPTURED_INDEX_REL, capturedIndexScaffold());
|
|
1868
1868
|
return out;
|
|
1869
1869
|
}
|
|
1870
|
+
function bytesAreOurs(path, bytes, recorded, writeSet) {
|
|
1871
|
+
const hash = sha256Hex(bytes);
|
|
1872
|
+
const recordedHash = recorded !== void 0 && "sha256" in recorded ? recorded.sha256 : void 0;
|
|
1873
|
+
return hash === recordedHash || hash === writeSet.generatedSha256.get(path);
|
|
1874
|
+
}
|
|
1870
1875
|
function readPreviousManifest(targetRepo) {
|
|
1871
1876
|
try {
|
|
1872
1877
|
return parseManifest(readFileSync4(join5(targetRepo, INSTALL_MANIFEST_REL), "utf-8"));
|
|
@@ -2015,7 +2020,7 @@ function readPluginManifest() {
|
|
|
2015
2020
|
const raw = readFileSync4(manifestPath, "utf-8");
|
|
2016
2021
|
return JSON.parse(raw);
|
|
2017
2022
|
}
|
|
2018
|
-
function copyManifestCommands(manifest, targetRepo, report, draft) {
|
|
2023
|
+
function copyManifestCommands(manifest, targetRepo, report, draft, writeSet) {
|
|
2019
2024
|
for (const cmd of manifest.commands ?? []) {
|
|
2020
2025
|
const srcFile = join5(BUNDLE_ROOT, ".claude-plugin", cmd.path);
|
|
2021
2026
|
if (!existsSync3(srcFile)) {
|
|
@@ -2024,8 +2029,11 @@ function copyManifestCommands(manifest, targetRepo, report, draft) {
|
|
|
2024
2029
|
const rel = commandStubRel(cmd.name);
|
|
2025
2030
|
const destFile = join5(targetRepo, rel);
|
|
2026
2031
|
const content = readFileSync4(srcFile, "utf-8");
|
|
2027
|
-
const
|
|
2032
|
+
const recorded = draft.files.get(rel);
|
|
2033
|
+
const { outcome, replacedExisting } = writeCollisionSafe(destFile, targetRepo, content, (current) => bytesAreOurs(rel, current, recorded, writeSet));
|
|
2028
2034
|
record(report, outcome, rel);
|
|
2035
|
+
if (replacedExisting)
|
|
2036
|
+
report.replacedPaths.push(rel);
|
|
2029
2037
|
noteFile(draft, targetRepo, rel, outcome);
|
|
2030
2038
|
}
|
|
2031
2039
|
}
|
|
@@ -2040,18 +2048,23 @@ function writeAllowlisted(targetAbsPath, targetRepoRoot, content, writtenPaths)
|
|
|
2040
2048
|
writeFileSync4(targetAbsPath, content, "utf-8");
|
|
2041
2049
|
writtenPaths.push(rel);
|
|
2042
2050
|
}
|
|
2043
|
-
function writeCollisionSafe(targetAbsPath, targetRepoRoot, content) {
|
|
2051
|
+
function writeCollisionSafe(targetAbsPath, targetRepoRoot, content, isOurs) {
|
|
2044
2052
|
const rel = relative(targetRepoRoot, targetAbsPath).replace(/\\/g, "/");
|
|
2045
2053
|
if (!isAllowlisted(rel)) {
|
|
2046
2054
|
throw new Error(`[halfcycle] Write-allowlist violation: attempted to write "${rel}". Only the method surface and scaffolding paths are writable.`);
|
|
2047
2055
|
}
|
|
2056
|
+
let replacedExisting = false;
|
|
2048
2057
|
if (existsSync3(targetAbsPath)) {
|
|
2049
|
-
const current = readFileSync4(targetAbsPath
|
|
2050
|
-
|
|
2058
|
+
const current = readFileSync4(targetAbsPath);
|
|
2059
|
+
if (current.toString("utf-8") === content)
|
|
2060
|
+
return { outcome: "skipped", replacedExisting: false };
|
|
2061
|
+
if (!isOurs(current))
|
|
2062
|
+
return { outcome: "collided", replacedExisting: false };
|
|
2063
|
+
replacedExisting = true;
|
|
2051
2064
|
}
|
|
2052
2065
|
mkdirSync4(dirname3(targetAbsPath), { recursive: true });
|
|
2053
2066
|
writeFileSync4(targetAbsPath, content, "utf-8");
|
|
2054
|
-
return "written";
|
|
2067
|
+
return { outcome: "written", replacedExisting };
|
|
2055
2068
|
}
|
|
2056
2069
|
var INSTALLER_OWNED_DIR = ".halfcycle/";
|
|
2057
2070
|
function writeOwned(targetAbsPath, targetRepoRoot, content) {
|
|
@@ -2686,7 +2699,7 @@ async function install(options) {
|
|
|
2686
2699
|
const writeSet = closedWriteSet();
|
|
2687
2700
|
const draft = startManifest(readPreviousManifest(targetRepo), (path) => writeSet.files.has(path), (path) => writeSet.dirs.has(path));
|
|
2688
2701
|
const dirsBefore = new Set([...writeSet.dirs].filter((dir) => existsSync3(join5(targetRepo, dir))));
|
|
2689
|
-
copyManifestCommands(manifest, targetRepo, report, draft);
|
|
2702
|
+
copyManifestCommands(manifest, targetRepo, report, draft, writeSet);
|
|
2690
2703
|
const vendoredBinSrc = resolveVendoredBinary();
|
|
2691
2704
|
const vendoredBinDest = join5(targetRepo, ".halfcycle", "bin", "bin.bundle.mjs");
|
|
2692
2705
|
const vendoredOutcome = recordOwned(report, vendoredBinDest, targetRepo, readFileSync4(vendoredBinSrc, "utf-8"), VENDORED_BIN_REL);
|