halfcycle 0.4.2 → 0.4.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/.claude-plugin/plugin.json +1 -1
- package/bin/bin.bundle.mjs +31 -6
- package/dist/claude-version-probe.d.ts.map +1 -1
- package/dist/cli.js +185 -91
- package/dist/cli.js.map +2 -2
- package/dist/confirm-identity.d.ts +42 -22
- package/dist/confirm-identity.d.ts.map +1 -1
- package/dist/device-signin.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -32
- package/dist/index.js.map +1 -1
- package/dist/install-manifest.d.ts +27 -2
- package/dist/install-manifest.d.ts.map +1 -1
- package/dist/install.d.ts +79 -10
- package/dist/install.d.ts.map +1 -1
- package/dist/merge-settings.d.ts +35 -16
- package/dist/merge-settings.d.ts.map +1 -1
- package/dist/own-engagement.d.ts +8 -7
- package/dist/own-engagement.d.ts.map +1 -1
- package/dist/uninstall.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -69,11 +69,12 @@
|
|
|
69
69
|
* silence back permanently and for every future question this CLI asks.
|
|
70
70
|
*
|
|
71
71
|
* So what this population gets instead is a record that does not live in scrollback.
|
|
72
|
-
* The account id settled on here is RETURNED to the caller, which writes it
|
|
73
|
-
* committed `.halfcycle/bundle.json`
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
72
|
+
* The account id settled on here is RETURNED to the caller, which on a CREATE writes it
|
|
73
|
+
* into the committed `.halfcycle/bundle.json` as `createdByAccountId` (`writeBundlePin`
|
|
74
|
+
* in `install.ts`; only the create writes it — E1, #1598) — the id and never the email,
|
|
75
|
+
* because that file is committed into the client's repository. A wrong-identity install
|
|
76
|
+
* is then discoverable afterwards, from the repository, by the person whose repository
|
|
77
|
+
* it is. Printing is not recording.
|
|
77
78
|
*
|
|
78
79
|
* The measurement is `isInteractiveRun` (a TTY plus the absence of a CI marker), whose
|
|
79
80
|
* one home is `device-signin.ts`. It is never inferred from anything else. (The
|
|
@@ -132,8 +133,9 @@ export interface ConfirmIdentityDeps extends ResolveOptions {
|
|
|
132
133
|
* every run and it is the wrong thing to put beside the value the reader is being
|
|
133
134
|
* asked to check: a person cannot verify a uuid, and thirty-eight characters of one
|
|
134
135
|
* pushed the email they CAN verify leftward into a longer line. It is not lost —
|
|
135
|
-
* `.halfcycle/bundle.json` records the account
|
|
136
|
-
* copy a support conversation can
|
|
136
|
+
* `.halfcycle/bundle.json` records the account that created the project, which is
|
|
137
|
+
* the copy a support conversation can be pointed at once the terminal is gone.
|
|
138
|
+
* The account a later run acted as is not recorded there (E1, #1598).
|
|
137
139
|
*/
|
|
138
140
|
verbose?: boolean;
|
|
139
141
|
/**
|
|
@@ -228,24 +230,42 @@ export declare function describeAccount(serviceUrl: string, credential: string,
|
|
|
228
230
|
* and a human needs the email. The first half of that is true and the conclusion was
|
|
229
231
|
* wrong: this label's reader is a person deciding whether a project should belong to
|
|
230
232
|
* this account, they cannot verify a uuid, and a uuid printed beside the one value they
|
|
231
|
-
* CAN verify buries it. The id has a better home already —
|
|
232
|
-
* in `.halfcycle/bundle.json`, which outlives the
|
|
233
|
-
* back on screen for the run that
|
|
233
|
+
* CAN verify buries it. The creating account's id has a better home already —
|
|
234
|
+
* `writeBundlePin` records it in `.halfcycle/bundle.json`, which outlives the
|
|
235
|
+
* scrollback — and `--verbose` puts this run's id back on screen for the run that
|
|
236
|
+
* wants it.
|
|
234
237
|
*
|
|
235
|
-
* WITH NO EMAIL the id is all there is, and it is printed
|
|
236
|
-
*
|
|
238
|
+
* WITH NO EMAIL BUT AN ANSWERED ACCOUNT the id is all there is, and it is printed —
|
|
239
|
+
* ONLY when `identity` itself is defined: an unnamed account named by its row is better
|
|
240
|
+
* than an unnamed account, but that is a claim about what `GET /account` just said, not
|
|
241
|
+
* about a credential this run merely holds. `(no email on record for it)` is the
|
|
242
|
+
* accepted exception to the "no internal words" scan precisely because it is scoped to
|
|
243
|
+
* this one case.
|
|
237
244
|
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
245
|
+
* **`identity === undefined` MEANS THE SAME THING EVERYWHERE THIS FUNCTION IS CALLED,
|
|
246
|
+
* AND IT MEANS "SAY NOTHING THAT CLAIMS AN ANSWER" (onboarding fix wave 2, F-01, the
|
|
247
|
+
* review's ruling on RW-02/RW-03 F-2, 2026-10-18).** `storedAccountId` is a credential
|
|
248
|
+
* this machine holds, not a fact the service stated — printing it, or printing
|
|
249
|
+
* "(no email on record for it)" beside it, asserts an answer this run never got.
|
|
250
|
+
* EVERY CALLER funnels through this one branch rather than deciding per-caller: `bin.ts`'s
|
|
251
|
+
* final report never reaches it (guarded by `identity !== undefined` before the call), and
|
|
252
|
+
* `confirm-identity.ts`'s own preamble (`accountLine`, gated the same way) and its stop
|
|
253
|
+
* remedy both go through it. The first cut of this fix gated only the preamble and left the
|
|
254
|
+
* stop remedy printing `account <id> (no email on record for it)` offline — the review's
|
|
255
|
+
* finding that fixing one caller and not the function itself reproduces the defect at the
|
|
256
|
+
* next call site.
|
|
241
257
|
*
|
|
242
|
-
* `
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
258
|
+
* **RETURNS `undefined` FOR THAT CASE RATHER THAN A SPLICED-IN NOUN PHRASE (round 2 of the
|
|
259
|
+
* same review, 2026-10-18).** A first attempt here returned a generic phrase ("the account
|
|
260
|
+
* this machine's saved sign-in belongs to" / "this credential's account") for every caller
|
|
261
|
+
* to interpolate — which reads naturally nowhere it is actually interpolated ("This
|
|
262
|
+
* machine's saved sign-in is for the account this machine's saved sign-in belongs to" / "is
|
|
263
|
+
* the credential for this credential's account"). Pushing the UNKNOWN case out to
|
|
264
|
+
* `undefined` keeps the one rule here (no id, no email claim, when `identity` is absent)
|
|
265
|
+
* while leaving each caller free to write its own grammatically whole sentence for that
|
|
266
|
+
* case — `armScript` below is the one caller that needs to, and does.
|
|
247
267
|
*/
|
|
248
|
-
export declare function accountLabel(identity: AccountIdentity | undefined, storedAccountId: string | undefined, verbose?: boolean
|
|
268
|
+
export declare function accountLabel(identity: AccountIdentity | undefined, storedAccountId: string | undefined, verbose?: boolean): string | undefined;
|
|
249
269
|
/**
|
|
250
270
|
* Read one line from the terminal. Kept out of the decision so the decision is testable.
|
|
251
271
|
* Also the Git for Windows offer's prompt (`pre-create-checks.ts`), so the terminal is
|
|
@@ -311,7 +331,7 @@ export declare function identitySwitchRemedy(home: string | undefined, interacti
|
|
|
311
331
|
*
|
|
312
332
|
* Returns the credential to use, which is a DIFFERENT one from the one passed in when
|
|
313
333
|
* the person switched account, and which carries the ACCOUNT ID this run acts as so the
|
|
314
|
-
* caller can record it on disk (`writeBundlePin`). Throws `SignInRefused` when they
|
|
334
|
+
* caller can record it on disk when it creates the project (`writeBundlePin`). Throws `SignInRefused` when they
|
|
315
335
|
* stop, which the CLI already prints as a refusal rather than as a crash: nothing has
|
|
316
336
|
* been created and nothing has been written at the point this is called, and that is
|
|
317
337
|
* what makes stopping a real option rather than an apology.
|
|
@@ -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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-signin.d.ts","sourceRoot":"","sources":["../src/device-signin.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"device-signin.d.ts","sourceRoot":"","sources":["../src/device-signin.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* INV-001: imports only from @halfcycle/core, @halfcycle/events, or Node builtins.
|
|
10
10
|
*/
|
|
11
|
-
export { install, checkDrift, readBundlePin, ZONE_B_DIR } from './install.js';
|
|
11
|
+
export { install, checkDrift, readBundlePin, pinCreatedByAccountId, ZONE_B_DIR } from './install.js';
|
|
12
12
|
export type { InstallOptions, InstallResult, BundlePin, EngagementType, DeviceCredential } from './install.js';
|
|
13
13
|
export { mintOrReadIdentity, readRootCommit, readRemote } from './identity.js';
|
|
14
14
|
export type { ProjectIdentity } from './identity.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrG,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/G,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACnF,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAyBhE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnG,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAI1F,cAAc,kBAAkB,CAAC;AAKjC,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1356,12 +1356,20 @@ function createProjectIdentityFile(targetRepoRoot) {
|
|
|
1356
1356
|
}
|
|
1357
1357
|
|
|
1358
1358
|
// dist/install-manifest.js
|
|
1359
|
+
import { Buffer } from "node:buffer";
|
|
1359
1360
|
import { createHash } from "node:crypto";
|
|
1360
1361
|
var INSTALL_MANIFEST_REL = ".halfcycle/install-manifest.json";
|
|
1361
1362
|
var INSTALL_MANIFEST_FORMAT = "halfcycle-install-manifest/v1";
|
|
1362
1363
|
function sha256Hex(bytes) {
|
|
1363
1364
|
return createHash("sha256").update(bytes).digest("hex");
|
|
1364
1365
|
}
|
|
1366
|
+
function lineKey(line) {
|
|
1367
|
+
return line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
1368
|
+
}
|
|
1369
|
+
function fileSha256(bytes) {
|
|
1370
|
+
const text = typeof bytes === "string" ? bytes : Buffer.from(bytes).toString("utf-8");
|
|
1371
|
+
return sha256Hex(text.split("\n").map(lineKey).join("\n"));
|
|
1372
|
+
}
|
|
1365
1373
|
function canonicalJson(value) {
|
|
1366
1374
|
if (Array.isArray(value))
|
|
1367
1375
|
return value.map(canonicalJson);
|
|
@@ -1544,7 +1552,7 @@ function startManifest(previous, isMember, isMemberDir) {
|
|
|
1544
1552
|
};
|
|
1545
1553
|
}
|
|
1546
1554
|
function recordInstalledFile(draft, path, bytes) {
|
|
1547
|
-
draft.files.set(path, { path, sha256:
|
|
1555
|
+
draft.files.set(path, { path, sha256: fileSha256(bytes) });
|
|
1548
1556
|
}
|
|
1549
1557
|
function recordRemovedFile(draft, path) {
|
|
1550
1558
|
draft.files.delete(path);
|
|
@@ -1650,8 +1658,20 @@ function projectPageUrl(engagementId) {
|
|
|
1650
1658
|
}
|
|
1651
1659
|
|
|
1652
1660
|
// dist/merge-settings.js
|
|
1661
|
+
function isHalfcycleCommand(hook, halfcycleCommands) {
|
|
1662
|
+
if (typeof hook !== "object" || hook === null)
|
|
1663
|
+
return false;
|
|
1664
|
+
const command = hook.command;
|
|
1665
|
+
return typeof command === "string" && halfcycleCommands.has(command);
|
|
1666
|
+
}
|
|
1653
1667
|
function isHalfcycleEntry(entry, halfcycleCommands) {
|
|
1654
|
-
return entry.hooks.some((h) =>
|
|
1668
|
+
return entry.hooks.some((h) => isHalfcycleCommand(h, halfcycleCommands));
|
|
1669
|
+
}
|
|
1670
|
+
function withoutHalfcycleCommands(entry, halfcycleCommands) {
|
|
1671
|
+
if (!isHalfcycleEntry(entry, halfcycleCommands))
|
|
1672
|
+
return entry;
|
|
1673
|
+
const remaining = entry.hooks.filter((h) => !isHalfcycleCommand(h, halfcycleCommands));
|
|
1674
|
+
return remaining.length > 0 ? { ...entry, hooks: remaining } : null;
|
|
1655
1675
|
}
|
|
1656
1676
|
function mergeSettings(existing, generated) {
|
|
1657
1677
|
const merged = { ...existing };
|
|
@@ -1670,7 +1690,7 @@ function mergeSettings(existing, generated) {
|
|
|
1670
1690
|
const mergedHooks = {};
|
|
1671
1691
|
const events = /* @__PURE__ */ new Set([...Object.keys(existingHooks), ...Object.keys(generatedHooks)]);
|
|
1672
1692
|
for (const event of events) {
|
|
1673
|
-
const developerEntries = (existingHooks[event] ?? []).
|
|
1693
|
+
const developerEntries = (existingHooks[event] ?? []).flatMap((entry) => withoutHalfcycleCommands(entry, halfcycleCommands) ?? []);
|
|
1674
1694
|
const halfcycleEntries = generatedHooks[event] ?? [];
|
|
1675
1695
|
mergedHooks[event] = [...developerEntries, ...halfcycleEntries];
|
|
1676
1696
|
}
|
|
@@ -1846,6 +1866,7 @@ function closedWriteSet() {
|
|
|
1846
1866
|
ownedDirs,
|
|
1847
1867
|
hookCommands: new Set(HALFCYCLE_HOOK_COMMANDS),
|
|
1848
1868
|
denyRuleSha256: new Set([...DENY_PATTERNS, ...RETIRED_DENY_PATTERNS].map((rule) => sha256Hex(rule))),
|
|
1869
|
+
settingsSchema: SETTINGS_SCHEMA,
|
|
1849
1870
|
gitignoreLines: /* @__PURE__ */ new Set([GITIGNORE_HEADER, ...REQUIRED_GITIGNORE_ENTRIES, LEGACY_ENV_LOCAL_REL]),
|
|
1850
1871
|
gitattributesLines: /* @__PURE__ */ new Set([
|
|
1851
1872
|
GITATTRIBUTES_HEADER,
|
|
@@ -1858,17 +1879,17 @@ function sha256OfWhatThisVersionWrites(commands) {
|
|
|
1858
1879
|
const out = /* @__PURE__ */ new Map();
|
|
1859
1880
|
const fromFile = (rel, src) => {
|
|
1860
1881
|
if (existsSync3(src))
|
|
1861
|
-
out.set(rel,
|
|
1882
|
+
out.set(rel, fileSha256(readFileSync4(src)));
|
|
1862
1883
|
};
|
|
1863
1884
|
for (const cmd of commands)
|
|
1864
1885
|
fromFile(commandStubRel(cmd.name), join5(BUNDLE_ROOT, ".claude-plugin", cmd.path));
|
|
1865
1886
|
for (const [rel, content] of hookScriptsThisVersionWrites())
|
|
1866
|
-
out.set(rel,
|
|
1887
|
+
out.set(rel, fileSha256(content));
|
|
1867
1888
|
fromFile(CAPTURED_INDEX_REL, capturedIndexScaffold());
|
|
1868
1889
|
return out;
|
|
1869
1890
|
}
|
|
1870
1891
|
function bytesAreOurs(path, bytes, recorded, writeSet) {
|
|
1871
|
-
const hash =
|
|
1892
|
+
const hash = fileSha256(bytes);
|
|
1872
1893
|
const recordedHash = recorded !== void 0 && "sha256" in recorded ? recorded.sha256 : void 0;
|
|
1873
1894
|
return hash === recordedHash || hash === writeSet.generatedSha256.get(path);
|
|
1874
1895
|
}
|
|
@@ -2034,6 +2055,8 @@ function copyManifestCommands(manifest, targetRepo, report, draft, writeSet) {
|
|
|
2034
2055
|
record(report, outcome, rel);
|
|
2035
2056
|
if (replacedExisting)
|
|
2036
2057
|
report.replacedPaths.push(rel);
|
|
2058
|
+
if (outcome === "collided" && recorded !== void 0)
|
|
2059
|
+
report.editedCollidedPaths.push(rel);
|
|
2037
2060
|
noteFile(draft, targetRepo, rel, outcome);
|
|
2038
2061
|
}
|
|
2039
2062
|
}
|
|
@@ -2054,16 +2077,17 @@ function writeCollisionSafe(targetAbsPath, targetRepoRoot, content, isOurs) {
|
|
|
2054
2077
|
throw new Error(`[halfcycle] Write-allowlist violation: attempted to write "${rel}". Only the method surface and scaffolding paths are writable.`);
|
|
2055
2078
|
}
|
|
2056
2079
|
let replacedExisting = false;
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2080
|
+
const current = existsSync3(targetAbsPath) ? readFileSync4(targetAbsPath) : null;
|
|
2081
|
+
const text = inLineEndingOf(current?.toString("utf-8") ?? null, content);
|
|
2082
|
+
if (current !== null) {
|
|
2083
|
+
if (current.toString("utf-8") === text)
|
|
2060
2084
|
return { outcome: "skipped", replacedExisting: false };
|
|
2061
2085
|
if (!isOurs(current))
|
|
2062
2086
|
return { outcome: "collided", replacedExisting: false };
|
|
2063
2087
|
replacedExisting = true;
|
|
2064
2088
|
}
|
|
2065
2089
|
mkdirSync4(dirname3(targetAbsPath), { recursive: true });
|
|
2066
|
-
writeFileSync4(targetAbsPath,
|
|
2090
|
+
writeFileSync4(targetAbsPath, text, "utf-8");
|
|
2067
2091
|
return { outcome: "written", replacedExisting };
|
|
2068
2092
|
}
|
|
2069
2093
|
var INSTALLER_OWNED_DIR = ".halfcycle/";
|
|
@@ -2075,11 +2099,12 @@ function writeOwned(targetAbsPath, targetRepoRoot, content) {
|
|
|
2075
2099
|
if (!rel.startsWith(INSTALLER_OWNED_DIR)) {
|
|
2076
2100
|
throw new Error(`[halfcycle] Path-ownership violation: attempted to claim "${rel}" by path. Only ${INSTALLER_OWNED_DIR} is owned outright by this installer; everywhere else a differing file may be a developer's, so ownership must be proved from the file's own contents (writeOwnedGenerated) rather than assumed from where it sits.`);
|
|
2077
2101
|
}
|
|
2078
|
-
|
|
2102
|
+
const current = readFileOrNull(targetAbsPath);
|
|
2103
|
+
const text = inLineEndingOf(current, content);
|
|
2104
|
+
if (current === text)
|
|
2079
2105
|
return "skipped";
|
|
2080
|
-
}
|
|
2081
2106
|
mkdirSync4(dirname3(targetAbsPath), { recursive: true });
|
|
2082
|
-
writeFileSync4(targetAbsPath,
|
|
2107
|
+
writeFileSync4(targetAbsPath, text, "utf-8");
|
|
2083
2108
|
return "written";
|
|
2084
2109
|
}
|
|
2085
2110
|
var GENERATED_HEADER_LINE_INDEX = 1;
|
|
@@ -2157,6 +2182,7 @@ function settingsParseRefusal(targetRepo, err) {
|
|
|
2157
2182
|
}
|
|
2158
2183
|
return `${file} could not be read as JSON${where} \u2014 fix it and run "npx halfcycle" again.`;
|
|
2159
2184
|
}
|
|
2185
|
+
var SETTINGS_SCHEMA = "https://json.schemastore.org/claude-code-settings.json";
|
|
2160
2186
|
function generateSettingsJson() {
|
|
2161
2187
|
const hooks = {};
|
|
2162
2188
|
for (const { event, matcher, timeout, command } of HALFCYCLE_HOOK_WIRING) {
|
|
@@ -2166,7 +2192,7 @@ function generateSettingsJson() {
|
|
|
2166
2192
|
});
|
|
2167
2193
|
}
|
|
2168
2194
|
const settings = {
|
|
2169
|
-
$schema:
|
|
2195
|
+
$schema: SETTINGS_SCHEMA,
|
|
2170
2196
|
permissions: {
|
|
2171
2197
|
// deny ONLY. See DENY_PATTERNS — an allow list evaporates under bypass mode
|
|
2172
2198
|
// and is the machine owner's grant to make, not ours.
|
|
@@ -2466,19 +2492,27 @@ function adoptBlockUnderHeader(before, header, claimable) {
|
|
|
2466
2492
|
let underHeader = false;
|
|
2467
2493
|
const lines = before.split("\n");
|
|
2468
2494
|
for (const [i, line] of lines.entries()) {
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2495
|
+
const key = lineKey(line);
|
|
2496
|
+
if (key === header) {
|
|
2497
|
+
if (i > 0 && lineKey(lines[i - 1]) === "")
|
|
2498
|
+
claimed.push(lines[i - 1]);
|
|
2472
2499
|
claimed.push(line);
|
|
2473
2500
|
underHeader = true;
|
|
2474
|
-
} else if (
|
|
2501
|
+
} else if (key.trim() === "") {
|
|
2475
2502
|
underHeader = false;
|
|
2476
|
-
} else if (underHeader && claimable.has(
|
|
2503
|
+
} else if (underHeader && claimable.has(key)) {
|
|
2477
2504
|
claimed.push(line);
|
|
2478
2505
|
}
|
|
2479
2506
|
}
|
|
2480
2507
|
return claimed.length > 0 ? claimed.join("\n") + "\n" : "";
|
|
2481
2508
|
}
|
|
2509
|
+
function lineEndingOf(text) {
|
|
2510
|
+
const at = text.indexOf("\n");
|
|
2511
|
+
return at > 0 && text[at - 1] === "\r" ? "\r\n" : "\n";
|
|
2512
|
+
}
|
|
2513
|
+
function inLineEndingOf(existing, generated) {
|
|
2514
|
+
return existing === null ? generated : generated.split("\n").join(lineEndingOf(existing));
|
|
2515
|
+
}
|
|
2482
2516
|
function gitignoreCovers(content) {
|
|
2483
2517
|
const lines = new Set(content.split("\n").map((l) => l.trim()));
|
|
2484
2518
|
return REQUIRED_GITIGNORE_ENTRIES.every((entry) => lines.has(entry));
|
|
@@ -2497,9 +2531,8 @@ function reconcileGitignore(targetRepo) {
|
|
|
2497
2531
|
return "skipped";
|
|
2498
2532
|
const existingLines = new Set(existing.split("\n").map((l) => l.trim()));
|
|
2499
2533
|
const toAdd = REQUIRED_GITIGNORE_ENTRIES.filter((entry) => !existingLines.has(entry));
|
|
2500
|
-
const
|
|
2501
|
-
|
|
2502
|
-
` + toAdd.join("\n") + "\n";
|
|
2534
|
+
const eol = lineEndingOf(existing);
|
|
2535
|
+
const suffix = (existing.endsWith("\n") ? "" : eol) + eol + [header, ...toAdd].join(eol) + eol;
|
|
2503
2536
|
writeFileSync4(gitignorePath, existing + suffix, "utf-8");
|
|
2504
2537
|
return "written";
|
|
2505
2538
|
} catch {
|
|
@@ -2534,8 +2567,9 @@ function reconcileGitattributes(targetRepo) {
|
|
|
2534
2567
|
const toAdd = rules.filter((rule) => !present.has(rule));
|
|
2535
2568
|
if (toAdd.length === 0)
|
|
2536
2569
|
return "skipped";
|
|
2537
|
-
const
|
|
2538
|
-
const
|
|
2570
|
+
const eol = lineEndingOf(existing);
|
|
2571
|
+
const separator = existing === "" ? "" : existing.endsWith("\n") ? eol : eol + eol;
|
|
2572
|
+
const suffix = separator + [GITATTRIBUTES_HEADER, ...toAdd].join(eol) + eol;
|
|
2539
2573
|
writeAllowlisted(path, targetRepo, existing + suffix, routed);
|
|
2540
2574
|
return "written";
|
|
2541
2575
|
} catch {
|
|
@@ -2555,9 +2589,9 @@ function previousPinForEngagement(targetRepoRoot, engagementId) {
|
|
|
2555
2589
|
function nonEmpty(value) {
|
|
2556
2590
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
2557
2591
|
}
|
|
2558
|
-
function writeBundlePin(targetRepoRoot, version, engagementId, engagementType,
|
|
2592
|
+
function writeBundlePin(targetRepoRoot, version, engagementId, engagementType, createdByAccountId, methodVersion, writtenPaths) {
|
|
2559
2593
|
const previous = previousPinForEngagement(targetRepoRoot, engagementId);
|
|
2560
|
-
const carried =
|
|
2594
|
+
const carried = pinCreatedByAccountId(previous) ?? nonEmpty(createdByAccountId);
|
|
2561
2595
|
const carriedMethodVersion = nonEmpty(methodVersion) ?? nonEmpty(previous?.methodVersion);
|
|
2562
2596
|
const installedAt = nonEmpty(previous?.installedAt) ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2563
2597
|
const projectPage = projectPageUrl(engagementId);
|
|
@@ -2566,12 +2600,13 @@ function writeBundlePin(targetRepoRoot, version, engagementId, engagementType, a
|
|
|
2566
2600
|
engagementId,
|
|
2567
2601
|
engagementType,
|
|
2568
2602
|
installedAt,
|
|
2569
|
-
...carried !== void 0 ? {
|
|
2603
|
+
...carried !== void 0 ? { createdByAccountId: carried } : {},
|
|
2570
2604
|
...carriedMethodVersion !== void 0 ? { methodVersion: carriedMethodVersion } : {},
|
|
2571
2605
|
...projectPage !== void 0 ? { projectPage } : {}
|
|
2572
2606
|
};
|
|
2573
2607
|
const pinPath = join5(targetRepoRoot, BUNDLE_PIN_REL);
|
|
2574
|
-
|
|
2608
|
+
const pinText = inLineEndingOf(readFileOrNull(pinPath), JSON.stringify(pin, null, 2) + "\n");
|
|
2609
|
+
writeAllowlisted(pinPath, targetRepoRoot, pinText, writtenPaths);
|
|
2575
2610
|
}
|
|
2576
2611
|
function writeCrewRoster(targetRepoRoot, report) {
|
|
2577
2612
|
const doc = {
|
|
@@ -2583,6 +2618,9 @@ function writeCrewRoster(targetRepoRoot, report) {
|
|
|
2583
2618
|
const crewPath = join5(targetRepoRoot, CREW_ROSTER_REL);
|
|
2584
2619
|
return recordOwned(report, crewPath, targetRepoRoot, rendered, CREW_ROSTER_REL);
|
|
2585
2620
|
}
|
|
2621
|
+
function pinCreatedByAccountId(pin) {
|
|
2622
|
+
return nonEmpty(pin?.createdByAccountId) ?? nonEmpty(pin?.accountId);
|
|
2623
|
+
}
|
|
2586
2624
|
function readBundlePin(targetRepoRoot) {
|
|
2587
2625
|
const pinPath = join5(targetRepoRoot, BUNDLE_PIN_REL);
|
|
2588
2626
|
if (!existsSync3(pinPath))
|
|
@@ -2683,7 +2721,7 @@ function migrateLegacyEnvLocal(targetRepo, stored) {
|
|
|
2683
2721
|
}
|
|
2684
2722
|
}
|
|
2685
2723
|
async function install(options) {
|
|
2686
|
-
const { targetRepo, engagementId, engagementType, credential, home,
|
|
2724
|
+
const { targetRepo, engagementId, engagementType, credential, home, createdByAccountId } = options;
|
|
2687
2725
|
assertEngagementId(engagementId);
|
|
2688
2726
|
if (!existsSync3(targetRepo)) {
|
|
2689
2727
|
throw new Error(`[halfcycle] Target repo does not exist: ${targetRepo}`);
|
|
@@ -2694,6 +2732,7 @@ async function install(options) {
|
|
|
2694
2732
|
skippedPaths: [],
|
|
2695
2733
|
mergedPaths: [],
|
|
2696
2734
|
collidedPaths: [],
|
|
2735
|
+
editedCollidedPaths: [],
|
|
2697
2736
|
replacedPaths: []
|
|
2698
2737
|
};
|
|
2699
2738
|
const writeSet = closedWriteSet();
|
|
@@ -2715,7 +2754,7 @@ async function install(options) {
|
|
|
2715
2754
|
}
|
|
2716
2755
|
recordSettingsMerge(draft, existingSettings, generatedSettings, settingsPreexisted);
|
|
2717
2756
|
const mergedSettings = mergeSettings(existingSettings, generatedSettings);
|
|
2718
|
-
const mergedSettingsText = JSON.stringify(mergedSettings, null, 2) + "\n";
|
|
2757
|
+
const mergedSettingsText = inLineEndingOf(readFileOrNull(settingsPath), JSON.stringify(mergedSettings, null, 2) + "\n");
|
|
2719
2758
|
mkdirSync4(dirname3(settingsPath), { recursive: true });
|
|
2720
2759
|
writeFileSync4(settingsPath, mergedSettingsText, "utf-8");
|
|
2721
2760
|
(settingsPreexisted ? report.mergedPaths : report.writtenPaths).push(".claude/settings.json");
|
|
@@ -2743,7 +2782,7 @@ async function install(options) {
|
|
|
2743
2782
|
if (credential) {
|
|
2744
2783
|
const mcpPath = join5(targetRepo, MCP_REGISTRATION_REL);
|
|
2745
2784
|
const existingMcp = existsSync3(mcpPath) ? readFileSync4(mcpPath, "utf-8") : null;
|
|
2746
|
-
const mcpContent = generateMcpRegistration(existingMcp, credential.mcpUrl);
|
|
2785
|
+
const mcpContent = inLineEndingOf(existingMcp, generateMcpRegistration(existingMcp, credential.mcpUrl));
|
|
2747
2786
|
recordMcpMerge(draft, existingMcp, mcpContent);
|
|
2748
2787
|
if (existingMcp === null) {
|
|
2749
2788
|
writeAllowlisted(mcpPath, targetRepo, mcpContent, report.writtenPaths);
|
|
@@ -2821,7 +2860,7 @@ async function install(options) {
|
|
|
2821
2860
|
case "absent":
|
|
2822
2861
|
break;
|
|
2823
2862
|
}
|
|
2824
|
-
writeBundlePin(targetRepo, manifest.version, engagementId, engagementType,
|
|
2863
|
+
writeBundlePin(targetRepo, manifest.version, engagementId, engagementType, createdByAccountId, credential?.methodVersion, report.writtenPaths);
|
|
2825
2864
|
noteFile(draft, targetRepo, BUNDLE_PIN_REL, "written");
|
|
2826
2865
|
noteFile(draft, targetRepo, CREW_ROSTER_REL, writeCrewRoster(targetRepo, report));
|
|
2827
2866
|
const scanResult = runBootstrapScan(targetRepo);
|
|
@@ -2841,6 +2880,7 @@ async function install(options) {
|
|
|
2841
2880
|
skippedPaths: report.skippedPaths,
|
|
2842
2881
|
mergedPaths: report.mergedPaths,
|
|
2843
2882
|
collidedPaths: report.collidedPaths,
|
|
2883
|
+
editedCollidedPaths: report.editedCollidedPaths,
|
|
2844
2884
|
replacedPaths: report.replacedPaths,
|
|
2845
2885
|
bootstrapScanRan: scanResult.ran,
|
|
2846
2886
|
legacyCredentialKept: migration.outcome === "kept" ? { keys: migration.unbacked, missing: migration.missingForAdoption } : null,
|
|
@@ -4090,6 +4130,7 @@ export {
|
|
|
4090
4130
|
mergeWithRecords,
|
|
4091
4131
|
mintOrReadIdentity,
|
|
4092
4132
|
obtainBuildRecord,
|
|
4133
|
+
pinCreatedByAccountId,
|
|
4093
4134
|
questionsToPut,
|
|
4094
4135
|
readBundlePin,
|
|
4095
4136
|
readRemote,
|