halfcycle 0.3.10 → 0.3.12

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.
@@ -0,0 +1,52 @@
1
+ /**
2
+ * A NAME FOR THE PROJECT THIS INSTALL IS CREATING, derived rather than asked for.
3
+ *
4
+ * Every project created by this CLI was called `Untitled project`: the create call
5
+ * sent no name, so the plane assigned its neutral default, and a person with two
6
+ * projects got two identical rows with nothing to tell them apart. The install
7
+ * already knows two things that are almost always the answer — the git remote and
8
+ * the directory — and neither costs a prompt in a flow that is deliberately quiet.
9
+ *
10
+ * **THE NAME THIS PRODUCES IS A GUESS, AND IT TRAVELS AS ONE.** It is sent in the
11
+ * create call's `derivedName` field, never `name`: a guess and a stated name are
12
+ * different claims, and the plane records which is which so that a name a person
13
+ * actually states later — when the method asks what the product is called —
14
+ * replaces this one. A guess that arrived in the field for stated names would
15
+ * outrank the answer forever, which is worse than the placeholder it replaces.
16
+ *
17
+ * `undefined` is a legitimate answer here (no remote, an unreadable path). The
18
+ * caller sends nothing and the plane's own default applies — this file never
19
+ * invents a placeholder of its own, because that string belongs to the plane.
20
+ *
21
+ * INV-001: Node builtins and bundle-internal modules only.
22
+ */
23
+ /**
24
+ * The repository name inside a git remote URL, or `undefined` if there is not one
25
+ * to read.
26
+ *
27
+ * Both remote forms are handled because both are ordinary: the HTTPS/SSH URL form
28
+ * (`https://host/org/repo.git`, `ssh://git@host/org/repo`) and the scp-like form
29
+ * (`git@host:org/repo.git`), which is not a URL at all and which a URL parser
30
+ * silently mangles. The ORGANISATION is deliberately dropped — `acme-checkout` is
31
+ * a project name a person recognises; `AcmeCorp/acme-checkout` is a coordinate,
32
+ * and the console has a place for coordinates and this is not it.
33
+ *
34
+ * Exported for its own test: the parsing is the part with edge cases, and testing
35
+ * it through a git repository fixture would test git.
36
+ */
37
+ export declare function repositoryNameFromRemote(remote: string): string | undefined;
38
+ /**
39
+ * The name to offer for the project being installed into `targetRepoRoot` — the
40
+ * git remote's repository name, else the directory's own name, else `undefined`.
41
+ *
42
+ * THE REMOTE IS PREFERRED OVER THE DIRECTORY because it is the name the project is
43
+ * known by rather than the name one machine happens to have checked it out under:
44
+ * `~/work/tmp2` and `~/src/checkout` are the same project, and a developer with
45
+ * several clones would otherwise get several differently-named projects.
46
+ *
47
+ * The remote is read through `identity.ts`'s `readRemote`, which is the one home
48
+ * for asking git that question in this package — this file adds no second
49
+ * subprocess and no second failure-swallowing.
50
+ */
51
+ export declare function deriveProjectName(targetRepoRoot: string): string | undefined;
52
+ //# sourceMappingURL=project-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-name.d.ts","sourceRoot":"","sources":["../src/project-name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAsBH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc3E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO5E"}
@@ -58,12 +58,32 @@ export interface ResolvedCredential {
58
58
  credential: string;
59
59
  source: CredentialSource;
60
60
  /**
61
- * The account the credential speaks for, when it is known. ABSENT for the
62
- * environment arm — a bare variable carries no identity and this CLI does not go
63
- * and ask, because the only way to find out is to spend a call, and control will
64
- * tell us by accepting or refusing it a moment later anyway.
61
+ * The account the credential speaks for, when it is known. ABSENT from what THIS
62
+ * RESOLVER returns on the environment arm — a bare variable carries no identity and
63
+ * the resolver does not go and ask, because the only way to find out is to spend a
64
+ * call, and control will tell us by accepting or refusing it a moment later anyway.
65
+ *
66
+ * `confirmActingIdentity` DOES spend that call, so the credential it hands back may
67
+ * carry an id on any arm, including this one — see `actingAs` there. That is the value
68
+ * the install records on disk, and it is control's answer rather than this machine's
69
+ * memory of which account a stored credential was written for.
65
70
  */
66
71
  accountId?: string;
72
+ /**
73
+ * When THIS MACHINE stored the credential, UTC ISO-8601 — present on the `stored`
74
+ * arm and on nothing else (W-2, #803).
75
+ *
76
+ * It is here because it is the fact that makes a reused sign-in recognisable to a
77
+ * human. "This install will act as account 0987fb25…" is a sentence a person cannot
78
+ * check; "…saved on this machine on 30 August" is one they can, because they either
79
+ * signed in that day or somebody else did. A fresh handoff does not carry it (the
80
+ * person is watching it happen) and the environment arm has none to carry.
81
+ *
82
+ * INFORMATION, NEVER A GATE — the same rule the store's `expiresAt` carries. Nothing
83
+ * may refuse or expire a credential on this value; whether a credential is live is
84
+ * control's question, answered with a 401.
85
+ */
86
+ signedInAt?: string;
67
87
  }
