halfcycle 0.4.6 → 0.4.8

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.
@@ -38,7 +38,7 @@
38
38
  * note. The service freezes both into the phase's Build Record; the caller fetches
39
39
  * that record afterwards (`build-record/obtain.ts`).
40
40
  */
41
- import { type AcceptanceOutcome, type PhaseCloseDecision } from '@halfcycle/events';
41
+ import { type AcceptanceOutcome, type MethodUpdate, type PhaseCloseDecision } from '@halfcycle/events';
42
42
  import { type PhaseStampFailure, type RepoCredential } from './open-phase.js';
43
43
  /**
44
44
  * Whether the commit this phase closed at could be read, and if so the full hash
@@ -76,6 +76,13 @@ export interface ClosedPhase {
76
76
  stampFailure: PhaseStampFailure | null;
77
77
  /** The commit sent with the close, or why none could be read. */
78
78
  closeCommit: CloseCommitOutcome;
79
+ /**
80
+ * The method version this close moved the project to (`existing-projects-carry-on`
81
+ * AC2), or `null` when it did not move. An older control's answer carries no
82
+ * field at all, which reads the same as `null` here — this CLI then prints
83
+ * and writes nothing about a move, exactly as it did before this field existed.
84
+ */
85
+ methodUpdated: MethodUpdate | null;
79
86
  }
80
87
  /**
81
88
  * Read the full HEAD commit of the NAMED repository, before the close is sent.
@@ -1 +1 @@
1
- {"version":3,"file":"close-phase.d.ts","sourceRoot":"","sources":["../src/close-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmB,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG/F;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,4EAA4E;AAC5E,eAAO,MAAM,aAAa,EAAE,gBAAkE,CAAC;AAE/F,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,iEAAiE;IACjE,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CA4BhF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,MAAM,EAAE,MAAM;IAE9B;;;;;OAKG;aACa,OAAO,CAAC,EAAE,MAAM;IAChC;;;;;;;;;;OAUG;aACa,IAAI,CAAC,EAAE,MAAM;gBApBb,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;IACf;;;;;OAKG;IACa,OAAO,CAAC,EAAE,MAAM,YAAA;IAChC;;;;;;;;;;OAUG;IACa,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,kBAAkB,EACzB,IAAI,CAAC,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,gBAAgC,GACvC,OAAO,CAAC,WAAW,CAAC,CAyEtB"}
1
+ {"version":3,"file":"close-phase.d.ts","sourceRoot":"","sources":["../src/close-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmB,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG/F;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,4EAA4E;AAC5E,eAAO,MAAM,aAAa,EAAE,gBAAkE,CAAC;AAE/F,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,iEAAiE;IACjE,WAAW,EAAE,kBAAkB,CAAC;IAChC;;;;;OAKG;IACH,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;CACpC;AAcD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CA4BhF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,MAAM,EAAE,MAAM;IAE9B;;;;;OAKG;aACa,OAAO,CAAC,EAAE,MAAM;IAChC;;;;;;;;;;OAUG;aACa,IAAI,CAAC,EAAE,MAAM;gBApBb,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;IACf;;;;;OAKG;IACa,OAAO,CAAC,EAAE,MAAM,YAAA;IAChC;;;;;;;;;;OAUG;IACa,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,kBAAkB,EACzB,IAAI,CAAC,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,GAAE,gBAAgC,GACvC,OAAO,CAAC,WAAW,CAAC,CAiFtB"}
@@ -1,17 +1,27 @@
1
1
  /**
2
2
  * The client half of `npx halfcycle@latest draw architecture` (System view · E1,
3
- * feature `diagram-files-for-docs`, AC1, AC4, AC5, AC6 and AC8's missing route).
3
+ * feature `diagram-files-for-docs`, AC1, AC4, AC5, AC6 and AC8's missing route) and of
4
+ * `draw phase <phase>` (System view · E2, feature `draw-phase-picture`, AC1 and AC5).
4
5
  *
5
- * THE ORDER IS THE SPEC'S. (1) read and check `docs/system.json`; (2) report it and
6
- * get its version — both through `system`'s own first stage,
7
- * `checkAndReportDescription` (`../system-report.ts`), never a copy of it; (3) ask the
8
- * service to draw that version; (4) check all five files, every look's picture and the
9
- * Mermaid, then write them; (5) print the Markdown, whose image line is the embedded
10
- * look's PNG (`EMBED_IMAGE_REL`, `./write.ts`, composed from the same table as that
11
- * file's path). The place and the files already there are checked on the machine
12
- * before anything is sent, and again just before writing, so a refusal this command
13
- * can make locally never costs a request, and a change made while it waited is still
14
- * seen.
6
+ * THE ORDER IS THE SPEC'S. (1) read and check `docs/system.json`; for a phase, read and
7
+ * check its plan in the same stage's `beforeSend`, through `plan`'s own
8
+ * `readAndCheckPlan` (`../plan.ts`), never a copy of it; then the place and the files in
9
+ * the way; (2) report the description and get its version — both through `system`'s
10
+ * own first stage, `checkAndReportDescription` (`../system-report.ts`), never a copy of
11
+ * it; for a phase, then report the plan through `DrawDeps.reportPlan`, `plan`'s own
12
+ * request (`reportPhasePlan`), sending the very plan `beforeSend` checked, never a
13
+ * second read of the file; (3) ask the service to draw that version; (4) check all five
14
+ * files, every look's picture and the Mermaid, then write them; (5) print the
15
+ * Markdown, whose image line is the embedded look's PNG (`embedImageLink`,
16
+ * `./write.ts`, composed from the same table as that file's path). The place and the
17
+ * files already there are checked on the machine before anything is sent, and again
18
+ * just before writing, so a refusal this command can make locally never costs a
19
+ * request, and a change made while it waited is still seen.
20
+ *
21
+ * A PHASE'S FILES. The base name is `phaseDiagramBase(phase)`, `renderPhaseSegment`'s
22
+ * segment. A phase that is not a valid identity is refused naming it, before anything
23
+ * is read; so is one whose base name ends in the Flight Deck word, in any case, whose
24
+ * Broadsheet files would take another phase's Flight Deck names.
15
25
  *
16
26
  * ONE RESPONSE-HANDLING RULE, the Build Record path's. A body that parses under
17
27
  * `systemDrawResultSchema` (`@halfcycle/events`, the one home of the shape) is
@@ -19,33 +29,49 @@
19
29
  * this POST means it predates drawing — asked of `isMissingRoute`
20
30
  * (`../missing-route.ts`), the one predicate, never a copy of its expression; a
21
31
  * missing report route says the same, because either way this service cannot draw.
22
- * Anything else is reported by its status and the service's own sentence.
32
+ * For a phase, the plan route and the draw route's phase arm ship in one service
33
+ * release, so a missing plan route is the one signal that this service cannot draw
34
+ * phase pictures, and the draw route is then never asked. Anything else is reported by
35
+ * its status and the service's own sentence.
23
36
  *
24
37
  * NO BYTE OF THE RESPONSE DECIDES A PATH (INV-023): the response gives contents only;
25
- * where they go is `./write.ts`'s constants.
38
+ * where they go is `./write.ts`'s constants and the base name this module chose from
39
+ * the arguments.
26
40
  *
27
- * WHAT LEAVES THE MACHINE. The checked description (through the shared stage), then
28
- * only `{ version, picture: 'architecture' }`.
41
+ * WHAT LEAVES THE MACHINE. The checked description (through the shared stage); for a
42
+ * phase, the checked plan (through `plan`'s request); then only the draw request,
43
+ * `{ version, picture: 'architecture' }` or `{ picture: 'phase', phase, planVersion }`.
29
44
  *
30
45
  * INV-001: Node builtins, the global `fetch`, `@halfcycle/events` and `@halfcycle/core`
31
46
  * only. SHIPS TO CLIENT DISK inside the CLI: every string here is a sentence a person
32
47
  * reads, so none names an internal register, route or setting; no comment sits beside
33
48
  * an object member.
34
49
  */
