halfcycle 0.3.7
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 +16 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/bin/bin.bundle.mjs +16771 -0
- package/commands/agent-teams-orchestration.md +11 -0
- package/commands/consistency-check.md +11 -0
- package/commands/context-update.md +11 -0
- package/commands/halfcycle-design.md +11 -0
- package/commands/halfcycle-setup.md +11 -0
- package/commands/stack-assembly-worker.md +11 -0
- package/commands/task-execution.md +11 -0
- package/commands/task-graph.md +11 -0
- package/commands/write-spec.md +11 -0
- package/dist/account-credential.d.ts +94 -0
- package/dist/account-credential.d.ts.map +1 -0
- package/dist/bin.d.ts +34 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +3156 -0
- package/dist/bin.js.map +6 -0
- package/dist/build-record/assemble.d.ts +37 -0
- package/dist/build-record/assemble.d.ts.map +1 -0
- package/dist/build-record/index.d.ts +39 -0
- package/dist/build-record/index.d.ts.map +1 -0
- package/dist/build-record/sources.d.ts +80 -0
- package/dist/build-record/sources.d.ts.map +1 -0
- package/dist/build-record/template.d.ts +18 -0
- package/dist/build-record/template.d.ts.map +1 -0
- package/dist/build-record/types.d.ts +163 -0
- package/dist/build-record/types.d.ts.map +1 -0
- package/dist/build-record/write.d.ts +26 -0
- package/dist/build-record/write.d.ts.map +1 -0
- package/dist/cli-contract.d.ts +120 -0
- package/dist/cli-contract.d.ts.map +1 -0
- package/dist/close-phase.d.ts +114 -0
- package/dist/close-phase.d.ts.map +1 -0
- package/dist/create-engagement.d.ts +248 -0
- package/dist/create-engagement.d.ts.map +1 -0
- package/dist/device-signin.d.ts +255 -0
- package/dist/device-signin.d.ts.map +1 -0
- package/dist/engagement-credential.d.ts +267 -0
- package/dist/engagement-credential.d.ts.map +1 -0
- package/dist/identity.d.ts +76 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2083 -0
- package/dist/index.js.map +6 -0
- package/dist/install.d.ts +355 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/loopback-signin.d.ts +173 -0
- package/dist/loopback-signin.d.ts.map +1 -0
- package/dist/mcp-endpoint.d.ts +35 -0
- package/dist/mcp-endpoint.d.ts.map +1 -0
- package/dist/merge-settings.d.ts +57 -0
- package/dist/merge-settings.d.ts.map +1 -0
- package/dist/mint-board-code.d.ts +41 -0
- package/dist/mint-board-code.d.ts.map +1 -0
- package/dist/open-phase.d.ts +107 -0
- package/dist/open-phase.d.ts.map +1 -0
- package/dist/probe-mcp.d.ts +47 -0
- package/dist/probe-mcp.d.ts.map +1 -0
- package/dist/resolve-credential.d.ts +126 -0
- package/dist/resolve-credential.d.ts.map +1 -0
- package/dist/scan.d.ts +131 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/setup/discovery.d.ts +73 -0
- package/dist/setup/discovery.d.ts.map +1 -0
- package/dist/setup/engagement.d.ts +99 -0
- package/dist/setup/engagement.d.ts.map +1 -0
- package/dist/setup/index.d.ts +17 -0
- package/dist/setup/index.d.ts.map +1 -0
- package/dist/setup/manifest.d.ts +155 -0
- package/dist/setup/manifest.d.ts.map +1 -0
- package/dist/setup/rows.d.ts +57 -0
- package/dist/setup/rows.d.ts.map +1 -0
- package/package.json +55 -0
- package/scaffolding/test/fixtures/captured/.gitkeep +0 -0
- package/scaffolding/test/fixtures/captured/manifest.json +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/setup/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAUH;iFACiF;AACjF,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;+CAC2C;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;CAC7C;AAED;oCACoC;AACpC,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvD;AA0JD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAuFtE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,YAAY,EAAE,CAG/E;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAI/D"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The confirm phase's output — the engagement record, the tracker choice, and the
|
|
3
|
+
* halt (feature `halfcycle-setup`, criteria 2 and 7; task T-17).
|
|
4
|
+
*
|
|
5
|
+
* **The halt is the load-bearing part.** `ENGAGEMENT.md` is a record of decisions,
|
|
6
|
+
* and a record of an unasked question is a fabrication — so the command does not
|
|
7
|
+
* proceed with an unanswered decision. There is no "we'll assume" and no default
|
|
8
|
+
* that skips the question. `buildEngagementRecord` returns a HALT rather than a
|
|
9
|
+
* document, and the halt writes nothing at all.
|
|
10
|
+
*
|
|
11
|
+
* **What a halt must not report, and why it is stated here rather than left to the
|
|
12
|
+
* caller.** A halt is precisely the case where the gate was NOT conducted, so the
|
|
13
|
+
* report it produces asserts only that the step was attempted and could not
|
|
14
|
+
* complete. It emits nothing. Reporting a failing gate would record an outcome for
|
|
15
|
+
* a question nobody asked — into a store with one writer, no delete path, and an
|
|
16
|
+
* upsert that may never touch a verdict — and gate precedence would then hand the
|
|
17
|
+
* step's decision to the gate tier, so a later completed run alone could no longer
|
|
18
|
+
* satisfy it. `HaltReport.emits` is therefore an empty, frozen list: the shape says
|
|
19
|
+
* what is true and nothing more.
|
|
20
|
+
*
|
|
21
|
+
* **Why the six decisions are not enumerated in this file.** Which questions an
|
|
22
|
+
* engagement settles is the method's content and has one home, upstream. This
|
|
23
|
+
* module enforces the *rule* — every decision put carries an answer AND a reason,
|
|
24
|
+
* and the caller states how many the run owes — which is what the criterion
|
|
25
|
+
* actually asserts. Encoding the list here would put method structure at rest in a
|
|
26
|
+
* shippable (INV-016's Connect surface) and would give this package a second home
|
|
27
|
+
* for something the method already owns.
|
|
28
|
+
*
|
|
29
|
+
* INV-001: this module imports only its own package's siblings.
|
|
30
|
+
*/
|
|
31
|
+
import type { ArtefactRow } from './manifest.js';
|
|
32
|
+
/** One settled decision: what was asked, what was answered, and why. A decision
|
|
33
|
+
* missing either half is not settled. */
|
|
34
|
+
export interface Decision {
|
|
35
|
+
readonly key: string;
|
|
36
|
+
readonly question: string;
|
|
37
|
+
readonly answer: string;
|
|
38
|
+
readonly rationale: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The tracker choice — a seventh recorded value, not one of the decisions.
|
|
42
|
+
*
|
|
43
|
+
* `chosen` defaults to the flat-file backend, `alternativeOffered` is what was put
|
|
44
|
+
* beside it, and `rationale` is why. Choosing silently is the failure this shape
|
|
45
|
+
* exists to prevent: the cost of a second place to look is consistently
|
|
46
|
+
* underestimated, and a tracker nobody opens is worse than a file in the repository.
|
|
47
|
+
*/
|
|
48
|
+
export interface TrackerChoice {
|
|
49
|
+
readonly chosen: string;
|
|
50
|
+
readonly alternativeOffered: string;
|
|
51
|
+
readonly rationale: string;
|
|
52
|
+
/** The repository directory the choice needs, or null when the backend lives
|
|
53
|
+
* outside the repository. */
|
|
54
|
+
readonly home: string | null;
|
|
55
|
+
}
|
|
56
|
+
/** The default, stated rather than assumed — with the alternative offered. */
|
|
57
|
+
export declare function flatFileTrackerDefault(): TrackerChoice;
|
|
58
|
+
/**
|
|
59
|
+
* What a halt reports. `emits` is empty and frozen — a halt conducts no gate, so
|
|
60
|
+
* it emits nothing, and there is no code path in this module that can add to it.
|
|
61
|
+
*/
|
|
62
|
+
export interface HaltReport {
|
|
63
|
+
readonly halted: true;
|
|
64
|
+
/** The keys of the decisions that are not settled, in the order they were put. */
|
|
65
|
+
readonly unsettled: readonly string[];
|
|
66
|
+
/** Plain words for the developer and for the step report's failure reason. */
|
|
67
|
+
readonly reason: string;
|
|
68
|
+
/** Always empty: nothing is emitted by a step that could not be conducted. */
|
|
69
|
+
readonly emits: readonly never[];
|
|
70
|
+
}
|
|
71
|
+
export type EngagementOutcome = {
|
|
72
|
+
readonly ok: true;
|
|
73
|
+
readonly document: string;
|
|
74
|
+
readonly rows: readonly ArtefactRow[];
|
|
75
|
+
} | {
|
|
76
|
+
readonly ok: false;
|
|
77
|
+
readonly halt: HaltReport;
|
|
78
|
+
};
|
|
79
|
+
export interface EngagementInput {
|
|
80
|
+
/** The decisions this run put, each with its answer and its reason. */
|
|
81
|
+
readonly decisions: readonly Decision[];
|
|
82
|
+
/** How many decisions the run owes. Supplied by the caller — the method owns
|
|
83
|
+
* which questions those are; this module owns that none of them is skipped. */
|
|
84
|
+
readonly requiredDecisions: number;
|
|
85
|
+
readonly tracker: TrackerChoice;
|
|
86
|
+
/** A name for the engagement, used in the document's title. */
|
|
87
|
+
readonly projectName: string;
|
|
88
|
+
/** When the decisions were settled, ISO-8601. */
|
|
89
|
+
readonly settledAt: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build the engagement record's manifest rows, or halt.
|
|
93
|
+
*
|
|
94
|
+
* Halts when fewer decisions were put than the run owes, or when any decision put
|
|
95
|
+
* is missing its answer or its reason. A halt returns NO rows, so nothing is
|
|
96
|
+
* written and no partial record is left behind.
|
|
97
|
+
*/
|
|
98
|
+
export declare function buildEngagementRecord(input: EngagementInput): EngagementOutcome;
|
|
99
|
+
//# sourceMappingURL=engagement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engagement.d.ts","sourceRoot":"","sources":["../../src/setup/engagement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAOjD;0CAC0C;AAC1C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;kCAC8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,8EAA8E;AAC9E,wBAAgB,sBAAsB,IAAI,aAAa,CAStD;AAMD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,SAAS,KAAK,EAAE,CAAC;CAClC;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,GACvF;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAWtD,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IACxC;oFACgF;IAChF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAgCD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CA6B/E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The setup write path — the one mechanism a served run lands client-tree
|
|
3
|
+
* artefacts through, plus the discover and confirm halves that feed it.
|
|
4
|
+
*
|
|
5
|
+
* `manifest.ts` is the mechanism (scope §2; the design journey's Layer-2 writes are
|
|
6
|
+
* its second consumer per scope §7, driven by T-18's walk); `rows.ts` fixes the
|
|
7
|
+
* declared paths and the additive form; `discovery.ts` is the anchored discover
|
|
8
|
+
* phase; `engagement.ts` is the confirm phase's record and its halt.
|
|
9
|
+
*/
|
|
10
|
+
export { applySetupWrites, SetupManifest } from './manifest.js';
|
|
11
|
+
export type { ArtefactRow, RowOutcome, ManifestEntry, WriteReport } from './manifest.js';
|
|
12
|
+
export { contextIndexRow, agentsPointerRow, layerDocumentRow, documentSectionRow, engagementRecordRow, trackerHomeRow, FLAT_FILE_TRACKER_HOME, } from './rows.js';
|
|
13
|
+
export { discoverRepository, questionsToPut, renderDiscovery, renderAnchor } from './discovery.js';
|
|
14
|
+
export type { DiscoveredFact, OpenQuestion, DiscoveryResult, FactAnchor } from './discovery.js';
|
|
15
|
+
export { buildEngagementRecord, flatFileTrackerDefault } from './engagement.js';
|
|
16
|
+
export type { Decision, TrackerChoice, EngagementInput, EngagementOutcome, HaltReport } from './engagement.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/setup/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEzF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,GACvB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnG,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAChF,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The write manifest — the ONE mechanism that lands client-tree artefacts during a
|
|
3
|
+
* served run (feature `halfcycle-setup`, the scope §2 write manifest; task T-17).
|
|
4
|
+
*
|
|
5
|
+
* **What this is.** A session resolving a served command executes what comes back
|
|
6
|
+
* and, where the instruction directs a write, lands it *through here*. Every row of
|
|
7
|
+
* the manifest — the union of what the served steps write — goes through one
|
|
8
|
+
* function, so the never-clobber rule, the declared-path rule and the report are
|
|
9
|
+
* stated once rather than per caller. `halfcycle-setup`'s five rows are the first
|
|
10
|
+
* consumer; the design journey's Layer-2 artefacts are the second (scope §7: one
|
|
11
|
+
* mechanism, two consumers).
|
|
12
|
+
*
|
|
13
|
+
* **The timing is the caller's, and that is deliberate.** The spec's manifest is
|
|
14
|
+
* *spread across the served steps* — `CLAUDE.md`/`AGENTS.md` and the scaffolding
|
|
15
|
+
* land at the first resolves, `ENGAGEMENT.md` and the tracker home at the last —
|
|
16
|
+
* and it is explicitly NOT a terminal write phase. This module therefore takes a
|
|
17
|
+
* batch of rows per call and is invoked once per resolve; it holds no schedule.
|
|
18
|
+
*
|
|
19
|
+
* **WHAT THIS MODULE MUST NOT BECOME, and why the API is shaped this way.** It
|
|
20
|
+
* carries no map from a step to the rows that step writes. Such a table is
|
|
21
|
+
* method structure at rest in a shippable (INV-016's Connect surface: nothing
|
|
22
|
+
* method-shaped is installed at rest; INV-001's allowlist exists to keep
|
|
23
|
+
* method-shaped values out of this package), and `stub-vocabulary-gate.test.ts`
|
|
24
|
+
* already asserts no source file here carries a step id. The instruction that
|
|
25
|
+
* directs a write arrives from the delivery service per resolve; the session turns
|
|
26
|
+
* it into rows; this module validates and applies them. Anything that would let
|
|
27
|
+
* this file answer "what does step X write?" is out of bounds.
|
|
28
|
+
*
|
|
29
|
+
* **Two rules from the spec are acceptance criteria, not implementation detail,
|
|
30
|
+
* and both are enforced here rather than by the caller:**
|
|
31
|
+
*
|
|
32
|
+
* - **`docs/method/` is never created in a client repository (INV-016).** It is
|
|
33
|
+
* denied POSITIVELY, not by omission: `docs/` scaffolding is a declared row,
|
|
34
|
+
* so `docs/method/` sits *inside* an allowed prefix and a plain allowlist would
|
|
35
|
+
* wave it through. The deny check runs first and wins, it runs on the
|
|
36
|
+
* `posix.normalize`d path so `.` and `//` segments cannot slip past it, and it
|
|
37
|
+
* is case-insensitive because on the default macOS filesystem `docs/METHOD/` IS
|
|
38
|
+
* `docs/method/`.
|
|
39
|
+
* - **Nothing pre-existing is overwritten.** A file the developer already owns is
|
|
40
|
+
* left byte-for-byte and reported; a file that gains a section keeps every byte
|
|
41
|
+
* it had. There is no overwrite path in this module at all. A path that is, or
|
|
42
|
+
* sits under, a **symbolic link** is left alone and reported rather than written
|
|
43
|
+
* through. **That guarantee is symlink-shaped and no wider:** `lstat` cannot see
|
|
44
|
+
* a HARD link, so a hardlinked declared path still writes into the file it
|
|
45
|
+
* shares an inode with, wherever that is. Stated rather than closed — a hardlink
|
|
46
|
+
* into a client repository is not a shape this product creates, and the honest
|
|
47
|
+
* boundary is worth more here than a guard that would have to stat every inode.
|
|
48
|
+
*
|
|
49
|
+
* **What the content check is, stated precisely because a wider claim was made here
|
|
50
|
+
* twice.** The module refuses content carrying any of three decidable forms of
|
|
51
|
+
* method structure — a step id, a step annotation, an anchor declaration. It is a
|
|
52
|
+
* tripwire, **not** a detector of method prose. **Measured over the population a
|
|
53
|
+
* session can actually reach — served bodies, not corpus documents — it refuses 0 of
|
|
54
|
+
* 58**, and only the step-id form fires on the wire at all — the anchor form has a
|
|
55
|
+
* latent cost there rather than a benefit. The constants' docblock
|
|
56
|
+
* carries both populations and why they differ; read it before crediting this check
|
|
57
|
+
* with anything.
|
|
58
|
+
*
|
|
59
|
+
* INV-019: the paths this module may write are exactly the five the feature spec
|
|
60
|
+
* declares — `CLAUDE.md`, `AGENTS.md`, `ENGAGEMENT.md`, `docs/tasks/` and the
|
|
61
|
+
* layer-doc scaffolding under `docs/`. All five are Zone-A client product material
|
|
62
|
+
* and clear the egress gate's path allowlist.
|
|
63
|
+
*
|
|
64
|
+
* INV-001: Node builtins only.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* One row of the manifest: a client-tree path and what the session wants there.
|
|
68
|
+
*
|
|
69
|
+
* `file` and `directory` are create-if-absent; `section` is the additive form the
|
|
70
|
+
* never-clobber rule is built around — an existing `CLAUDE.md` gains a section and
|
|
71
|
+
* keeps every byte it had.
|
|
72
|
+
*/
|
|
73
|
+
export type ArtefactRow = {
|
|
74
|
+
readonly path: string;
|
|
75
|
+
readonly kind: 'file';
|
|
76
|
+
readonly content: string;
|
|
77
|
+
} | {
|
|
78
|
+
readonly path: string;
|
|
79
|
+
readonly kind: 'section';
|
|
80
|
+
readonly heading: string;
|
|
81
|
+
readonly body: string;
|
|
82
|
+
} | {
|
|
83
|
+
readonly path: string;
|
|
84
|
+
readonly kind: 'directory';
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* What happened to one row.
|
|
88
|
+
*
|
|
89
|
+
* - `created` — the path did not exist; it was created.
|
|
90
|
+
* - `section-added` — an existing file gained a section and kept every byte.
|
|
91
|
+
* - `already-present`— our content/section was already there; nothing was written.
|
|
92
|
+
* - `left-alone` — the developer already owns that path with different content;
|
|
93
|
+
* it was NOT overwritten, and it is reported.
|
|
94
|
+
*/
|
|
95
|
+
export type RowOutcome = 'created' | 'section-added' | 'already-present' | 'left-alone';
|
|
96
|
+
/** One line of the printed report. `path` is repo-relative, `/`-separated. */
|
|
97
|
+
export interface ManifestEntry {
|
|
98
|
+
readonly path: string;
|
|
99
|
+
readonly outcome: RowOutcome;
|
|
100
|
+
/** Why, in the developer's language — the report is load-bearing, not courteous. */
|
|
101
|
+
readonly note: string;
|
|
102
|
+
}
|
|
103
|
+
/** The result of applying one batch of rows (i.e. of one resolve's writes). */
|
|
104
|
+
export interface WriteReport {
|
|
105
|
+
readonly entries: readonly ManifestEntry[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Apply one batch of manifest rows to a project repository and report every path
|
|
109
|
+
* touched.
|
|
110
|
+
*
|
|
111
|
+
* Called once per resolve, with the rows that resolve's instruction directed — so
|
|
112
|
+
* the writes land WITH their step rather than in a terminal phase. Refuses (throws)
|
|
113
|
+
* on an undeclared path, on the reserved mirror path, and on content carrying
|
|
114
|
+
* method structure; those are gate failures, not warnings.
|
|
115
|
+
*/
|
|
116
|
+
export declare function applySetupWrites(targetRepo: string, rows: readonly ArtefactRow[]): WriteReport;
|
|
117
|
+
/**
|
|
118
|
+
* The accumulated manifest across a run — the union of what the served steps wrote,
|
|
119
|
+
* printed once as the report the spec calls load-bearing. A setup command that works
|
|
120
|
+
* silently is indistinguishable from one that failed.
|
|
121
|
+
*/
|
|
122
|
+
export declare class SetupManifest {
|
|
123
|
+
private readonly rows;
|
|
124
|
+
/** Fold one resolve's report into the run's manifest. */
|
|
125
|
+
add(report: WriteReport): void;
|
|
126
|
+
/** Every row, in the order the resolves produced them. */
|
|
127
|
+
entries(): readonly ManifestEntry[];
|
|
128
|
+
/** The paths this run actually changed — created or section-added. */
|
|
129
|
+
changedPaths(): readonly string[];
|
|
130
|
+
/** True iff the run changed nothing — the honest output of a second run. */
|
|
131
|
+
nothingToDo(): boolean;
|
|
132
|
+
/**
|
|
133
|
+
* The paths this run wanted and did not get: a name the developer already uses, or
|
|
134
|
+
* a symlink it would not follow. **Not the same as "already set up"** — a run where
|
|
135
|
+
* every row is `left-alone` changed nothing *and* set nothing up, and reporting
|
|
136
|
+
* that as done is the failure the report exists to prevent.
|
|
137
|
+
*/
|
|
138
|
+
leftAlonePaths(): readonly string[];
|
|
139
|
+
/**
|
|
140
|
+
* The report, in plain words. Names every path touched, including the ones left
|
|
141
|
+
* alone — a path the command decided not to write is exactly what a developer
|
|
142
|
+
* needs told.
|
|
143
|
+
*
|
|
144
|
+
* **The header describes the run's actual composition, and says nothing universal
|
|
145
|
+
* unless it holds.** Two earlier forms got this wrong in the same way, one round
|
|
146
|
+
* apart: the first printed "already set up" for a run that wrote nothing *because
|
|
147
|
+
* every path was already the developer's*, and the second printed "every path this
|
|
148
|
+
* needed is already yours" for the **mixed** state — some rows already correct
|
|
149
|
+
* from an earlier run, some blocked — which is the ordinary second-run case and is
|
|
150
|
+
* simply false. Counts are what the header is built from now, and *every* appears
|
|
151
|
+
* only when the count says every.
|
|
152
|
+
*/
|
|
153
|
+
render(): string;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/setup/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AASH;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,eAAe,GAAG,iBAAiB,GAAG,YAAY,CAAC;AAExF,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AA4aD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CAyB9F;AAMD;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuB;IAE5C,yDAAyD;IACzD,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAI9B,0DAA0D;IAC1D,OAAO,IAAI,SAAS,aAAa,EAAE;IAInC,sEAAsE;IACtE,YAAY,IAAI,SAAS,MAAM,EAAE;IAMjC,4EAA4E;IAC5E,WAAW,IAAI,OAAO;IAItB;;;;;OAKG;IACH,cAAc,IAAI,SAAS,MAAM,EAAE;IAInC;;;;;;;;;;;;;OAaG;IACH,MAAM,IAAI,MAAM;CAsBjB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The declared rows of the manifest, as row constructors (feature
|
|
3
|
+
* `halfcycle-setup`; tasks T-17 and T-18).
|
|
4
|
+
*
|
|
5
|
+
* **Why constructors rather than a table of content.** The manifest's rows are a
|
|
6
|
+
* client-tree *path* convention — `CLAUDE.md`, `AGENTS.md`, `ENGAGEMENT.md`,
|
|
7
|
+
* the tracker home and the layer-doc scaffolding under `docs/` — and those paths
|
|
8
|
+
* are what [INV-019] makes this package declare. The *content* of each row is the
|
|
9
|
+
* session's, composed from the instruction the delivery service served for that
|
|
10
|
+
* step. So each function here fixes the path and takes the content.
|
|
11
|
+
*
|
|
12
|
+
* **What is deliberately absent.** There is no function here that answers "which
|
|
13
|
+
* rows does step X write?", and no caller can ask one. The schedule — which rows
|
|
14
|
+
* land at which resolve — belongs to the served run, not to this package (see
|
|
15
|
+
* `manifest.ts`'s docblock).
|
|
16
|
+
*
|
|
17
|
+
* INV-001: no imports outside this package's own modules.
|
|
18
|
+
*/
|
|
19
|
+
import type { ArtefactRow } from './manifest.js';
|
|
20
|
+
/** The tracker home the flat-file backend uses. `tracker-adapter-conventions` §3
|
|
21
|
+
* pins it; this package creates the directory and nothing else — the adapter,
|
|
22
|
+
* the vocabulary and the conformance suite are `tracker-localfile`'s. */
|
|
23
|
+
export declare const FLAT_FILE_TRACKER_HOME = "docs/tasks";
|
|
24
|
+
/** The project context index. Created when absent; when the developer already has
|
|
25
|
+
* one it gains a section and keeps every byte. */
|
|
26
|
+
export declare function contextIndexRow(heading: string, body: string): ArtefactRow;
|
|
27
|
+
/** The pointer file that sends any other agent to the context index. Whole-file:
|
|
28
|
+
* a developer who already has one keeps it untouched. */
|
|
29
|
+
export declare function agentsPointerRow(content: string): ArtefactRow;
|
|
30
|
+
/** A layer document the project does not have yet. Scaffolding only where absent
|
|
31
|
+
* is the mechanism's job — an existing document is left alone and reported. */
|
|
32
|
+
export declare function layerDocumentRow(path: string, content: string): ArtefactRow;
|
|
33
|
+
/**
|
|
34
|
+
* A section added to a document the project already has, at any declared path
|
|
35
|
+
* (task T-18 — the design journey's shape, which `/halfcycle-setup` never had).
|
|
36
|
+
*
|
|
37
|
+
* **The gap this closes.** Setup writes each of its documents once, so a whole-file
|
|
38
|
+
* row was enough: `contextIndexRow` is the only additive row and it is pinned to
|
|
39
|
+
* `CLAUDE.md`. The design journey writes a document at one served step and comes
|
|
40
|
+
* back to it at a LATER one — `docs/invariants.md` is created as a template and
|
|
41
|
+
* then gains extracted invariants; a features index is created empty and then gains
|
|
42
|
+
* entries. A whole-file row at the second step would find the file present with
|
|
43
|
+
* different bytes and report `left-alone`, which is correct never-clobber behaviour
|
|
44
|
+
* and the wrong outcome for the run: the step's work would silently not land.
|
|
45
|
+
*
|
|
46
|
+
* The path is the caller's, exactly as `layerDocumentRow`'s is, and for the same
|
|
47
|
+
* reason: which document a step writes is the served instruction's to say, and this
|
|
48
|
+
* package holds no table of it. Everything that makes the row safe — the declared
|
|
49
|
+
* path allowlist, the reserved-mirror deny, the single-line heading rule and the
|
|
50
|
+
* never-clobber guarantee — is `manifest.ts`'s and is not restated here.
|
|
51
|
+
*/
|
|
52
|
+
export declare function documentSectionRow(path: string, heading: string, body: string): ArtefactRow;
|
|
53
|
+
/** The record of the engagement's decisions. */
|
|
54
|
+
export declare function engagementRecordRow(content: string): ArtefactRow;
|
|
55
|
+
/** The chosen tracker's home, when it is the flat-file backend. */
|
|
56
|
+
export declare function trackerHomeRow(home?: string): ArtefactRow;
|
|
57
|
+
//# sourceMappingURL=rows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../../src/setup/rows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;0EAE0E;AAC1E,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD;mDACmD;AACnD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAE1E;AAED;0DAC0D;AAC1D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAE7D;AAED;gFACgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAE3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAE3F;AAED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAEhE;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAA+B,GAAG,WAAW,CAEjF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "halfcycle",
|
|
3
|
+
"version": "0.3.7",
|
|
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
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"ai-agents",
|
|
9
|
+
"agentic-coding",
|
|
10
|
+
"spec-driven-development",
|
|
11
|
+
"code-review",
|
|
12
|
+
"mcp",
|
|
13
|
+
"prd",
|
|
14
|
+
"software-architecture",
|
|
15
|
+
"ai-code-quality",
|
|
16
|
+
"engineering-process",
|
|
17
|
+
"technical-specification"
|
|
18
|
+
],
|
|
19
|
+
"homepage": "https://halfcycle.ai",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"commands",
|
|
27
|
+
"scaffolding",
|
|
28
|
+
"bin",
|
|
29
|
+
".claude-plugin"
|
|
30
|
+
],
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"bin": {
|
|
38
|
+
"halfcycle": "./dist/bin.js"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json && node scripts/bundle-entries.mjs && node scripts/vendor-runner-bin.mjs",
|
|
42
|
+
"typecheck": "tsc --noEmit -p tsconfig.test.json",
|
|
43
|
+
"test": "tsc -p tsconfig.test.json && node --test \"dist-test/test/\"*.test.js"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"zod": "^4.4.3"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@halfcycle/core": "workspace:*",
|
|
50
|
+
"@halfcycle/events": "workspace:*",
|
|
51
|
+
"@types/node": "^20.0.0",
|
|
52
|
+
"esbuild": "^0.28.1",
|
|
53
|
+
"typescript": "^5.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_readme": "Halfcycle's captured-fixture store. Empty until something is captured. Halfcycle writes recorded third-party API responses under test/fixtures/captured/<provider>/<slug>.json and indexes them here, so your tests can replay a real response instead of calling the live service. It is separate from your own test directory on purpose and is not a second home for your tests — put those wherever your project already puts them. Safe to leave alone; deleting it means the next capture recreates it. This note disappears once the first fixture is captured.",
|
|
3
|
+
"entries": []
|
|
4
|
+
}
|