68
88
  export interface ResolveOptions extends SignInDeps {
69
89
  /** The process environment to read `HALFCYCLE_TOKEN` and `CI` from. */
@@ -82,6 +102,34 @@ export interface ResolveOptions extends SignInDeps {
82
102
  * back through the browser for a reason that had nothing to do with signing in.
83
103
  */
84
104
  export declare function obtainCredential(serviceUrl: string, opts?: ResolveOptions): Promise<ResolvedCredential>;
105
+ /**
106
+ * The person looked at the account this machine had saved and said *not that one* —
107
+ * forget it and sign in through the browser (W-2, #803).
108
+ *
109
+ * ---------------------------------------------------------------------------
110
+ * IT IS NOT `replaceRefusedCredential`, AND THE DIFFERENCE IS THE ONLY REASON IT IS A
111
+ * SEPARATE FUNCTION. That one is driven by CONTROL refusing a value; this one is driven
112
+ * by a HUMAN refusing an identity. The mechanics coincide today — forget, sign in,
113
+ * store — and they are shared below rather than copied, but the decisions do not:
114
+ *
115
+ * - The refusal path must NOT re-sign-in for an environment credential or a
116
+ * seconds-old one, because both loop. Neither is true here: this is only ever
117
+ * reached from a credential a person was shown and declined, and a person declining
118
+ * an account is a reason to offer them a different one every single time.
119
+ * - The refusal path is a recovery the CLI performs on its own initiative. This one is
120
+ * an instruction, and refusing to carry it out because of a rule about loops would
121
+ * leave a developer holding the exact identity they just said was wrong.
122
+ *
123
+ * Folding the two into one function with a flag was the alternative, and the flag would
124
+ * have been named "the human asked" — which is the whole of the difference, so it is
125
+ * two named functions instead.
126
+ *
127
+ * FORGETTING FIRST IS DELIBERATE. If the handoff is declined or times out, the machine
128
+ * is left with NO saved sign-in rather than with the one the person rejected. The next
129
+ * run then asks the browser, which is the state they were trying to reach; keeping the
130
+ * old value would silently restore the identity they refused.
131
+ */
132
+ export declare function switchAccount(serviceUrl: string, opts?: ResolveOptions): Promise<ResolvedCredential>;
85
133
  /**
86
134
  * Control refused the credential we presented. Replace it, if replacing it is a
87
135
  * thing this CLI is allowed to do.
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-credential.d.ts","sourceRoot":"","sources":["../src/resolve-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAOH,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;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;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,CA0B7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAmBpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAqBxE"}
1
+ {"version":3,"file":"resolve-credential.d.ts","sourceRoot":"","sources":["../src/resolve-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAOH,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;;;;;;;;;;;;;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;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAKpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAqBxE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "halfcycle",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
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",