halfcycle 0.3.40 → 0.4.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/.claude-plugin/plugin.json +1 -1
- package/README.md +7 -13
- package/bin/bin.bundle.mjs +191 -145
- package/commands/halfcycle-setup.md +3 -3
- package/dist/bin.js +1 -6823
- package/dist/claude-version-probe.d.ts +32 -0
- package/dist/claude-version-probe.d.ts.map +1 -1
- package/dist/cli.js +7161 -0
- package/dist/cli.js.map +6 -0
- package/dist/confirm-identity.d.ts +26 -1
- package/dist/confirm-identity.d.ts.map +1 -1
- package/dist/create-engagement.d.ts +30 -0
- package/dist/create-engagement.d.ts.map +1 -1
- package/dist/device-signin.d.ts.map +1 -1
- package/dist/identity.d.ts +50 -13
- package/dist/identity.d.ts.map +1 -1
- package/dist/index.js +208 -116
- package/dist/index.js.map +3 -3
- package/dist/install.d.ts +57 -0
- package/dist/install.d.ts.map +1 -1
- package/dist/merge-settings.d.ts +11 -2
- package/dist/merge-settings.d.ts.map +1 -1
- package/dist/node-floor.d.ts +54 -0
- package/dist/node-floor.d.ts.map +1 -0
- package/dist/own-engagement.d.ts +25 -5
- package/dist/own-engagement.d.ts.map +1 -1
- package/dist/pre-create-checks.d.ts +61 -0
- package/dist/pre-create-checks.d.ts.map +1 -0
- package/dist/resolve-credential.d.ts.map +1 -1
- package/dist/uninstall.d.ts +31 -9
- package/dist/uninstall.d.ts.map +1 -1
- package/package.json +6 -2
- package/dist/bin.js.map +0 -6
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE HOME of the oldest Node Halfcycle runs on, and of the one-line check that
|
|
3
|
+
* says so (#1561).
|
|
4
|
+
*
|
|
5
|
+
* **Why a check at all.** Everything Halfcycle runs on a developer's machine is
|
|
6
|
+
* built for a modern Node. On an older one it does not fail with a reason: it fails
|
|
7
|
+
* while PARSING, before a line of it runs, with `Unexpected token {`, `Unexpected
|
|
8
|
+
* token .` or a missing built-in, and a stack trace. A GUI-launched editor on macOS
|
|
9
|
+
* can find an old Node first on its path, so a developer who installed a current
|
|
10
|
+
* one still meets this.
|
|
11
|
+
*
|
|
12
|
+
* **Why it is a program TEXT and not a function.** The check has to run before
|
|
13
|
+
* anything that would not parse, so it cannot live inside the code it protects.
|
|
14
|
+
* It is spliced, as source, in front of each thing that starts Node on the
|
|
15
|
+
* developer's machine:
|
|
16
|
+
*
|
|
17
|
+
* - the installer's entry file (`scripts/bundle-entries.mjs` writes `dist/bin.js`
|
|
18
|
+
* from it, in front of a dynamic import of the real CLI);
|
|
19
|
+
* - the MCP connection-headers command (`MCP_HEADERS_HELPER_COMMAND`, install.ts);
|
|
20
|
+
* - the guard hook wrapper, before it hands over to the vendored runner
|
|
21
|
+
* (`generateGuardRunnerWrapper`, install.ts).
|
|
22
|
+
*
|
|
23
|
+
* The session-marker scripts' own short `node -e` lines are NOT gated: they already
|
|
24
|
+
* swallow their errors and fall back, so an old Node there costs a marker, never a
|
|
25
|
+
* stack trace, and gating them would print the same sentence twice at session start
|
|
26
|
+
* (the guard wrapper also runs then).
|
|
27
|
+
*
|
|
28
|
+
* **What the program text must hold to.**
|
|
29
|
+
* - It PARSES ON NODE 10: no `?.`, no `??`, no `??=`, no private class fields,
|
|
30
|
+
* nothing newer. The guarded tail is the caller's business; on an old Node it is
|
|
31
|
+
* parsed but never run, so it may use any syntax Node 10 can parse (a dynamic
|
|
32
|
+
* `import()` parses there; measured).
|
|
33
|
+
* - It needs no `require` and no `import`: it runs as a script (Node 10, and the
|
|
34
|
+
* `node -e` programs) and as a module (`dist/bin.js` on Node 12+), and only
|
|
35
|
+
* `process` and `console` exist in both.
|
|
36
|
+
* - It holds none of `"`, `$`, `%`, a backtick, `\` or `!`, because the headers
|
|
37
|
+
* command sits inside one pair of double quotes under both a POSIX shell and
|
|
38
|
+
* `cmd.exe` (see `MCP_HEADERS_HELPER_COMMAND`), and the hook wrapper quotes it
|
|
39
|
+
* the same way.
|
|
40
|
+
* - It SETS the exit code rather than calling `process.exit`, so the sentence on
|
|
41
|
+
* stderr is never cut short when stderr is a pipe, which it is under a hook.
|
|
42
|
+
*
|
|
43
|
+
* **Exit 1 with the sentence on stderr** is how Claude Code shows a hook's
|
|
44
|
+
* non-blocking error: the first stderr line, in the transcript. It is the channel
|
|
45
|
+
* the runner already uses when it has never been configured.
|
|
46
|
+
*/
|
|
47
|
+
export declare const NODE_FLOOR_MAJOR = 18;
|
|
48
|
+
/**
|
|
49
|
+
* Wrap `guarded` (program text) so it runs only on a Node at or above the floor.
|
|
50
|
+
* Below it, one line goes to stderr and the exit code is 1. Pass `''` for a
|
|
51
|
+
* check-only program.
|
|
52
|
+
*/
|
|
53
|
+
export declare function nodeFloorProgram(guarded: string): string;
|
|
54
|
+
//# sourceMappingURL=node-floor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-floor.d.ts","sourceRoot":"","sources":["../src/node-floor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAKnC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOxD"}
|
package/dist/own-engagement.d.ts
CHANGED
|
@@ -101,6 +101,24 @@ export interface OutcomeBRefusal {
|
|
|
101
101
|
}
|
|
102
102
|
/** Discriminate `joinPinnedEngagement`'s result without inspecting an error. */
|
|
103
103
|
export declare function isOutcomeBRefusal(result: OwnedEngagement | OutcomeBRefusal): result is OutcomeBRefusal;
|
|
104
|
+
/**
|
|
105
|
+
* What `createOwnedEngagement` RETURNS, never throws, when the folder's id names a
|
|
106
|
+
* project another account owns (`project-identity-reuse` AC4, #1555) — someone else's
|
|
107
|
+
* committed `.halfcycle/project.json`, with no pin beside it.
|
|
108
|
+
*
|
|
109
|
+
* A return rather than a throw for the same reason `OutcomeBRefusal` is one: the caller
|
|
110
|
+
* must tell this apart from every other refusal without reading an error message. It is
|
|
111
|
+
* NOT `OutcomeBRefusal`, because the two outcomes are opposite: the join arm installs
|
|
112
|
+
* uninstrumented against an engagement id it already has, while this arm has no
|
|
113
|
+
* project to pin the folder to and stops (`bin.ts` exits 1 with the reset line).
|
|
114
|
+
*/
|
|
115
|
+
export interface ProjectOwnedElsewhere {
|
|
116
|
+
readonly outcome: 'project-owned-elsewhere';
|
|
117
|
+
/** The service's own sentence, forwarded verbatim. */
|
|
118
|
+
readonly message: string;
|
|
119
|
+
}
|
|
120
|
+
/** Discriminate `createOwnedEngagement`'s result without inspecting an error. */
|
|
121
|
+
export declare function isProjectOwnedElsewhere(result: OwnedEngagement | ProjectOwnedElsewhere): result is ProjectOwnedElsewhere;
|
|
104
122
|
/**
|
|
105
123
|
* Sign in if needed, then create an engagement owned by whoever signed in (T-08).
|
|
106
124
|
*
|
|
@@ -126,9 +144,11 @@ export declare function isOutcomeBRefusal(result: OwnedEngagement | OutcomeBRefu
|
|
|
126
144
|
* attempt's credential has source `browser-handoff`, for which
|
|
127
145
|
* `replaceRefusedCredential` always returns `null`.
|
|
128
146
|
*
|
|
129
|
-
* NOTHING HAS BEEN WRITTEN when any of this fails. Every throw here happens before
|
|
130
|
-
* `install()`, and
|
|
131
|
-
*
|
|
147
|
+
* NOTHING MORE HAS BEEN WRITTEN when any of this fails. Every throw here happens before
|
|
148
|
+
* `install()`, and the request itself refuses a half-formed answer rather than returning
|
|
149
|
+
* one. The one file already in the folder is `.halfcycle/project.json`, written before
|
|
150
|
+
* this function by `runPreCreateChecks` so that `projectId` exists before any request
|
|
151
|
+
* (#1555): whatever fails here, a re-run asks for the same project.
|
|
132
152
|
*
|
|
133
153
|
* ---------------------------------------------------------------------------
|
|
134
154
|
* **THE CONFIRMATION IS BETWEEN THE TWO STATEMENTS, AND ITS POSITION IS THE FIX**
|
|
@@ -144,7 +164,7 @@ export declare function isOutcomeBRefusal(result: OwnedEngagement | OutcomeBRefu
|
|
|
144
164
|
* ignored the return would print a browser handoff and then create the project under
|
|
145
165
|
* the account the person had just rejected.
|
|
146
166
|
*/
|
|
147
|
-
export declare function createOwnedEngagement(serviceUrl: string, targetRepo: string, deps?: OwnEngagementDeps): Promise<OwnedEngagement>;
|
|
167
|
+
export declare function createOwnedEngagement(serviceUrl: string, targetRepo: string, projectId: string, deps?: OwnEngagementDeps): Promise<OwnedEngagement | ProjectOwnedElsewhere>;
|
|
148
168
|
/**
|
|
149
169
|
* Sign in if needed, then obtain THIS caller's own credential for the engagement the
|
|
150
170
|
* repository is already pinned to (T-24, #610).
|
|
@@ -209,7 +229,7 @@ export declare function createOwnedEngagement(serviceUrl: string, targetRepo: st
|
|
|
209
229
|
* this client knows something about that the plane does not.
|
|
210
230
|
*
|
|
211
231
|
* A rethrown `CreateEngagementRefused` already carries a client-safe composed message
|
|
212
|
-
* (the plane's sentence inside `[
|
|
232
|
+
* (the plane's sentence inside `[halfcycle] Join-engagement failed: …`), so the
|
|
213
233
|
* caller prints the fact and adds nothing. **Nothing is retried and nothing is
|
|
214
234
|
* written** either way; the difference is only whether this client speaks.
|
|
215
235
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"own-engagement.d.ts","sourceRoot":"","sources":["../src/own-engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EAAyB,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGxF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,GAAG,eAAe,GACxC,MAAM,IAAI,eAAe,CAE3B;AAED
|
|
1
|
+
{"version":3,"file":"own-engagement.d.ts","sourceRoot":"","sources":["../src/own-engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EAAyB,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAGxF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,GAAG,eAAe,GACxC,MAAM,IAAI,eAAe,CAE3B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,iFAAiF;AACjF,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,GAAG,qBAAqB,GAC9C,MAAM,IAAI,qBAAqB,CAEjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,eAAe,GAAG,qBAAqB,CAAC,CAwDlD;AAmDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,eAAe,GAAG,eAAe,CAAC,CAoF5C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The checks the installer runs BEFORE it sends anything (`project-identity-reuse`
|
|
3
|
+
* AC1 and AC2, #1555 decision D1; #1567's settings-file and read-only messages; #1563's
|
|
4
|
+
* system folders and nested projects; #1557's Git for Windows offer, decision D2).
|
|
5
|
+
* Two halves of one sequence: `runLocalChecks` (writes nothing) runs on every arm before
|
|
6
|
+
* the first request; `runPreCreateChecks` (claims the folder id) runs on the create arm
|
|
7
|
+
* before the create.
|
|
8
|
+
*
|
|
9
|
+
* An install that is going to fail must fail before a project exists on the server.
|
|
10
|
+
* Until this module it failed inside `install()`, after the create: a read-only folder
|
|
11
|
+
* or a `.claude/settings.json` with a comment in it left an orphan project behind on
|
|
12
|
+
* every attempt, and each re-run made another.
|
|
13
|
+
*
|
|
14
|
+
* ONE STRAIGHT SEQUENCE, IN ORDER, EACH STEP A REFUSAL OR NOTHING. `runPreCreateChecks`
|
|
15
|
+
* is a list of statements, not a decision tree: a later check that belongs before the
|
|
16
|
+
* create is one more line in it, in the position its cost earns. A check that must not
|
|
17
|
+
* write into the folder at all (a system folder, a folder inside another project) goes
|
|
18
|
+
* ABOVE `claimFolderId`, which is the first step that writes.
|
|
19
|
+
*
|
|
20
|
+
* Every refusal is a `PreCreateRefused` carrying one client-safe sentence that names
|
|
21
|
+
* the folder or the file and the one thing to do. `bin.ts` prints it and exits 1.
|
|
22
|
+
*
|
|
23
|
+
* INV-001: Node builtins, `@halfcycle/events`, and bundle-internal modules. The folder
|
|
24
|
+
* id is judged by `projectIdSchema` — the same schema control uses to answer `400` —
|
|
25
|
+
* so this package holds no second idea of what a usable id looks like.
|
|
26
|
+
*/
|
|
27
|
+
/** A local check refused the install. `message` is the sentence to print. */
|
|
28
|
+
export declare class PreCreateRefused extends Error {
|
|
29
|
+
constructor(message: string);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* THE FIRST HALF OF THE SEQUENCE, ON EVERY ARM: the checks that write nothing. `bin.ts`
|
|
33
|
+
* runs it before the first request any arm sends (a re-run's `askAccount` comes before
|
|
34
|
+
* the arms decide), so a system folder, a folder inside another project and a Windows
|
|
35
|
+
* machine without Git Bash are refused whether the run would create, join or reuse.
|
|
36
|
+
* Returns whether Git for Windows was installed by this run. Sends no request; throws
|
|
37
|
+
* `PreCreateRefused`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runLocalChecks(targetRepo: string): Promise<{
|
|
40
|
+
readonly gitInstalled: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* THE SECOND HALF, ON THE CREATE ARM ONLY: claim the folder id — the first step that
|
|
44
|
+
* writes — then the settings file. Returns the folder id the create request must carry.
|
|
45
|
+
* Not run on the join and reuse arms, which never write before their request (a refused
|
|
46
|
+
* join leaves the tree exactly as it was — `project-identity-reuse` AC7). Sends no
|
|
47
|
+
* request; throws `PreCreateRefused`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function runPreCreateChecks(targetRepo: string): string;
|
|
50
|
+
export declare function refuseSystemFolder(targetRepo: string, platform?: NodeJS.Platform): void;
|
|
51
|
+
/**
|
|
52
|
+
* A folder inside a folder that is already a Halfcycle project (#1563): some PARENT
|
|
53
|
+
* holds the committed pin. Refused, naming that parent, and never reused or created
|
|
54
|
+
* here — a second project nested in the first is what 0.4.0 made. The target's own
|
|
55
|
+
* pin is not looked at (that is a re-run, decided by the arms in `bin.ts`). Edge cases
|
|
56
|
+
* such as monorepos are deliberately not special-cased here (#1570).
|
|
57
|
+
*/
|
|
58
|
+
export declare function refuseInsideProject(targetRepo: string): void;
|
|
59
|
+
/** The one install command the offer runs and the refusal names (#1557, decision D2). */
|
|
60
|
+
export declare const GIT_INSTALL_ARGS: readonly string[];
|
|
61
|
+
//# sourceMappingURL=pre-create-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-create-checks.d.ts","sourceRoot":"","sources":["../src/pre-create-checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAUH,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,CAKpG;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7D;AA0BD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,IAAI,CAWzG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAU5D;AAUD,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAA+D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-credential.d.ts","sourceRoot":"","sources":["../src/resolve-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMzD,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE7D,wDAAwD;AACxD,MAAM,MAAM,gBAAgB;AAC1B,+EAA+E;AAC7E,aAAa;AACf,uEAAuE;GACrE,QAAQ;AACV,oEAAoE;GAClE,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAiB7B;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAG7B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAWpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"resolve-credential.d.ts","sourceRoot":"","sources":["../src/resolve-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMzD,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE7D,wDAAwD;AACxD,MAAM,MAAM,gBAAgB;AAC1B,+EAA+E;AAC7E,aAAa;AACf,uEAAuE;GACrE,QAAQ;AACV,oEAAoE;GAClE,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAiB7B;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAG7B;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAWpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAyBxE"}
|
package/dist/uninstall.d.ts
CHANGED
|
@@ -2,18 +2,40 @@
|
|
|
2
2
|
* `halfcycle uninstall` — takes back exactly what the installer put in this
|
|
3
3
|
* repository, and nothing else (`client-uninstall.md`, T-21).
|
|
4
4
|
*
|
|
5
|
-
* WHAT DECIDES THAT
|
|
6
|
-
* install manifest (`install-manifest.ts`)
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* WHAT DECIDES THAT SOMETHING IS OURS: WHAT IT IS, NEVER WHETHER A RECORD LISTS IT
|
|
6
|
+
* (#1568). The committed install manifest (`install-manifest.ts`) is a file anyone
|
|
7
|
+
* can edit, delete with `.halfcycle/`, or never get, when an install stops part-way.
|
|
8
|
+
* So nothing is removed because the manifest names it, and nothing is kept because
|
|
9
|
+
* the manifest is missing. Every path acted on is a member of the closed write set
|
|
10
|
+
* held in code (`install.ts`, `closedWriteSet`), and within it:
|
|
11
|
+
* - an ENTRY that runs Halfcycle goes: every hook command in
|
|
12
|
+
* `HALFCYCLE_HOOK_COMMANDS` (current and retired, `@halfcycle/core`) and the
|
|
13
|
+
* `halfcycle` MCP server — the same entries a re-install replaces;
|
|
14
|
+
* - a FILE goes when it sits in `.halfcycle/`, the directory the installer owns by
|
|
15
|
+
* path, or when its bytes are bytes Halfcycle wrote there: the hash the record
|
|
16
|
+
* holds, or what this version writes (`generatedSha256`). Any other file is kept
|
|
17
|
+
* and named;
|
|
18
|
+
* - a MERGED FILE (`.claude/settings.json`, `.mcp.json`, `.gitignore`,
|
|
19
|
+
* `.gitattributes`) loses our entries and nothing else, always: the same
|
|
20
|
+
* predicate decides them on every path (`ourHookEntries`, `ourMcpServers`, the
|
|
21
|
+
* block under our header). Nothing is written that the developer did not have —
|
|
22
|
+
* no copy from git, no earlier version of the file — so their content always
|
|
23
|
+
* stays; a merged JSON file comes back in the installer's formatting, and one
|
|
24
|
+
* left empty goes (T-17c: putting git's copy back lost uncommitted edits);
|
|
25
|
+
* - a write-set directory goes, once empty, only when an install recorded creating
|
|
26
|
+
* it or the installer owns it by path — never one that may be the developer's.
|
|
27
|
+
* The record supplies only what nothing else can show: the deny rules and `$schema`
|
|
28
|
+
* an install added, the blocks it appended to `.gitignore` and `.gitattributes`, and
|
|
29
|
+
* which keys it created. With no record those come from the tree by the installer's
|
|
30
|
+
* own first-run rule (`noRecord`), which claims nothing it cannot see — so our deny
|
|
31
|
+
* rules and `$schema` stay. A symbolic link, or a path under one, is never
|
|
32
|
+
* followed.
|
|
12
33
|
*
|
|
13
34
|
* THE ORDER OF WORK IS THE SPEC'S, and it is load-bearing:
|
|
14
35
|
* 1. validate everything and change nothing on any failure — the arguments (in
|
|
15
|
-
* `bin.ts`), the manifest, the pin, the project id when the
|
|
16
|
-
* and that each merged JSON file present parses as
|
|
36
|
+
* `bin.ts`), the manifest when there is one, the pin, the project id when the
|
|
37
|
+
* credential is to go, and that each merged JSON file present either parses as
|
|
38
|
+
* a JSON object or holds nothing of Halfcycle's;
|
|
17
39
|
* 2. unmerge `.claude/settings.json` first, so no hook points at a deleted script,
|
|
18
40
|
* then `.mcp.json`, so no registration points at a deleted helper;
|
|
19
41
|
* 3. remove the recorded files, except the pin and the manifest, and the CI
|
package/dist/uninstall.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../src/uninstall.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AA2CH,2BAA2B;AAC3B,eAAO,MAAM,sBAAsB,wBAAwB,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,kEAAkE;AAClE,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAClC;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,aAAa,CAAC;IAC9D,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;CACxC;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,gBAAgB,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAc7G;AA4hBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAiJpE;AA8OD,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAmEhH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "halfcycle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Your coding agents are the engineers. Halfcycle is the rest of the team: product owner, architect, planner and independent reviewer for Claude Code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"type": "module",
|
|
26
26
|
"main": "./dist/index.js",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
27
30
|
"types": "./dist/index.d.ts",
|
|
28
31
|
"files": [
|
|
29
32
|
"dist",
|
|
@@ -44,7 +47,8 @@
|
|
|
44
47
|
"scripts": {
|
|
45
48
|
"build": "tsc -p tsconfig.json && node scripts/bundle-entries.mjs && node scripts/vendor-runner-bin.mjs",
|
|
46
49
|
"typecheck": "tsc --noEmit -p tsconfig.test.json",
|
|
47
|
-
"test": "tsc -p tsconfig.test.json
|
|
50
|
+
"build:test": "tsc -p tsconfig.test.json",
|
|
51
|
+
"test": "node -e \"const{existsSync,readdirSync}=require('fs');const d='dist-test/test';if(!existsSync(d)||!readdirSync(d).some(f=>f.endsWith('.test.js'))){console.error('dist-test/test has no compiled *.test.js files — run pnpm run build:test first');process.exit(1)}\" && node --test \"dist-test/test/\"*.test.js"
|
|
48
52
|
},
|
|
49
53
|
"dependencies": {
|
|
50
54
|
"zod": "^4.4.3"
|