halfcycle 0.4.5 → 0.4.6

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,168 @@
1
+ /**
2
+ * The client half of `npx halfcycle@latest system` (System view · E1, feature
3
+ * `system-description`): read the project's `docs/system.json`, check it with the one
4
+ * shared check, warn about owned patterns that match no tracked file, and report it
5
+ * to the Halfcycle service, which answers with the version it holds.
6
+ *
7
+ * ONE HOME FOR EVERY RULE THIS VERB APPLIES (INV-003). The shape, the cross-field
8
+ * rules and the ownership grammar are `@halfcycle/events`' `checkSystemDescription`
9
+ * and `ownerOf` — this module calls them and restates none of them. The unowned-
10
+ * pattern warning asks `ownerOf` of a one-part, one-pattern description per pattern
11
+ * rather than matching paths itself, so "does this pattern own this file" has exactly
12
+ * one implementation, the one E3's counting uses. The answer's shape is the events
13
+ * package's `systemReportResultSchema`. "Is this a service without the route" is
14
+ * `isMissingRoute` (`./missing-route.ts`), shared with `build-record` and `draw`.
15
+ * `draw` takes this module's first stage, `checkAndReportDescription`, whole: the
16
+ * two verbs read, check and report the description by one path, not two copies.
17
+ *
18
+ * ONE RESPONSE-HANDLING RULE, the Build Record path's. A body that parses under
19
+ * `systemReportResultSchema` is authoritative, whatever its status. Otherwise the
20
+ * service's missing-route answer to a POST means it predates the route; anything
21
+ * else is reported by its status and the service's own sentence.
22
+ *
23
+ * WHAT LEAVES THE MACHINE. Only the description, and only after it passed the check.
24
+ * The tracked-file list read for the warning is a local read: nothing it finds is
25
+ * sent, and it sets nothing (INV-021). Nothing here writes into the person's tree.
26
+ *
27
+ * INV-001: Node builtins, the global `fetch`, `@halfcycle/events` and
28
+ * `@halfcycle/core` (through the shared credential and command helpers) only.
29
+ * SHIPS TO CLIENT DISK inside the CLI: every string here is a sentence a person
30
+ * reads, so none names an internal register, route or setting; no comment sits
31
+ * beside an object member.
32
+ */
33
+ import { type SystemDescription, type SystemDescriptionProblem } from '@halfcycle/events';
34
+ import type { RepoCredential } from './open-phase.js';
35
+ /** Where the description lives, relative to the repository root. */
36
+ export declare const SYSTEM_DESCRIPTION_REL = "docs/system.json";
37
+ /**
38
+ * What reading `docs/system.json` came to. `missing`: there is no such file.
39
+ * `unreadable`: something is there and could not be read as a file. `not-json`: it
40
+ * was read and does not parse; `error` is the parser's own sentence. `read`: the
41
+ * parsed value, not yet checked.
42
+ */
43
+ export type DescriptionFile = {
44
+ kind: 'missing';
45
+ } | {
46
+ kind: 'unreadable';
47
+ } | {
48
+ kind: 'not-json';
49
+ error: string;
50
+ } | {
51
+ kind: 'read';
52
+ value: unknown;
53
+ };
54
+ /**
55
+ * Read and parse the description under `repoRoot`. Never throws. A missing file is
56
+ * told apart from an unreadable one because the remedies differ: the first is
57
+ * written by the method's architecture step, the second is the person's to fix.
58
+ */
59
+ export declare function readDescriptionFile(repoRoot: string): DescriptionFile;
60
+ /**
61
+ * A problem's place in words a person can find in their file: the dotted path the
62
+ * check reports (`parts.3.name`), then the part or connection it is in, named by its
63
+ * id or its ends when the raw value carries them, by its position otherwise.
64
+ */
65
+ export declare function problemPlace(raw: unknown, path: string): string;
66
+ /** One line per problem, each naming where it is, for the terminal. */
67
+ export declare function problemLines(raw: unknown, problems: readonly SystemDescriptionProblem[]): string;
68
+ /** An owned pattern that matches no file git tracks, and the part that lists it. */
69
+ export interface UnownedPattern {
70
+ readonly partId: string;
71
+ readonly pattern: string;
72
+ }
73
+ /** How the tracked-file list is obtained; replaced in tests. `null` when there is none. */
74
+ export type ListTrackedFiles = (repoRoot: string) => string[] | null;
75
+ /**
76
+ * The files git tracks under `repoRoot`, as `git ls-files -z` prints them (relative,
77
+ * `/`-separated, unquoted), or `null` when there is no git, `repoRoot` is not inside
78
+ * a repository, or the list could not be read. The repository-locating variables are
79
+ * removed from git's environment so the folder named is the one read.
80
+ */
81
+ export declare const listTrackedFiles: ListTrackedFiles;
82
+ /**
83
+ * The owned patterns that match no tracked file — how a description drifts from the
84
+ * code. A warning, never a refusal. `null` when the tracked-file list is unavailable:
85
+ * the warning is then skipped, not guessed.
86
+ *
87
+ * Each pattern is asked of `ownerOf` on its own (a description holding just that part
88
+ * with just that pattern), so a pattern another part outranks on every file still
89
+ * counts as matching: the warning is about patterns that name nothing, not about
90
+ * ranking.
91
+ */
92
+ export declare function unownedPatterns(description: SystemDescription, tracked: readonly string[] | null): UnownedPattern[] | null;
93
+ /** The warning lines for unowned patterns, one per pattern. */
94
+ export declare function unownedPatternLines(unowned: readonly UnownedPattern[]): string;
95
+ /**
96
+ * What came of reporting the description. `recorded`: the service holds it as
97
+ * `version` (a description it already had returns that version). `refused`: the
98
+ * service's own problems. `no-route`: this service cannot take a description yet.
99
+ * `unavailable`: it could not be reported, and `why` says so.
100
+ */
101
+ export type ReportOutcome = {
102
+ kind: 'recorded';
103
+ version: number;
104
+ reportedAt: string;
105
+ } | {
106
+ kind: 'refused';
107
+ problems: SystemDescriptionProblem[];
108
+ } | {
109
+ kind: 'no-route';
110
+ } | {
111
+ kind: 'unavailable';
112
+ why: string;
113
+ };
114
+ /** The address the description is reported to: the engagement is one path segment, encoded once. */
115
+ export declare function systemReportUrl(credential: RepoCredential): string;
116
+ /**
117
+ * Report a checked description. Never throws: the network, the service and an answer
118
+ * this CLI cannot read are each an outcome the caller prints.
119
+ */
120
+ export declare function reportSystemDescription(credential: RepoCredential, description: SystemDescription): Promise<ReportOutcome>;
121
+ /** What `system` prints and the exit code it ends with. */
122
+ export interface SystemRun {
123
+ readonly stdout: string;
124
+ readonly stderr: string;
125
+ readonly exitCode: 0 | 1;
126
+ }
127
+ /** The pieces `runSystem` reaches outside itself through; replaced in tests. */
128
+ export interface SystemDeps {
129
+ readonly readCredential: (repoRoot: string) => RepoCredential;
130
+ readonly listTracked: ListTrackedFiles;
131
+ readonly report: (credential: RepoCredential, description: SystemDescription) => Promise<ReportOutcome>;
132
+ }
133
+ /**
134
+ * What the shared first stage came to. `stopped`: the verb ends here and `stderr` is
135
+ * the whole of what it prints. `no-route`: the service cannot take a description yet;
136
+ * the caller words that for its own verb. `recorded`: the service holds the checked
137
+ * description as `version`, and `credential` is the one it was reported with.
138
+ * `warnings` is the unowned-pattern lines, printed whatever the caller does next.
139
+ */
140
+ export type DescriptionStage = {
141
+ kind: 'stopped';
142
+ stderr: string;
143
+ } | {
144
+ kind: 'no-route';
145
+ warnings: string;
146
+ } | {
147
+ kind: 'recorded';
148
+ version: number;
149
+ credential: RepoCredential;
150
+ warnings: string;
151
+ };
152
+ /** The verbs that report the description first. Names the prefix of every line. */
153
+ export type DescriptionVerb = 'system' | 'draw';
154
+ /**
155
+ * READ, CHECK, WARN, REPORT — the one path both `system` and `draw` take before
156
+ * anything else (feature `diagram-files-for-docs`, step 1 and 2 of the command). The
157
+ * order is the spec's: nothing is sent unless the file reads, parses and passes every
158
+ * rule, and the credential is only looked for once there is something to send.
159
+ *
160
+ * `beforeSend` is the caller's own local refusal, asked after the description passed
161
+ * and before the credential is read or anything sent: `draw` refuses there when a file
162
+ * it does not own is in the way, so a refusal it can make on the machine never costs a
163
+ * request. It returns the line to print, or `null` to go on.
164
+ */
165
+ export declare function checkAndReportDescription(repoRoot: string, deps: SystemDeps, verb: DescriptionVerb, beforeSend?: () => string | null): Promise<DescriptionStage>;
166
+ /** The whole `system` verb: the shared stage, then its version printed. */
167
+ export declare function runSystem(repoRoot: string, deps: SystemDeps): Promise<SystemRun>;
168
+ //# sourceMappingURL=system-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-report.d.ts","sourceRoot":"","sources":["../src/system-report.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "halfcycle",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
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",