@momentiq/dark-factory-cli 0.7.0-alpha.9 → 1.0.0
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/cli.js +383 -29
- package/dist/cli.js.map +1 -1
- package/dist/handoff/accept-verb.d.ts +31 -0
- package/dist/handoff/accept-verb.d.ts.map +1 -0
- package/dist/handoff/accept-verb.js +165 -0
- package/dist/handoff/accept-verb.js.map +1 -0
- package/dist/handoff/args.d.ts +19 -0
- package/dist/handoff/args.d.ts.map +1 -0
- package/dist/handoff/args.js +68 -0
- package/dist/handoff/args.js.map +1 -0
- package/dist/handoff/assignees.d.ts +37 -0
- package/dist/handoff/assignees.d.ts.map +1 -0
- package/dist/handoff/assignees.js +46 -0
- package/dist/handoff/assignees.js.map +1 -0
- package/dist/handoff/handoff-verb.d.ts +34 -0
- package/dist/handoff/handoff-verb.d.ts.map +1 -0
- package/dist/handoff/handoff-verb.js +451 -0
- package/dist/handoff/handoff-verb.js.map +1 -0
- package/dist/handoff/handoffs-verb.d.ts +29 -0
- package/dist/handoff/handoffs-verb.d.ts.map +1 -0
- package/dist/handoff/handoffs-verb.js +84 -0
- package/dist/handoff/handoffs-verb.js.map +1 -0
- package/dist/handoff/index.d.ts +14 -143
- package/dist/handoff/index.d.ts.map +1 -1
- package/dist/handoff/index.js +28 -647
- package/dist/handoff/index.js.map +1 -1
- package/dist/handoff/iso.d.ts +9 -0
- package/dist/handoff/iso.d.ts.map +1 -0
- package/dist/handoff/iso.js +47 -0
- package/dist/handoff/iso.js.map +1 -0
- package/dist/handoff/links.d.ts +48 -0
- package/dist/handoff/links.d.ts.map +1 -0
- package/dist/handoff/links.js +211 -0
- package/dist/handoff/links.js.map +1 -0
- package/dist/handoff/markers.d.ts +50 -0
- package/dist/handoff/markers.d.ts.map +1 -0
- package/dist/handoff/markers.js +121 -0
- package/dist/handoff/markers.js.map +1 -0
- package/dist/handoff/ports.d.ts +126 -0
- package/dist/handoff/ports.d.ts.map +1 -0
- package/dist/handoff/ports.js +34 -0
- package/dist/handoff/ports.js.map +1 -0
- package/dist/handoff/real-clients.d.ts +43 -0
- package/dist/handoff/real-clients.d.ts.map +1 -0
- package/dist/handoff/real-clients.js +291 -0
- package/dist/handoff/real-clients.js.map +1 -0
- package/dist/handoff/rehydrate-core.d.ts +55 -0
- package/dist/handoff/rehydrate-core.d.ts.map +1 -0
- package/dist/handoff/rehydrate-core.js +243 -0
- package/dist/handoff/rehydrate-core.js.map +1 -0
- package/dist/handoff/rehydrate-render.d.ts +3 -0
- package/dist/handoff/rehydrate-render.d.ts.map +1 -0
- package/dist/handoff/rehydrate-render.js +107 -0
- package/dist/handoff/rehydrate-render.js.map +1 -0
- package/dist/handoff/rehydrate-verb.d.ts +31 -0
- package/dist/handoff/rehydrate-verb.d.ts.map +1 -0
- package/dist/handoff/rehydrate-verb.js +111 -0
- package/dist/handoff/rehydrate-verb.js.map +1 -0
- package/dist/handoff/scrub.d.ts +99 -0
- package/dist/handoff/scrub.d.ts.map +1 -0
- package/dist/handoff/scrub.js +127 -0
- package/dist/handoff/scrub.js.map +1 -0
- package/dist/handoff/strip-control.d.ts +4 -0
- package/dist/handoff/strip-control.d.ts.map +1 -0
- package/dist/handoff/strip-control.js +16 -0
- package/dist/handoff/strip-control.js.map +1 -0
- package/dist/mcp/server.d.ts +0 -8
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/handoff.d.ts +16 -8
- package/dist/mcp/tools/handoff.d.ts.map +1 -1
- package/dist/mcp/tools/handoff.js +253 -303
- package/dist/mcp/tools/handoff.js.map +1 -1
- package/package.json +2 -2
- package/dist/handoff/cli.d.ts +0 -5
- package/dist/handoff/cli.d.ts.map +0 -1
- package/dist/handoff/cli.js +0 -227
- package/dist/handoff/cli.js.map +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raised by the core for every operator-facing refusal/abort (the bash
|
|
3
|
+
* `die`). Carries an optional `savedNotePath` so the CLI can echo where a
|
|
4
|
+
* composed note was preserved when a push/gate blocked it (Decision D5 —
|
|
5
|
+
* the reasoning is the precious artifact and is never discarded).
|
|
6
|
+
*/
|
|
7
|
+
export declare class HandoffError extends Error {
|
|
8
|
+
readonly savedNotePath: string | undefined;
|
|
9
|
+
constructor(message: string, savedNotePath?: string);
|
|
10
|
+
}
|
|
11
|
+
export interface IssueView {
|
|
12
|
+
readonly number: number;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
readonly body: string;
|
|
15
|
+
readonly state: "OPEN" | "CLOSED";
|
|
16
|
+
readonly assignees: ReadonlyArray<{
|
|
17
|
+
readonly login: string;
|
|
18
|
+
}>;
|
|
19
|
+
readonly labels: ReadonlyArray<{
|
|
20
|
+
readonly name: string;
|
|
21
|
+
}>;
|
|
22
|
+
readonly updatedAt: string;
|
|
23
|
+
readonly closedAt: string | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Subset of IssueView fields for drift/race checks (assignees + state +
|
|
27
|
+
* updatedAt; body omitted). Separate seam from issueView so the fake's
|
|
28
|
+
* ordinal counters split: _body-bearing_ vs _drift-only_ calls increment
|
|
29
|
+
* independently (mirrors bash's `issue_view_body` vs `issue_view` counter
|
|
30
|
+
* namespaces in tests/bin/gh).
|
|
31
|
+
*/
|
|
32
|
+
export interface IssueViewSlim {
|
|
33
|
+
readonly state: "OPEN" | "CLOSED";
|
|
34
|
+
readonly assignees: ReadonlyArray<{
|
|
35
|
+
readonly login: string;
|
|
36
|
+
}>;
|
|
37
|
+
readonly updatedAt: string;
|
|
38
|
+
/** body is optional — the drift check may skip it. */
|
|
39
|
+
readonly body?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface PrView {
|
|
42
|
+
readonly title: string;
|
|
43
|
+
readonly state: "OPEN" | "CLOSED" | "MERGED";
|
|
44
|
+
readonly mergeStateStatus: string;
|
|
45
|
+
readonly reviewDecision: string;
|
|
46
|
+
readonly statusCheckRollup: ReadonlyArray<{
|
|
47
|
+
readonly conclusion?: string;
|
|
48
|
+
readonly state?: string;
|
|
49
|
+
readonly status?: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
export interface IssueListItem {
|
|
53
|
+
readonly number: number;
|
|
54
|
+
readonly title: string;
|
|
55
|
+
readonly assignees: ReadonlyArray<{
|
|
56
|
+
readonly login: string;
|
|
57
|
+
}>;
|
|
58
|
+
readonly body?: string;
|
|
59
|
+
readonly createdAt?: string;
|
|
60
|
+
readonly updatedAt?: string;
|
|
61
|
+
readonly closedAt?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface IssueCreated {
|
|
64
|
+
readonly number: number;
|
|
65
|
+
readonly url: string;
|
|
66
|
+
}
|
|
67
|
+
export interface GhClient {
|
|
68
|
+
/** `gh auth status` — throws on non-zero. */
|
|
69
|
+
authStatus(): Promise<void>;
|
|
70
|
+
/** `gh api user --jq .login` */
|
|
71
|
+
apiUserLogin(): Promise<string>;
|
|
72
|
+
/** `gh label create handoff …` (idempotent — failure not fatal) */
|
|
73
|
+
ensureHandoffLabel(): Promise<void>;
|
|
74
|
+
/** `gh issue view <n> --json <full set>` — full IssueView (body included) */
|
|
75
|
+
issueView(num: number, opts?: {
|
|
76
|
+
repo?: string;
|
|
77
|
+
}): Promise<IssueView>;
|
|
78
|
+
/** Same fields minus body (separate seam for drift checks). */
|
|
79
|
+
issueViewSlim(num: number, opts?: {
|
|
80
|
+
repo?: string;
|
|
81
|
+
}): Promise<IssueViewSlim>;
|
|
82
|
+
/** `gh issue list --label handoff --state <s> ...` */
|
|
83
|
+
issueList(opts: {
|
|
84
|
+
state: "open" | "closed";
|
|
85
|
+
assignee?: "@me" | string;
|
|
86
|
+
search?: string;
|
|
87
|
+
}): Promise<readonly IssueListItem[]>;
|
|
88
|
+
/** `gh issue create --title <t> --body-file - --label handoff` */
|
|
89
|
+
issueCreate(opts: {
|
|
90
|
+
title: string;
|
|
91
|
+
bodyMd: string;
|
|
92
|
+
label: string;
|
|
93
|
+
}): Promise<IssueCreated>;
|
|
94
|
+
/** `gh issue edit <n> --body-file -` */
|
|
95
|
+
issueEditBody(num: number, bodyMd: string): Promise<void>;
|
|
96
|
+
/** `gh issue edit <n> --add-label <l>` */
|
|
97
|
+
issueAddLabel(num: number, label: string): Promise<void>;
|
|
98
|
+
/** `gh issue edit <n> --add-assignee @me` */
|
|
99
|
+
issueAssignMe(num: number): Promise<void>;
|
|
100
|
+
/** `gh issue edit <n> --remove-assignee @me` — idempotent; throws only on REAL gh errors. */
|
|
101
|
+
issueUnassignMe(num: number): Promise<void>;
|
|
102
|
+
/** `gh issue close <n>` */
|
|
103
|
+
issueClose(num: number): Promise<void>;
|
|
104
|
+
/** `gh pr view <n> --json state,mergeStateStatus,reviewDecision,statusCheckRollup,title` */
|
|
105
|
+
prView(num: number, opts?: {
|
|
106
|
+
repo?: string;
|
|
107
|
+
}): Promise<PrView>;
|
|
108
|
+
/** `gh pr list --head <branch> --state open --json number,title` */
|
|
109
|
+
prListByHead(branch: string): Promise<ReadonlyArray<{
|
|
110
|
+
number: number;
|
|
111
|
+
title: string;
|
|
112
|
+
}>>;
|
|
113
|
+
}
|
|
114
|
+
export interface GitClient {
|
|
115
|
+
/** `git rev-parse --abbrev-ref HEAD` — returns "HEAD" on detached. */
|
|
116
|
+
currentBranch(): Promise<string>;
|
|
117
|
+
/** True iff `git diff --quiet` OR `git diff --cached --quiet` returns non-zero. */
|
|
118
|
+
isDirty(): Promise<boolean>;
|
|
119
|
+
}
|
|
120
|
+
export interface Clock {
|
|
121
|
+
/** Epoch seconds (Unix). */
|
|
122
|
+
nowEpoch(): number;
|
|
123
|
+
/** YYYY-MM-DD in UTC. */
|
|
124
|
+
todayYmd(): string;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=ports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/handoff/ports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// packages/cli/src/handoff/ports.ts
|
|
2
|
+
//
|
|
3
|
+
// Hexagonal ports: GhClient + GitClient + Clock. All side-effecting verbs
|
|
4
|
+
// take these as parameters; tests inject queue-based fakes (see
|
|
5
|
+
// tests/handoff/fixtures/stubs/), production uses real-clients.ts which
|
|
6
|
+
// spawns gh/git.
|
|
7
|
+
//
|
|
8
|
+
// The GhClient surface is fine-grained per gh idiom (one method per gh
|
|
9
|
+
// verb pattern the bash uses) so the test fake can ordinal-key responses
|
|
10
|
+
// per-method, mirroring bash's _bump_counter + STUB_ISSUE_BODY_N seam.
|
|
11
|
+
// The verb impl is constrained to call these in the SAME ORDER the bash
|
|
12
|
+
// did — drift/race tests assert that order (see advisor finding #2).
|
|
13
|
+
//
|
|
14
|
+
// HandoffError is the SINGLE class identity used across every v2 throw
|
|
15
|
+
// site (verbs + ports + clients). Defined here (the lowest leaf in the
|
|
16
|
+
// handoff module graph) so the new public surface (./index.js, Task 23)
|
|
17
|
+
// can re-export from here without a cycle. The v1 monolith used to own
|
|
18
|
+
// this class — Task 22 inverted the re-export when the v1 index.ts was
|
|
19
|
+
// deleted, so this is now the canonical definition.
|
|
20
|
+
/**
|
|
21
|
+
* Raised by the core for every operator-facing refusal/abort (the bash
|
|
22
|
+
* `die`). Carries an optional `savedNotePath` so the CLI can echo where a
|
|
23
|
+
* composed note was preserved when a push/gate blocked it (Decision D5 —
|
|
24
|
+
* the reasoning is the precious artifact and is never discarded).
|
|
25
|
+
*/
|
|
26
|
+
export class HandoffError extends Error {
|
|
27
|
+
savedNotePath;
|
|
28
|
+
constructor(message, savedNotePath) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "HandoffError";
|
|
31
|
+
this.savedNotePath = savedNotePath;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/handoff/ports.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,0EAA0E;AAC1E,gEAAgE;AAChE,wEAAwE;AACxE,iBAAiB;AACjB,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,wEAAwE;AACxE,qEAAqE;AACrE,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,uEAAuE;AACvE,uEAAuE;AACvE,oDAAoD;AAEpD;;;;;GAKG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,aAAa,CAAqB;IAC3C,YAAY,OAAe,EAAE,aAAsB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Clock, GhClient, GitClient, IssueCreated, IssueListItem, IssueView, IssueViewSlim, PrView } from "./ports.js";
|
|
2
|
+
export declare class SpawnGhClient implements GhClient {
|
|
3
|
+
authStatus(): Promise<void>;
|
|
4
|
+
apiUserLogin(): Promise<string>;
|
|
5
|
+
ensureHandoffLabel(): Promise<void>;
|
|
6
|
+
issueView(num: number, opts?: {
|
|
7
|
+
repo?: string;
|
|
8
|
+
}): Promise<IssueView>;
|
|
9
|
+
issueViewSlim(num: number, opts?: {
|
|
10
|
+
repo?: string;
|
|
11
|
+
}): Promise<IssueViewSlim>;
|
|
12
|
+
issueList(opts: {
|
|
13
|
+
state: "open" | "closed";
|
|
14
|
+
assignee?: "@me" | string;
|
|
15
|
+
search?: string;
|
|
16
|
+
}): Promise<readonly IssueListItem[]>;
|
|
17
|
+
issueCreate(opts: {
|
|
18
|
+
title: string;
|
|
19
|
+
bodyMd: string;
|
|
20
|
+
label: string;
|
|
21
|
+
}): Promise<IssueCreated>;
|
|
22
|
+
issueEditBody(num: number, bodyMd: string): Promise<void>;
|
|
23
|
+
issueAddLabel(num: number, label: string): Promise<void>;
|
|
24
|
+
issueAssignMe(num: number): Promise<void>;
|
|
25
|
+
issueUnassignMe(num: number): Promise<void>;
|
|
26
|
+
issueClose(num: number): Promise<void>;
|
|
27
|
+
prView(num: number, opts?: {
|
|
28
|
+
repo?: string;
|
|
29
|
+
}): Promise<PrView>;
|
|
30
|
+
prListByHead(branch: string): Promise<ReadonlyArray<{
|
|
31
|
+
number: number;
|
|
32
|
+
title: string;
|
|
33
|
+
}>>;
|
|
34
|
+
}
|
|
35
|
+
export declare class SpawnGitClient implements GitClient {
|
|
36
|
+
currentBranch(): Promise<string>;
|
|
37
|
+
isDirty(): Promise<boolean>;
|
|
38
|
+
}
|
|
39
|
+
export declare class SystemClock implements Clock {
|
|
40
|
+
nowEpoch(): number;
|
|
41
|
+
todayYmd(): string;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=real-clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"real-clients.d.ts","sourceRoot":"","sources":["../../src/handoff/real-clients.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EACV,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,SAAS,EACT,aAAa,EACb,MAAM,EACP,MAAM,YAAY,CAAC;AAuGpB,qBAAa,aAAc,YAAW,QAAQ;IACtC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAc/B,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC,SAAS,CACb,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAC3B,OAAO,CAAC,SAAS,CAAC;IAWf,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAC3B,OAAO,CAAC,aAAa,CAAC;IAQnB,SAAS,CAAC,IAAI,EAAE;QACpB,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;QACzB,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC;IAmB/B,WAAW,CAAC,IAAI,EAAE;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,YAAY,CAAC;IAiCnB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B3C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAWlE,YAAY,CAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAgB7D;AAMD,qBAAa,cAAe,YAAW,SAAS;IACxC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAQhC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAMlC;AAMD,qBAAa,WAAY,YAAW,KAAK;IACvC,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;CAOnB"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// packages/cli/src/handoff/real-clients.ts
|
|
2
|
+
//
|
|
3
|
+
// Production spawn-based implementations of the GhClient + GitClient + Clock
|
|
4
|
+
// ports. Tests use the queue-based FakeGhClient/FakeGitClient/FixedClock
|
|
5
|
+
// from tests/handoff/fixtures/stubs/ (Task 8) — these clients are exercised
|
|
6
|
+
// end-to-end by the verb tests (Tasks 17-20) and live-smoke (Task 32).
|
|
7
|
+
//
|
|
8
|
+
// The spawn pattern mirrors the Cycle 8 v1 defaultExec in index.ts:50-120,
|
|
9
|
+
// consolidated here as the home for the production clients. Two deliberate
|
|
10
|
+
// divergences from v1:
|
|
11
|
+
//
|
|
12
|
+
// 1. v1 resolves {code:127} on ENOENT and a separate requireTools() layer
|
|
13
|
+
// translates 127 → HandoffError. The standalone clients here throw
|
|
14
|
+
// HandoffError DIRECTLY from exec() on ENOENT — there is no
|
|
15
|
+
// requireTools wrapper in the hexagonal seam. Consequence:
|
|
16
|
+
// currentBranch/isDirty/issueUnassignMe still swallow non-zero exit
|
|
17
|
+
// codes (their intended behavior), but throw if gh/git is entirely
|
|
18
|
+
// absent — which is the correct distinction (missing binary ≠ "clean
|
|
19
|
+
// tree"/"not assigned"). v1 is deleted in Task 22.
|
|
20
|
+
// 2. The bash-side issueUnassignMe was idempotent on "not assigned"
|
|
21
|
+
// stderr (handoff.sh, the `*"not assigned"*` case). Mirrored here.
|
|
22
|
+
//
|
|
23
|
+
// HandoffError is imported as a VALUE (since we throw it); everything else
|
|
24
|
+
// is type-only. ports.ts re-exports HandoffError from ./index.js for the
|
|
25
|
+
// Tasks 11-22 window — Task 22 inverts that to put the class here in ports.
|
|
26
|
+
import { spawn } from "node:child_process";
|
|
27
|
+
import { HandoffError } from "./ports.js";
|
|
28
|
+
const MAX_BUFFER = 64 * 1024 * 1024;
|
|
29
|
+
/**
|
|
30
|
+
* Spawn helper. Resolves with {code, stdout, stderr} regardless of process
|
|
31
|
+
* exit status. Rejects ONLY on spawn-time errors — and an ENOENT (binary
|
|
32
|
+
* not on PATH) is translated into a HandoffError with an actionable
|
|
33
|
+
* "install …" message so the operator sees the fix path, not a raw Node
|
|
34
|
+
* error.
|
|
35
|
+
*
|
|
36
|
+
* SECURITY: this uses `child_process.spawn` with an argument-array form
|
|
37
|
+
* (no shell, no string interpolation). NOT `child_process.exec` — the
|
|
38
|
+
* local helper is named `exec` because it returns an ExecResult, not
|
|
39
|
+
* because it shells out. There is no shell process; arguments go
|
|
40
|
+
* directly to the child binary, so shell metacharacters in user input
|
|
41
|
+
* are inert. The bin name itself is a fixed literal ("gh"/"git").
|
|
42
|
+
*
|
|
43
|
+
* `spawn` (not `execFile`/`promisify`) is mandatory: some calls pipe a
|
|
44
|
+
* body to `--body-file -` on the child's STDIN. promisify(execFile)'s
|
|
45
|
+
* `input` option is silently dropped (it's exec-only), which would send
|
|
46
|
+
* EMPTY input and hang the child waiting on EOF.
|
|
47
|
+
*/
|
|
48
|
+
function exec(bin, args, options = {}) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const child = spawn(bin, [...args], {
|
|
51
|
+
stdio: [options.input !== undefined ? "pipe" : "ignore", "pipe", "pipe"],
|
|
52
|
+
});
|
|
53
|
+
let stdout = "";
|
|
54
|
+
let stderr = "";
|
|
55
|
+
let overflow = false;
|
|
56
|
+
child.stdout?.on("data", (chunk) => {
|
|
57
|
+
if (stdout.length < MAX_BUFFER)
|
|
58
|
+
stdout += chunk.toString("utf8");
|
|
59
|
+
else
|
|
60
|
+
overflow = true;
|
|
61
|
+
});
|
|
62
|
+
child.stderr?.on("data", (chunk) => {
|
|
63
|
+
if (stderr.length < MAX_BUFFER)
|
|
64
|
+
stderr += chunk.toString("utf8");
|
|
65
|
+
});
|
|
66
|
+
child.on("error", (err) => {
|
|
67
|
+
const nodeErr = err;
|
|
68
|
+
if (nodeErr.code === "ENOENT") {
|
|
69
|
+
reject(new HandoffError(bin === "gh"
|
|
70
|
+
? "gh not found — install GitHub CLI and run 'gh auth login'."
|
|
71
|
+
: `${bin} not found — install ${bin}.`));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
reject(err);
|
|
75
|
+
});
|
|
76
|
+
child.on("close", (code) => {
|
|
77
|
+
resolve({
|
|
78
|
+
code: overflow ? 1 : (code ?? 1),
|
|
79
|
+
stdout,
|
|
80
|
+
stderr,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
if (options.input !== undefined && child.stdin) {
|
|
84
|
+
child.stdin.on("error", () => {
|
|
85
|
+
// EPIPE if the child exits before reading stdin — non-fatal; the
|
|
86
|
+
// close handler reports the real exit code.
|
|
87
|
+
});
|
|
88
|
+
child.stdin.end(options.input);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function gh(args, options = {}) {
|
|
93
|
+
return exec("gh", args, options);
|
|
94
|
+
}
|
|
95
|
+
function git(args) {
|
|
96
|
+
return exec("git", args);
|
|
97
|
+
}
|
|
98
|
+
/** Throw HandoffError with stderr text on non-zero exit; return on ok. */
|
|
99
|
+
function expectOk(result, context) {
|
|
100
|
+
if (result.code !== 0) {
|
|
101
|
+
const stderr = result.stderr.trim() || "(no stderr)";
|
|
102
|
+
throw new HandoffError(`${context} failed (exit ${result.code}): ${stderr}`);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// SpawnGhClient — 14 methods covering every gh verb pattern the bash uses.
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
export class SpawnGhClient {
|
|
110
|
+
async authStatus() {
|
|
111
|
+
const r = await gh(["auth", "status"]);
|
|
112
|
+
if (r.code !== 0) {
|
|
113
|
+
throw new HandoffError("gh not authenticated — run 'gh auth login'.");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async apiUserLogin() {
|
|
117
|
+
const r = expectOk(await gh(["api", "user", "--jq", ".login"]), "gh api user");
|
|
118
|
+
const login = r.stdout.trim();
|
|
119
|
+
if (!login) {
|
|
120
|
+
throw new HandoffError("could not determine @me's login (gh api user returned empty) — run 'gh auth status'.");
|
|
121
|
+
}
|
|
122
|
+
return login;
|
|
123
|
+
}
|
|
124
|
+
async ensureHandoffLabel() {
|
|
125
|
+
// Idempotent: never fatal. gh returns non-zero if the label exists.
|
|
126
|
+
await gh([
|
|
127
|
+
"label",
|
|
128
|
+
"create",
|
|
129
|
+
"handoff",
|
|
130
|
+
"--description",
|
|
131
|
+
"Agent handoff (Cycle 12 protocol)",
|
|
132
|
+
"--color",
|
|
133
|
+
"cccccc",
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
136
|
+
async issueView(num, opts = {}) {
|
|
137
|
+
const args = ["issue", "view", String(num)];
|
|
138
|
+
if (opts.repo)
|
|
139
|
+
args.push("--repo", opts.repo);
|
|
140
|
+
args.push("--json", "number,title,body,state,assignees,labels,updatedAt,closedAt");
|
|
141
|
+
const r = expectOk(await gh(args), `gh issue view ${num}`);
|
|
142
|
+
return JSON.parse(r.stdout);
|
|
143
|
+
}
|
|
144
|
+
async issueViewSlim(num, opts = {}) {
|
|
145
|
+
const args = ["issue", "view", String(num)];
|
|
146
|
+
if (opts.repo)
|
|
147
|
+
args.push("--repo", opts.repo);
|
|
148
|
+
args.push("--json", "state,assignees,updatedAt");
|
|
149
|
+
const r = expectOk(await gh(args), `gh issue view ${num} (slim)`);
|
|
150
|
+
return JSON.parse(r.stdout);
|
|
151
|
+
}
|
|
152
|
+
async issueList(opts) {
|
|
153
|
+
const args = [
|
|
154
|
+
"issue",
|
|
155
|
+
"list",
|
|
156
|
+
"--label",
|
|
157
|
+
"handoff",
|
|
158
|
+
"--state",
|
|
159
|
+
opts.state,
|
|
160
|
+
];
|
|
161
|
+
if (opts.assignee)
|
|
162
|
+
args.push("--assignee", opts.assignee);
|
|
163
|
+
if (opts.search)
|
|
164
|
+
args.push("--search", opts.search);
|
|
165
|
+
args.push("--json", "number,title,assignees,body,createdAt,updatedAt,closedAt");
|
|
166
|
+
const r = expectOk(await gh(args), "gh issue list");
|
|
167
|
+
return JSON.parse(r.stdout);
|
|
168
|
+
}
|
|
169
|
+
async issueCreate(opts) {
|
|
170
|
+
const args = [
|
|
171
|
+
"issue",
|
|
172
|
+
"create",
|
|
173
|
+
"--title",
|
|
174
|
+
opts.title,
|
|
175
|
+
"--label",
|
|
176
|
+
opts.label,
|
|
177
|
+
"--body-file",
|
|
178
|
+
"-",
|
|
179
|
+
];
|
|
180
|
+
const r = await gh(args, { input: opts.bodyMd });
|
|
181
|
+
if (r.code !== 0) {
|
|
182
|
+
throw new HandoffError(`gh issue create failed (exit ${r.code}): ${r.stderr.trim() || r.stdout.trim() || "(no output)"}`);
|
|
183
|
+
}
|
|
184
|
+
// gh issue create prints the URL on stdout (last non-empty line).
|
|
185
|
+
const lines = r.stdout
|
|
186
|
+
.trim()
|
|
187
|
+
.split("\n")
|
|
188
|
+
.map((line) => line.trim())
|
|
189
|
+
.filter((line) => line.length > 0);
|
|
190
|
+
const url = lines[lines.length - 1] ?? "";
|
|
191
|
+
const match = url.match(/\/issues\/(\d+)\b/);
|
|
192
|
+
if (!match) {
|
|
193
|
+
throw new HandoffError(`could not parse issue number from \`gh issue create\` output: ${r.stdout.trim()}`);
|
|
194
|
+
}
|
|
195
|
+
return { number: Number(match[1]), url };
|
|
196
|
+
}
|
|
197
|
+
async issueEditBody(num, bodyMd) {
|
|
198
|
+
const args = ["issue", "edit", String(num), "--body-file", "-"];
|
|
199
|
+
const r = await gh(args, { input: bodyMd });
|
|
200
|
+
if (r.code !== 0) {
|
|
201
|
+
throw new HandoffError(`gh issue edit ${num} --body-file failed (exit ${r.code}): ${r.stderr.trim() || "(no stderr)"}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async issueAddLabel(num, label) {
|
|
205
|
+
expectOk(await gh(["issue", "edit", String(num), "--add-label", label]), `gh issue edit ${num} --add-label ${label}`);
|
|
206
|
+
}
|
|
207
|
+
async issueAssignMe(num) {
|
|
208
|
+
expectOk(await gh(["issue", "edit", String(num), "--add-assignee", "@me"]), `gh issue edit ${num} --add-assignee @me`);
|
|
209
|
+
}
|
|
210
|
+
async issueUnassignMe(num) {
|
|
211
|
+
// Bash parity: handoff.sh treats "not assigned" stderr as idempotent
|
|
212
|
+
// success (same case-arm in the shell version). Mirror that here so
|
|
213
|
+
// /handoff on a PR that's no longer assigned to @me is a no-op rather
|
|
214
|
+
// than an error.
|
|
215
|
+
const r = await gh([
|
|
216
|
+
"issue",
|
|
217
|
+
"edit",
|
|
218
|
+
String(num),
|
|
219
|
+
"--remove-assignee",
|
|
220
|
+
"@me",
|
|
221
|
+
]);
|
|
222
|
+
if (r.code !== 0) {
|
|
223
|
+
const stderr = r.stderr;
|
|
224
|
+
if (/not assigned/i.test(stderr) ||
|
|
225
|
+
/could not assign/i.test(stderr) ||
|
|
226
|
+
/cannot remove/i.test(stderr)) {
|
|
227
|
+
return; // idempotent no-op
|
|
228
|
+
}
|
|
229
|
+
throw new HandoffError(`gh issue edit ${num} --remove-assignee @me failed: ${stderr.trim() || "(no stderr)"}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async issueClose(num) {
|
|
233
|
+
expectOk(await gh(["issue", "close", String(num)]), `gh issue close ${num}`);
|
|
234
|
+
}
|
|
235
|
+
async prView(num, opts = {}) {
|
|
236
|
+
const args = ["pr", "view", String(num)];
|
|
237
|
+
if (opts.repo)
|
|
238
|
+
args.push("--repo", opts.repo);
|
|
239
|
+
args.push("--json", "state,mergeStateStatus,reviewDecision,statusCheckRollup,title");
|
|
240
|
+
const r = expectOk(await gh(args), `gh pr view ${num}`);
|
|
241
|
+
return JSON.parse(r.stdout);
|
|
242
|
+
}
|
|
243
|
+
async prListByHead(branch) {
|
|
244
|
+
const r = expectOk(await gh([
|
|
245
|
+
"pr",
|
|
246
|
+
"list",
|
|
247
|
+
"--head",
|
|
248
|
+
branch,
|
|
249
|
+
"--state",
|
|
250
|
+
"open",
|
|
251
|
+
"--json",
|
|
252
|
+
"number,title",
|
|
253
|
+
]), `gh pr list --head ${branch}`);
|
|
254
|
+
return JSON.parse(r.stdout);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// SpawnGitClient — currentBranch + isDirty.
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
export class SpawnGitClient {
|
|
261
|
+
async currentBranch() {
|
|
262
|
+
const r = await git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
263
|
+
// Non-zero (e.g., not in a repo) → fall back to "HEAD" so callers
|
|
264
|
+
// get a stable string rather than an exception. ENOENT (git missing)
|
|
265
|
+
// still throws from exec().
|
|
266
|
+
return r.code === 0 ? r.stdout.trim() || "HEAD" : "HEAD";
|
|
267
|
+
}
|
|
268
|
+
async isDirty() {
|
|
269
|
+
const unstaged = await git(["diff", "--quiet"]);
|
|
270
|
+
if (unstaged.code !== 0)
|
|
271
|
+
return true;
|
|
272
|
+
const staged = await git(["diff", "--cached", "--quiet"]);
|
|
273
|
+
return staged.code !== 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// SystemClock — wall clock for format_age + create-title date.
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
export class SystemClock {
|
|
280
|
+
nowEpoch() {
|
|
281
|
+
return Math.floor(Date.now() / 1000);
|
|
282
|
+
}
|
|
283
|
+
todayYmd() {
|
|
284
|
+
const d = new Date();
|
|
285
|
+
const y = d.getUTCFullYear();
|
|
286
|
+
const m = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
287
|
+
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
288
|
+
return `${y}-${m}-${day}`;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=real-clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"real-clients.js","sourceRoot":"","sources":["../../src/handoff/real-clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type GhClient } from "./ports.js";
|
|
2
|
+
export interface LinkedItemDerivation {
|
|
3
|
+
readonly kind: "pr" | "issue" | "?";
|
|
4
|
+
readonly display: string;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly state: "OPEN" | "CLOSED" | "MERGED" | "UNREACHABLE";
|
|
7
|
+
/** Human annotation: "", "(merged)", "(closed)",
|
|
8
|
+
* "(unreachable: gh pr view failed)" / "(unreachable: gh issue view failed)",
|
|
9
|
+
* "[open]", "[open, assigned X]", "(unknown link type)". */
|
|
10
|
+
readonly annotation: string;
|
|
11
|
+
/** Present for OPEN PRs only — copy-pastable `gh pr checkout N [--repo owner/repo]`. */
|
|
12
|
+
readonly checkoutHint?: string;
|
|
13
|
+
/** Extra fields for OPEN PRs (mergeStateStatus/reviewDecision/checksSummary)
|
|
14
|
+
* or OPEN issues (assigneesCsv). Absent for MERGED/CLOSED/UNREACHABLE. */
|
|
15
|
+
readonly extra?: {
|
|
16
|
+
readonly mergeStateStatus?: string;
|
|
17
|
+
readonly reviewDecision?: string;
|
|
18
|
+
readonly checksSummary?: string;
|
|
19
|
+
readonly assigneesCsv?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface RehydrateData {
|
|
23
|
+
readonly issueNumber: number;
|
|
24
|
+
/** Stripped of control chars (operator-editable title — ANSI defense). */
|
|
25
|
+
readonly title: string;
|
|
26
|
+
/** Value only — render adds the `state: ` prefix and indentation.
|
|
27
|
+
* One of:
|
|
28
|
+
* "open (unassigned — on the stack)"
|
|
29
|
+
* "open (assigned X[,Y...])"
|
|
30
|
+
* "closed (accepted YYYY-MM-DD)"
|
|
31
|
+
* "closed"
|
|
32
|
+
*/
|
|
33
|
+
readonly stateLine: string;
|
|
34
|
+
readonly linkedItems: readonly LinkedItemDerivation[];
|
|
35
|
+
/** Count of items with state === "UNREACHABLE" (strict-mode trigger). */
|
|
36
|
+
readonly linkFailures: number;
|
|
37
|
+
/** Last marker block from `view.body`, INCLUDING the marker tokens.
|
|
38
|
+
* `null` if no well-formed block found. Control chars NOT yet stripped —
|
|
39
|
+
* the renderer strips them at print time (matches bash). */
|
|
40
|
+
readonly note: string | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Derive structured live state for handoff issue #N. Used by /accept (strict),
|
|
44
|
+
* /rehydrate (lenient), and df_rehydrate (MCP structuredContent).
|
|
45
|
+
*
|
|
46
|
+
* Linked items are processed SEQUENTIALLY (bash parity + FakeGhClient ordinal
|
|
47
|
+
* slot stability). The MAIN issue is the FIRST `issueView` call; any linked
|
|
48
|
+
* issues that follow share that counter, so test slots are 1 = handoff, 2+ =
|
|
49
|
+
* linked issues.
|
|
50
|
+
*
|
|
51
|
+
* @throws HandoffError if `gh.issueView(issueNum)` fails — the live-state
|
|
52
|
+
* anchor is required; don't proceed on the note alone.
|
|
53
|
+
*/
|
|
54
|
+
export declare function deriveRehydrateData(issueNum: number, gh: GhClient): Promise<RehydrateData>;
|
|
55
|
+
//# sourceMappingURL=rehydrate-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rehydrate-core.d.ts","sourceRoot":"","sources":["../../src/handoff/rehydrate-core.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAgB,KAAK,QAAQ,EAAe,MAAM,YAAY,CAAC;AAGtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,GAAG,GAAG,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC7D;;gEAE4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;8EAC0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACtD,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;gEAE4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAqJD;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC,aAAa,CAAC,CA0DxB"}
|