35
- import { type SystemDrawDrawn } from '@halfcycle/events';
50
+ import { type SystemDrawDrawn, type SystemDrawRequest } from '@halfcycle/events';
36
51
  import type { RepoCredential } from '../open-phase.js';
52
+ import { type PlanDeps } from '../plan.js';
37
53
  import { type SystemDeps, type SystemRun } from '../system-report.js';
38
- import { type DiagramSet, type DiagramWriteResult } from './write.js';
39
- export { ARCHITECTURE_NAME, DIAGRAM_DIR_REL, DIAGRAM_FILES, DIAGRAM_MARKER_LINE, EMBED_IMAGE_REL, EMBEDDED_LOOK, PICTURE_NAMES, checkPictures, diagramRel, pngOf, svgOf, diagramPaths, writeDiagramSet, } from './write.js';
40
- /** The usage line, printed for any argument but `architecture`. */
41
- export declare const DRAW_USAGE = "npx halfcycle@latest draw architecture [--repo <root>]";
54
+ import { type DiagramBaseName, type DiagramSet, type DiagramWriteResult, type EmbeddingDoc } from './write.js';
55
+ export { ARCHITECTURE_BASE, ARCHITECTURE_NAME, DIAGRAM_DIR_REL, DIAGRAM_FILES, DIAGRAM_MARKER_LINE, EMBEDDED_LOOK, baseTakesFlightDeckNames, checkPictures, diagramRel, embedImageLink, embedImageName, markdownLinkName, phaseDiagramBase, pictureNames, pngOf, svgOf, diagramPaths, writeDiagramSet, type DiagramBaseName, } from './write.js';
56
+ /** The usage line, printed for anything but `architecture` or `phase <phase>`. */
57
+ export declare const DRAW_USAGE = "npx halfcycle@latest draw (architecture | phase <phase>) [--repo <root>]";
58
+ /** Which picture: the whole system's, or one phase's plan on it. */
59
+ export type DrawPicture = {
60
+ kind: 'architecture';
61
+ } | {
62
+ kind: 'phase';
63
+ phase: string;
64
+ };
42
65
  /**
43
- * What the arguments after `draw` came to: the repository root to work in, or usage.
44
- * Exactly one positional, `architecture`, and at most one `--repo <root>`; anything
45
- * else, including no argument, is usage. A phase name never reaches here in E1.
66
+ * What the arguments after `draw` came to: the picture and the repository root to work
67
+ * in, or usage. `architecture` alone, or `phase` followed by exactly one phase, plus at
68
+ * most one `--repo <root>`; anything else, including no argument and `phase` with no
69
+ * name, is usage. The phase is not checked here: a name that cannot be a phase is the
70
+ * verb's to refuse, by name.
46
71
  */
47
72
  export type DrawArgs = {
48
73
  ok: true;
74
+ picture: DrawPicture;
49
75
  repoRoot: string | undefined;
50
76
  } | {
51
77
  ok: false;
@@ -72,20 +98,38 @@ export type DrawOutcome = {
72
98
  /** The address the drawing is asked of: the engagement is one path segment, encoded once. */
73
99
  export declare function systemDrawUrl(credential: RepoCredential): string;
74
100
  /**
75
- * Ask the service to draw `version`. Never throws: the network, the service and an
76
- * answer this CLI cannot read are each an outcome the caller prints.
101
+ * Ask the service to draw the picture `request` names. Never throws: the network, the
102
+ * service and an answer this CLI cannot read are each an outcome the caller prints.
103
+ */
104
+ export declare function requestDrawing(credential: RepoCredential, request: SystemDrawRequest): Promise<DrawOutcome>;
105
+ /**
106
+ * The pieces `runDraw` reaches outside itself through; replaced in tests. `reportPlan`
107
+ * is `plan`'s own request, used only for a phase.
77
108
  */
78
- export declare function requestDrawing(credential: RepoCredential, version: number): Promise<DrawOutcome>;
79
- /** The pieces `runDraw` reaches outside itself through; replaced in tests. */
80
109
  export interface DrawDeps extends SystemDeps {
81
- readonly draw: (credential: RepoCredential, version: number) => Promise<DrawOutcome>;
82
- readonly write: (repoRoot: string, set: DiagramSet) => DiagramWriteResult;
110
+ readonly reportPlan: PlanDeps['reportPlan'];
111
+ readonly draw: (credential: RepoCredential, request: SystemDrawRequest) => Promise<DrawOutcome>;
112
+ readonly write: (repoRoot: string, base: DiagramBaseName, set: DiagramSet) => DiagramWriteResult;
83
113
  }
84
- /** The Markdown to paste into a document directly under `docs/`, and the line before it. */
85
- export declare function pasteLines(mermaid: string): string;
114
+ /**
115
+ * What a picture is pasted as: the document it goes in, and the image's alt text.
116
+ * The architecture's goes directly under `docs/`; a phase's in its own document in
117
+ * `docs/phases/`.
118
+ */
119
+ export type PasteTarget = {
120
+ doc: EmbeddingDoc;
121
+ alt: string;
122
+ base: DiagramBaseName;
123
+ };
124
+ /** The architecture's paste target. */
125
+ export declare const ARCHITECTURE_PASTE: PasteTarget;
126
+ /** A phase's paste target: `Phase <name>`, in `docs/phases/`. */
127
+ export declare function phasePaste(phase: string): PasteTarget;
128
+ /** The Markdown to paste into the document `target` names, and the line before it. */
129
+ export declare function pasteLines(mermaid: string, target: PasteTarget): string;
86
130
  /**
87
131
  * The whole verb, in the order the module header gives. Exit 0 only when the five
88
132
  * files are written or already up to date and the Markdown is printed.
89
133
  */
90
- export declare function runDraw(repoRoot: string, deps: DrawDeps): Promise<SystemRun>;
134
+ export declare function runDraw(repoRoot: string, picture: DrawPicture, deps: DrawDeps): Promise<SystemRun>;
91
135
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/draw/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAkD,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,aAAa,EACb,aAAa,EACb,UAAU,EACV,KAAK,EACL,KAAK,EACL,YAAY,EACZ,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,mEAAmE;AACnE,eAAO,MAAM,UAAU,2DAA2D,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAElF,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CAiB/D;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,UAAU,EAAE,cAAc,GAAG,MAAM,CAEhE;AAUD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmDtG;AAED,8EAA8E;AAC9E,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACrF,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,KAAK,kBAAkB,CAAC;CAC3E;AAMD,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASlD;AAYD;;;GAGG;AACH,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAiElF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/draw/index.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,30 @@
1
1
  /**
2
- * The architecture pictures writer — what `draw architecture` writes into the person's
3
- * repository (System view · E1, feature `diagram-files-for-docs`, AC4, AC5, AC6 and
4
- * the "someone else's file in the way" behaviour).
2
+ * The pictures writer — what `draw architecture` and `draw phase` write into the
3
+ * person's repository (System view · E1, feature `diagram-files-for-docs`, AC4, AC5,
4
+ * AC6 and the "someone else's file in the way" behaviour; widened to a base name by
5
+ * E2, feature `draw-phase-picture` AC5).
5
6
  *
6
7
  * NO BYTE OF THE RESPONSE DECIDES A PATH (INV-023). Every path here is composed from
7
8
  * `repoRoot` (the caller's `--repo` or the working directory), the constant directory
8
- * `docs/diagrams` and the constant name `architecture` with a constant extension. The
9
+ * `docs/diagrams` and a BASE NAME with a constant extension. A base name is a
10
+ * `DiagramBaseName`, and only two things make one: `ARCHITECTURE_BASE` (the constant
11
+ * `architecture`) and `phaseDiagramBase(phase)` (`renderPhaseSegment`'s segment, the
12
+ * one home of a phase's file segment). The type is branded, so a string from anywhere
13
+ * else, a response included, does not compile where a base name is asked for. The
9
14
  * response contributes file CONTENTS only; nothing in it is ever joined, resolved or
10
- * compared as a path. `DiagramPaths` is built by `diagramPaths(repoRoot)` alone.
15
+ * compared as a path. `DiagramPaths` is built by `diagramPaths(repoRoot, base)` alone.
16
+ *
17
+ * Every rule below is stated for the architecture's names, which are the base name
18
+ * `architecture`; a phase's are the same with its base name in their place.
11
19
  *
12
20
  * FIVE FILES, ONE TABLE. Each look in `SYSTEM_PICTURE_THEMES` (`@halfcycle/events`, the
13
21
  * one list of looks) has a PNG and an SVG; the Mermaid is one file, because Mermaid has
14
- * no look. A look selects its file name from `PICTURE_NAMES`, a constant typed against
22
+ * no look. A look selects its file name from `pictureNames(base)`, a table typed against
15
23
  * `SystemPictureTheme`, so a look the list does not hold has no name and the compiler
16
24
  * refuses a look the table forgets. The looks are iterated from the list, never from
17
25
  * the response's keys: the strict result schema already refused any other key, and
18
26
  * this module would not read one if it came. Which look documents embed is
19
- * `EMBEDDED_LOOK`, and only there: the printed image line (`EMBED_IMAGE_REL`) is
27
+ * `EMBEDDED_LOOK`, and only there: the printed image line (`embedImageLink`) is
20
28
  * composed from the same file-name table as that look's path, so the line and the file
21
29
  * cannot name different pictures.
22
30
  *
@@ -79,18 +87,42 @@
79
87
  * DISK inside the CLI: every string here is a sentence a person reads, and no comment
80
88
  * sits beside an object member.
81
89
  */
82
- import { type SystemDrawDrawn, type SystemPictureTheme } from '@halfcycle/events';
90
+ import { type PhaseIdentity, type SystemDrawDrawn, type SystemPictureTheme } from '@halfcycle/events';
83
91
  import { type RecordPairIo } from '../build-record/write.js';
84
92
  /** The one directory the pictures go in, relative to the repository root, `/`-separated. */
85
93
  export declare const DIAGRAM_DIR_REL = "docs/diagrams";
86
- /** The one picture name E1 draws; also the Mermaid file's name. */
94
+ /** The architecture picture's name; also its Mermaid file's name. */
87
95
  export declare const ARCHITECTURE_NAME = "architecture";
96
+ declare const diagramBaseBrand: unique symbol;
97
+ /**
98
+ * The name a set of five files is built from. Branded so only the two makers below
99
+ * produce one: a plain string, a response's included, is a compile error where a base
100
+ * name is asked for (INV-023).
101
+ */
102
+ export type DiagramBaseName = string & {
103
+ readonly [diagramBaseBrand]: true;
104
+ };
105
+ /** The architecture's base name. */
106
+ export declare const ARCHITECTURE_BASE: DiagramBaseName;
107
+ /**
108
+ * A phase's base name: `renderPhaseSegment(phase)`, so `notifications` gives
109
+ * `phase-notifications`. Throws on an invalid identity, as that function does; the
110
+ * verb checks the identity first and reports it rather than throwing.
111
+ */
112
+ export declare function phaseDiagramBase(phase: PhaseIdentity): DiagramBaseName;
113
+ /**
114
+ * Would this base name's Broadsheet files take another set's Flight Deck names?
115
+ * `phase-a.flightdeck.png` is phase `a`'s Flight Deck picture, so a base name ending in
116
+ * the Flight Deck word, in any case (a case-insensitive file system would collide
117
+ * too), is refused before anything is sent.
118
+ */
119
+ export declare function baseTakesFlightDeckNames(base: DiagramBaseName): boolean;
88
120
  /**
89
- * Each look's file name, before its extension: Broadsheet takes the bare name, Flight
90
- * Deck the name with its look after it. Typed against the one list of looks, so the
91
- * table cannot hold a look the list does not, or miss one it does.
121
+ * Each look's file name, before its extension: Broadsheet takes the bare base name,
122
+ * Flight Deck the base name with its look after it. Typed against the one list of
123
+ * looks, so the table cannot hold a look the list does not, or miss one it does.
92
124
  */
93
- export declare const PICTURE_NAMES: Readonly<Record<SystemPictureTheme, string>>;
125
+ export declare function pictureNames(base: DiagramBaseName): Readonly<Record<SystemPictureTheme, string>>;
94
126
  /**
95
127
  * The look documents embed, and the only place that choice is made. Its PNG is the
96
128
  * printed image line, and its SVG is the one the Mermaid file sits beside.
@@ -116,19 +148,36 @@ export declare function pngOf(look: SystemPictureTheme): PictureFile;
116
148
  */
117
149
  export declare const DIAGRAM_FILES: readonly DiagramFile[];
118
150
  /**
119
- * The embedded picture as a document directly under `docs/` names it:
120
- * `diagrams/architecture.png`. Composed from the same table as that file's path.
151
+ * The embedded picture's file name in `docs/diagrams`: `architecture.png`. Composed
152
+ * from the same table as that file's path, so the printed image line and the file
153
+ * cannot name different pictures.
154
+ */
155
+ export declare function embedImageName(base: DiagramBaseName): string;
156
+ /**
157
+ * Where the document the picture is pasted into sits: directly under `docs/` (the
158
+ * architecture's), or in `docs/phases/` (a phase's).
159
+ */
160
+ export type EmbeddingDoc = 'docs' | 'docs/phases';
161
+ /**
162
+ * A file name as a Markdown link target: percent-encoded (`encodeURIComponent`), and
163
+ * `(` and `)` too, which would otherwise end the link.
164
+ */
165
+ export declare function markdownLinkName(name: string): string;
166
+ /**
167
+ * The embedded picture as a document at `doc` links it: `diagrams/architecture.png`
168
+ * from `docs/`, `../diagrams/phase-notifications.png` from `docs/phases/`. The file
169
+ * name is the one `embedImageName` gives, encoded for a link.
121
170
  */
122
- export declare const EMBED_IMAGE_REL: string;
171
+ export declare function embedImageLink(base: DiagramBaseName, doc: EmbeddingDoc): string;
123
172
  /** The fixed paths, composed from `repoRoot` and constants only. */
124
173
  export interface DiagramPaths {
125
174
  readonly repoRoot: string;
126
175
  readonly dir: string;
127
176
  readonly file: Readonly<Record<DiagramFile, string>>;
128
177
  }
129
- export declare function diagramPaths(repoRoot: string): DiagramPaths;
178
+ export declare function diagramPaths(repoRoot: string, base: DiagramBaseName): DiagramPaths;
130
179
  /** A file's place as a person finds it: `docs/diagrams/architecture.svg`. */
131
- export declare function diagramRel(which: DiagramFile): string;
180
+ export declare function diagramRel(base: DiagramBaseName, which: DiagramFile): string;
132
181
  /**
133
182
  * The five files in the order a person reads them: each look's PNG then its SVG, then
134
183
  * the Mermaid file.
@@ -178,7 +227,7 @@ export type ExistingRead = {
178
227
  */
179
228
  export declare function readExistingSet(paths: DiagramPaths): ExistingRead;
180
229
  /** The sentence for a file in the way, or for the temporary file beside it when `temp`. */
181
- export declare function inTheWayLine(which: DiagramFile, temp?: boolean): string;
230
+ export declare function inTheWayLine(base: DiagramBaseName, which: DiagramFile, temp?: boolean): string;
182
231
  /** The five files as bytes, checked and ready to write. */
183
232
  export type DiagramSet = Readonly<Record<DiagramFile, Uint8Array>>;
184
233
  /** What checking the drawn pictures came to: the bytes, or what was wrong, in plain words. */
@@ -198,7 +247,7 @@ export type PictureCheck = {
198
247
  * Each sentence names the file the bad bytes were for, so a person reading it knows
199
248
  * which picture was wrong.
200
249
  */
201
- export declare function checkPictures(drawn: SystemDrawDrawn): PictureCheck;
250
+ export declare function checkPictures(drawn: SystemDrawDrawn, base: DiagramBaseName): PictureCheck;
202
251
  /**
203
252
  * What writing came to. `up-to-date`: every file already held these bytes and none
204
253
  * was touched. `written`: the files in `changed` were replaced or created.
@@ -228,5 +277,6 @@ export type DiagramWriteResult = {
228
277
  * header states. Never throws for a file-system failure: it is a `failed` result,
229
278
  * and the set on disk is the old one.
230
279
  */
231
- export declare function writeDiagramSet(repoRoot: string, set: DiagramSet, io?: RecordPairIo): DiagramWriteResult;
280
+ export declare function writeDiagramSet(repoRoot: string, base: DiagramBaseName, set: DiagramSet, io?: RecordPairIo): DiagramWriteResult;
281
+ export {};
232
282
  //# sourceMappingURL=write.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/draw/write.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/draw/write.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -118,6 +118,7 @@ var VENDORED_BIN_REL = ".halfcycle/bin/bin.bundle.mjs";
118
118
  var SESSION_START_MARKER_REL = ".claude/hooks/session-start-marker.sh";
119
119
  var GUARD_RUNNER_REL = ".claude/hooks/guard-runner.sh";
120
120
  var USER_PROMPT_REMINDER_REL = ".claude/hooks/user-prompt-reminder.sh";
121
+ var USER_PROMPT_SCOPE_REL = ".claude/hooks/user-prompt-scope.sh";
121
122
  var SESSION_END_MARKER_REL = ".claude/hooks/session-end-marker.sh";
122
123
  var WRITE_CAPABLE_TOOLS = ["Edit", "MultiEdit", "NotebookEdit", "Write"];
123
124
  function hookCommand(script, verb) {
@@ -146,6 +147,13 @@ var HALFCYCLE_HOOK_WIRING = [
146
147
  command: hookCommand(USER_PROMPT_REMINDER_REL),
147
148
  script: USER_PROMPT_REMINDER_REL
148
149
  },
150
+ {
151
+ event: "UserPromptSubmit",
152
+ matcher: null,
153
+ timeout: 10,
154
+ command: hookCommand(USER_PROMPT_SCOPE_REL),
155
+ script: USER_PROMPT_SCOPE_REL
156
+ },
149
157
  {
150
158
  event: "PostToolUse",
151
159
  matcher: WRITE_CAPABLE_TOOLS.join("|"),
@@ -227,6 +235,9 @@ function quoteForShell(value) {
227
235
  }
228
236
  var HALFCYCLE_COMMAND = "npx halfcycle@latest";
229
237
 
238
+ // ../core/dist/release-version.js
239
+ var RELEASE_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
240
+
230
241
  // ../events/dist/result.js
231
242
  import { z as z2 } from "zod";
232
243
  var firedGuardSchema = z2.object({
@@ -293,15 +304,12 @@ function hasLoneSurrogate(text) {
293
304
  }
294
305
  var LONE_SURROGATE_MESSAGE = "must be valid text: it holds half of a character pair with no other half";
295
306
 
296
- // ../events/dist/build-record.js
297
- import { z as z4 } from "zod";
298
-
299
307
  // ../events/dist/state.js
300
308
  import { z as z3 } from "zod";
301
309
  var utcIso8601 = z3.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/, "must be a UTC ISO-8601 timestamp ending in Z");
302
310
  var STATE_RECORD_FORMAT = "halfcycle-state-record/v1";
303
311
  var stepIdSchema = z3.string().regex(/^(l[0-5](-l[0-5])?|xl)\.[a-z0-9-]+$/);
304
- var methodVersionSchema = z3.string().regex(/^\d+\.\d+\.\d+$/);
312
+ var methodVersionSchema = z3.string().regex(RELEASE_VERSION_PATTERN);
305
313
  var anchorPathRegex = /^(?!\/)(?!.*#)(?!method\/)(?!(.*\/)?docs\/method\/).+$/;
306
314
  var recordKindSchema = z3.enum(["artefact", "step-run", "gate", "intervention"]);
307
315
  var methodLayerSchema = z3.enum(["l0", "l1", "l2", "l3", "l3-l4", "l4", "l5", "xl"]);
@@ -478,6 +486,9 @@ var stateRecordSchema = z3.discriminatedUnion("recordKind", [
478
486
  interventionRecordSchema
479
487
  ]);
480
488
 
489
+ // ../events/dist/build-record.js
490
+ import { z as z4 } from "zod";
491
+
481
492
  // ../events/dist/control-characters.js
482
493
  var CONTROL_CHARACTER_CLASS = "\\p{Cc}";
483
494
  var CONTROL_CHARACTER = new RegExp(CONTROL_CHARACTER_CLASS, "u");
@@ -581,9 +592,11 @@ function statementText(max) {
581
592
  });
582
593
  }
583
594
  var closeActorSchema = plainText(ACTOR_MAX);
595
+ var PHASE_NAME_RULE = `must be a phase name: not empty, no slash or backslash, not starting with a dot, no control characters, at most ${PHASE_NAME_MAX_BYTES} bytes`;
584
596
  var phaseNameSchema = z4.string().refine((v) => isValidPhaseIdentity(v), {
585
- message: `must be a phase name: not empty, no slash or backslash, not starting with a dot, no control characters, at most ${PHASE_NAME_MAX_BYTES} bytes`
597
+ message: PHASE_NAME_RULE
586
598
  });
599
+ var phaseIdentitySchema = z4.union([z4.string(), z4.number()], { error: "must be a phase name or a whole number" }).refine((v) => isValidPhaseIdentity(v), { message: PHASE_NAME_RULE });
587
600
  var closeStatementsSchema = z4.object({
588
601
  thesis: statementText(STATEMENT_MAX).nullable(),
589
602
  outcome: statementText(STATEMENT_MAX).nullable(),
@@ -1014,6 +1027,11 @@ var deviceConfirmResponseSchema = z6.union([
1014
1027
  ]);
1015
1028
  var DASHBOARD_URL = "https://app.halfcycle.ai";
1016
1029
 
1030
+ // ../events/dist/project-page.js
1031
+ function projectPageUrl(engagementId) {
1032
+ return isEngagementId(engagementId) ? `${DASHBOARD_URL}/${encodeURIComponent(engagementId)}` : void 0;
1033
+ }
1034
+
1017
1035
  // ../events/dist/credential-wire.js
1018
1036
  import { z as z7 } from "zod";
1019
1037
  var engagementCredentialResponseSchema = z7.object({
@@ -1652,11 +1670,6 @@ function nodeFloorProgram(guarded) {
1652
1670
  return `if(+process.versions.node.split('.')[0]<${NODE_FLOOR_MAJOR}){console.error('${NODE_FLOOR_SENTENCE_HEAD}'+process.versions.node);process.exitCode=1}else{${guarded}}`;
1653
1671
  }
1654
1672
 
1655
- // dist/project-page.js
1656
- function projectPageUrl(engagementId) {
1657
- return isEngagementId(engagementId) ? `${DASHBOARD_URL}/${encodeURIComponent(engagementId)}` : void 0;
1658
- }
1659
-
1660
1673
  // dist/merge-settings.js
1661
1674
  function isHalfcycleCommand(hook, halfcycleCommands) {
1662
1675
  if (typeof hook !== "object" || hook === null)
@@ -2383,6 +2396,54 @@ printf '%s\\n' '${USER_PROMPT_REMINDER_SENTENCE}'
2383
2396
  exit 0
2384
2397
  `;
2385
2398
  }
2399
+ var GENERATED_USER_PROMPT_SCOPE_HEADER = "# Typed scope approval \u2014 generated by";
2400
+ function generateUserPromptScopeHook() {
2401
+ return `#!/usr/bin/env bash
2402
+ ${GENERATED_USER_PROMPT_SCOPE_HEADER} the Halfcycle installer.
2403
+ #
2404
+ # Lets the owner of this project approve a phase's scope, or send it back, by
2405
+ # typing "approve <phase>" or "send back <phase>: <note>" as the whole prompt in
2406
+ # their own Claude Code session.
2407
+ #
2408
+ # AN ORDINARY PROMPT STARTS NOTHING. This script reads the hook input once and
2409
+ # looks only at the start of the prompt's value. Unless the prompt begins, after
2410
+ # any whitespace (typed, or escaped in the input), with "approve " or
2411
+ # "send back " in any case, it exits 0 with no output, and Node never starts.
2412
+ # A quote inside any other field arrives escaped, so no other field (the folder
2413
+ # the session is in, for one) can read as the start of the prompt.
2414
+ #
2415
+ # Otherwise it finds the project root from its own location, never from the
2416
+ # folder the session has moved to, and hands the same input to the guard
2417
+ # wrapper beside it. That decides whether the line counts and prints at most
2418
+ # one plain line. Nothing here ever blocks a prompt.
2419
+ #
2420
+ # FAILS OPEN up to that hand-over: any error before it exits 0 with no output.
2421
+ # After it, the wrapper's own exit stands.
2422
+ trap 'exit 0' ERR
2423
+ set -e
2424
+
2425
+ # Read with the shell's own builtin, so the check below is the only program an
2426
+ # ordinary prompt starts.
2427
+ HC_INPUT=""
2428
+ IFS= read -r -d '' HC_INPUT || true
2429
+
2430
+ # What may come before the phrase: whitespace as typed, as a short escape, as a
2431
+ # \\u escape, or as the UTF-8 bytes of a Unicode space. Compared byte for byte.
2432
+ HC_LEAD='[[:space:]]|\\\\[nrtf]|\\\\u(000[9a-d]|0020|00a0|1680|200[0-9a]|202[89f]|205f|3000|feff)'
2433
+ HC_LEAD="$HC_LEAD|"$'\\xc2\\xa0|\\xe1\\x9a\\x80|\\xe2\\x80[\\x80-\\x8a\\xa8\\xa9\\xaf]|\\xe2\\x81\\x9f|\\xe3\\x80\\x80|\\xef\\xbb\\xbf'
2434
+ if ! printf '%s' "$HC_INPUT" | LC_ALL=C grep -Eiq "\\"prompt\\"[[:space:]]*:[[:space:]]*\\"($HC_LEAD)*(approve|send back) "; then
2435
+ exit 0
2436
+ fi
2437
+
2438
+ HC_SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
2439
+ HC_PROJECT_ROOT=$(CDPATH= cd -- "$HC_SCRIPT_DIR/../.." && pwd)
2440
+ export CLAUDE_PROJECT_DIR="$HC_PROJECT_ROOT"
2441
+
2442
+ trap - ERR
2443
+ set +e
2444
+ exec bash "$HC_PROJECT_ROOT/.claude/hooks/guard-runner.sh" hook user-prompt-submit <<<"$HC_INPUT"
2445
+ `;
2446
+ }
2386
2447
  var CI_STANZA_KNOWN_HEADER_HASHES = [
2387
2448
  "b225800b2d699811f32ac213238cbf81c35b5e6a74114bdf55e39cd9d7e2928f",
2388
2449
  "674181735460f051af7c157222cf851fc3000fb3b8af3a10ea0bde9fe5eaba1f",
@@ -2458,6 +2519,7 @@ function removeRetiredMcpHeadersHelper(targetRepo) {
2458
2519
  var OWNED_GENERATED_HEADERS = {
2459
2520
  ".claude/hooks/guard-runner.sh": GENERATED_GUARD_RUNNER_HEADER,
2460
2521
  ".claude/hooks/user-prompt-reminder.sh": GENERATED_USER_PROMPT_REMINDER_HEADER,
2522
+ ".claude/hooks/user-prompt-scope.sh": GENERATED_USER_PROMPT_SCOPE_HEADER,
2461
2523
  ".claude/hooks/session-end-marker.sh": GENERATED_SESSION_END_HEADER,
2462
2524
  ".claude/hooks/session-start-marker.sh": GENERATED_SESSION_START_HEADER
2463
2525
  };
@@ -2466,6 +2528,7 @@ function hookScriptsThisVersionWrites() {
2466
2528
  [".claude/hooks/guard-runner.sh", generateGuardRunnerWrapper()],
2467
2529
  [".claude/hooks/session-end-marker.sh", generateSessionEndMarker()],
2468
2530
  [".claude/hooks/user-prompt-reminder.sh", generateUserPromptReminderHook()],
2531
+ [".claude/hooks/user-prompt-scope.sh", generateUserPromptScopeHook()],
2469
2532
  [".claude/hooks/session-start-marker.sh", generateSessionStartMarker()]
2470
2533
  ];
2471
2534
  }
@@ -3859,7 +3922,7 @@ function renderBuildRecordV2Markdown(record2) {
3859
3922
  `Phase: ${phase} (the name the client gave it)`,
3860
3923
  OBSERVED_LABEL,
3861
3924
  [
3862
- `- Method version: ${p.text(record2.observed.methodVersion)}. The Halfcycle method is updated from time to time, and each update has its own version number. This is the one the project was run under; it does not change during a project.`,
3925
+ `- Method version: ${p.text(record2.observed.methodVersion)}. The Halfcycle method is updated from time to time, and each update has its own version number. This is the one the phase was run under. A project moves to a newer version only between phases.`,
3863
3926
  `- Project identifier: ${p.text(record2.observed.engagementId)}. Halfcycle keeps this project's records under this identifier.`,
3864
3927
  `- Record format: ${p.text(record2.format)}. This names the layout this file and the .json file beside it follow, for software that reads them.`
3865
3928
  ].join("\n"),