@bluewombat/manager-fake 0.1.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.
Files changed (99) hide show
  1. package/README.md +58 -0
  2. package/SPECS.md +65 -0
  3. package/dist/adapter/fetch/run-fetch.d.ts +24 -0
  4. package/dist/adapter/fetch/run-fetch.d.ts.map +1 -0
  5. package/dist/adapter/fetch/run-fetch.js +119 -0
  6. package/dist/adapter/fetch/run-fetch.js.map +1 -0
  7. package/dist/adapter/normalize/fingerprint.d.ts +8 -0
  8. package/dist/adapter/normalize/fingerprint.d.ts.map +1 -0
  9. package/dist/adapter/normalize/fingerprint.js +26 -0
  10. package/dist/adapter/normalize/fingerprint.js.map +1 -0
  11. package/dist/adapter/normalize/normalize.d.ts +17 -0
  12. package/dist/adapter/normalize/normalize.d.ts.map +1 -0
  13. package/dist/adapter/normalize/normalize.js +199 -0
  14. package/dist/adapter/normalize/normalize.js.map +1 -0
  15. package/dist/adapter/progress/emit.d.ts +3 -0
  16. package/dist/adapter/progress/emit.d.ts.map +1 -0
  17. package/dist/adapter/progress/emit.js +6 -0
  18. package/dist/adapter/progress/emit.js.map +1 -0
  19. package/dist/adapter/raw/parse-raw.d.ts +14 -0
  20. package/dist/adapter/raw/parse-raw.d.ts.map +1 -0
  21. package/dist/adapter/raw/parse-raw.js +47 -0
  22. package/dist/adapter/raw/parse-raw.js.map +1 -0
  23. package/dist/adapter/run/run-adapter.d.ts +25 -0
  24. package/dist/adapter/run/run-adapter.d.ts.map +1 -0
  25. package/dist/adapter/run/run-adapter.js +125 -0
  26. package/dist/adapter/run/run-adapter.js.map +1 -0
  27. package/dist/adapter/types.d.ts +51 -0
  28. package/dist/adapter/types.d.ts.map +1 -0
  29. package/dist/adapter/types.js +3 -0
  30. package/dist/adapter/types.js.map +1 -0
  31. package/dist/emitter/event/field-matrix.d.ts +29 -0
  32. package/dist/emitter/event/field-matrix.d.ts.map +1 -0
  33. package/dist/emitter/event/field-matrix.js +93 -0
  34. package/dist/emitter/event/field-matrix.js.map +1 -0
  35. package/dist/emitter/progress/emit.d.ts +3 -0
  36. package/dist/emitter/progress/emit.d.ts.map +1 -0
  37. package/dist/emitter/progress/emit.js +6 -0
  38. package/dist/emitter/progress/emit.js.map +1 -0
  39. package/dist/emitter/render/render-event.d.ts +14 -0
  40. package/dist/emitter/render/render-event.d.ts.map +1 -0
  41. package/dist/emitter/render/render-event.js +116 -0
  42. package/dist/emitter/render/render-event.js.map +1 -0
  43. package/dist/emitter/render/truncate.d.ts +9 -0
  44. package/dist/emitter/render/truncate.d.ts.map +1 -0
  45. package/dist/emitter/render/truncate.js +10 -0
  46. package/dist/emitter/render/truncate.js.map +1 -0
  47. package/dist/emitter/run/run-emitter.d.ts +21 -0
  48. package/dist/emitter/run/run-emitter.d.ts.map +1 -0
  49. package/dist/emitter/run/run-emitter.js +89 -0
  50. package/dist/emitter/run/run-emitter.js.map +1 -0
  51. package/dist/emitter/thread/slug.d.ts +7 -0
  52. package/dist/emitter/thread/slug.d.ts.map +1 -0
  53. package/dist/emitter/thread/slug.js +18 -0
  54. package/dist/emitter/thread/slug.js.map +1 -0
  55. package/dist/emitter/thread/thread.d.ts +32 -0
  56. package/dist/emitter/thread/thread.d.ts.map +1 -0
  57. package/dist/emitter/thread/thread.js +58 -0
  58. package/dist/emitter/thread/thread.js.map +1 -0
  59. package/dist/emitter/types.d.ts +45 -0
  60. package/dist/emitter/types.d.ts.map +1 -0
  61. package/dist/emitter/types.js +3 -0
  62. package/dist/emitter/types.js.map +1 -0
  63. package/dist/index.d.ts +16 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +98 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/listener/delivery/run-hook.d.ts +8 -0
  68. package/dist/listener/delivery/run-hook.d.ts.map +1 -0
  69. package/dist/listener/delivery/run-hook.js +50 -0
  70. package/dist/listener/delivery/run-hook.js.map +1 -0
  71. package/dist/listener/progress/emit.d.ts +3 -0
  72. package/dist/listener/progress/emit.d.ts.map +1 -0
  73. package/dist/listener/progress/emit.js +6 -0
  74. package/dist/listener/progress/emit.js.map +1 -0
  75. package/dist/listener/run/run-listener.d.ts +31 -0
  76. package/dist/listener/run/run-listener.d.ts.map +1 -0
  77. package/dist/listener/run/run-listener.js +173 -0
  78. package/dist/listener/run/run-listener.js.map +1 -0
  79. package/dist/listener/source/list-source.d.ts +13 -0
  80. package/dist/listener/source/list-source.d.ts.map +1 -0
  81. package/dist/listener/source/list-source.js +35 -0
  82. package/dist/listener/source/list-source.js.map +1 -0
  83. package/dist/listener/source/read-event.d.ts +7 -0
  84. package/dist/listener/source/read-event.d.ts.map +1 -0
  85. package/dist/listener/source/read-event.js +47 -0
  86. package/dist/listener/source/read-event.js.map +1 -0
  87. package/dist/listener/source/select-events.d.ts +13 -0
  88. package/dist/listener/source/select-events.d.ts.map +1 -0
  89. package/dist/listener/source/select-events.js +23 -0
  90. package/dist/listener/source/select-events.js.map +1 -0
  91. package/dist/listener/types.d.ts +42 -0
  92. package/dist/listener/types.d.ts.map +1 -0
  93. package/dist/listener/types.js +3 -0
  94. package/dist/listener/types.js.map +1 -0
  95. package/dist/manager.d.ts +17 -0
  96. package/dist/manager.d.ts.map +1 -0
  97. package/dist/manager.js +114 -0
  98. package/dist/manager.js.map +1 -0
  99. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Manager: fake
2
+
3
+ The FeatureManager triplet that needs no account: a directory of JSON files is
4
+ the Source, a directory of `.ndjson` Threads is the report.
5
+ Contract: [SPECS.md](./SPECS.md).
6
+
7
+ ```bash
8
+ npm install @bluewombat/runtime @bluewombat/manager-fake
9
+ npx mason init --manager @bluewombat/manager-fake
10
+ ```
11
+
12
+ ```json
13
+ {
14
+ "manager": "@bluewombat/manager-fake",
15
+ "managerOptions": { "source": "./.mason/source", "target": "./.mason/threads" }
16
+ }
17
+ ```
18
+
19
+ ## Options
20
+
21
+ | Option | Required | Default | Meaning |
22
+ | ----------------- | -------- | ------- | --------------------------------------------------------------- |
23
+ | `source` | yes | — | Directory of raw intentions. Must exist. Relative to the config |
24
+ | `target` | yes | — | Directory the Threads are appended to. Created if absent |
25
+ | `defaultPriority` | no | `50` | Priority for a raw intention that carries none (0…100) |
26
+
27
+ ## Stack
28
+
29
+ Repository stack — TypeScript, Node 24.20, Biome, `node:test`. See [docs/DEVELOPMENT.md](../../../docs/DEVELOPMENT.md).
30
+
31
+ ## Setup
32
+
33
+ From the repository root:
34
+
35
+ ```bash
36
+ nvm use
37
+ npm install
38
+ ```
39
+
40
+ ## Commands
41
+
42
+ | Task | Command |
43
+ | --------- | ---------------- |
44
+ | Lint | `npm run lint` |
45
+ | Format | `npm run format` |
46
+ | Typecheck | `npm run tsc` |
47
+ | Test | `npm test` |
48
+ | Build | `npm run build` |
49
+
50
+ ## Layout
51
+
52
+ ```
53
+ SPECS.md the contract
54
+ README.md how to build and configure it
55
+ src/
56
+ index.ts createManager, checkManager, scaffoldManager — the plugin face
57
+ manager.ts the ManagerPort (listen / adapt / report live in listener/, adapter/, emitter/)
58
+ ```
package/SPECS.md ADDED
@@ -0,0 +1,65 @@
1
+ # Manager: fake
2
+
3
+ A plugin, not a Transformer. Directory Source in, directory Thread out, as
4
+ one `ManagerPort`. Listen / adapt / report live in this package.
5
+
6
+ ## 1. Job
7
+
8
+ ```
9
+ Host manager-fake
10
+ ---- ------------
11
+ managerOptions read source / target
12
+ a Cursor drain the directory
13
+ one semantic Event append to the Thread
14
+ ← ManagerPort
15
+ ```
16
+
17
+ **In:** a `ManagerContext`. **Out:** a `ManagerPort`, or a reason.
18
+
19
+ ## 2. Options
20
+
21
+ Relative paths resolve against the config file's directory, so a checked-in
22
+ example needs no absolute path.
23
+
24
+ | Option | Rule |
25
+ | ----------------- | ----------------------------------------------------------------- |
26
+ | `source` | Required. Must already exist as a directory — this package never creates it |
27
+ | `target` | Required. Created at `createManager` time if absent |
28
+ | `defaultPriority` | Integer 0…100. Default 50 |
29
+
30
+ An unknown option key is refused by name.
31
+
32
+ ## 3. Keys
33
+
34
+ `fake:<id>` from the raw intention's `id`, or `fake:unconvertible` when it has
35
+ none. The project is the payload's `project`, or `unknown`.
36
+
37
+ ## 4. Ready
38
+
39
+ This manager has no ready signal: a directory Source delivers a `ready` file as
40
+ its own intention, so `signalsReady` is absent and Host uses the
41
+ FeatureStandard's `intent`.
42
+
43
+ ## 5. Doctor
44
+
45
+ `checkManager` reports the Source (`fail` when it is not a directory) and the
46
+ Thread directory (`warn` when it does not exist yet — the run creates it). No
47
+ network, ever.
48
+
49
+ ## 6. Init
50
+
51
+ `scaffoldManager` writes the default `source` / `target` paths and creates
52
+ those directories so the first JSON file has somewhere to go. `createManager`
53
+ still refuses a missing Source: prepare is an init convenience, not a silent
54
+ create at run time.
55
+
56
+ ## 7. Acceptance
57
+
58
+ 1. Relative `source` and `target` resolve against the config file, and the
59
+ Thread directory exists after `createManager`.
60
+ 2. A missing `source` directory, a missing required option, and an unknown
61
+ option key each return a reason, not a throw.
62
+ 3. `checkManager` with unreadable options returns exactly one `fail`.
63
+ 4. `scaffoldManager` creates the default Source and Thread directories.
64
+
65
+ How to build and configure: [README.md](./README.md).
@@ -0,0 +1,24 @@
1
+ export type FetchResult = {
2
+ kind: "merged";
3
+ object: Record<string, unknown>;
4
+ } | {
5
+ kind: "empty";
6
+ } | {
7
+ kind: "unavailable";
8
+ detail: string;
9
+ } | {
10
+ kind: "interrupted";
11
+ };
12
+ export type FetchRequest = {
13
+ argv: string[];
14
+ timeoutMs: number;
15
+ shouldInterrupt: () => boolean;
16
+ };
17
+ /**
18
+ * Run the enrichment command. Every failure is `unavailable`, never `invalid`:
19
+ * a Fetch that did not answer says nothing about the intention.
20
+ */
21
+ export declare function runFetch(request: FetchRequest): Promise<FetchResult>;
22
+ /** Exported for tests: the stdout contract of the Fetch, without a process. */
23
+ export declare function readFetchStdout(stdout: string): FetchResult;
24
+ //# sourceMappingURL=run-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-fetch.d.ts","sourceRoot":"","sources":["../../../src/adapter/fetch/run-fetch.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5B,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,OAAO,CAAC;CAChC,CAAC;AAQF;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA2FpE;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAgB3D"}
@@ -0,0 +1,119 @@
1
+ import { spawn } from "node:child_process";
2
+ const OUTPUT_TRUNCATE = 8_192;
3
+ function truncate(text) {
4
+ return text.length <= OUTPUT_TRUNCATE ? text : `${text.slice(0, OUTPUT_TRUNCATE)}…[truncated]`;
5
+ }
6
+ /**
7
+ * Run the enrichment command. Every failure is `unavailable`, never `invalid`:
8
+ * a Fetch that did not answer says nothing about the intention.
9
+ */
10
+ export function runFetch(request) {
11
+ return new Promise((resolve) => {
12
+ const [file, ...args] = request.argv;
13
+ if (file === undefined) {
14
+ resolve({ kind: "unavailable", detail: "Empty Fetch command." });
15
+ return;
16
+ }
17
+ let settled = false;
18
+ let timedOut = false;
19
+ let interrupted = false;
20
+ let stdout = "";
21
+ let stderr = "";
22
+ let timer;
23
+ let interruptPoll;
24
+ const finish = (result) => {
25
+ if (settled) {
26
+ return;
27
+ }
28
+ settled = true;
29
+ if (timer !== undefined) {
30
+ clearTimeout(timer);
31
+ }
32
+ if (interruptPoll !== undefined) {
33
+ clearInterval(interruptPoll);
34
+ }
35
+ resolve(result);
36
+ };
37
+ let child;
38
+ try {
39
+ child = spawn(file, args, { stdio: ["ignore", "pipe", "pipe"] });
40
+ }
41
+ catch (error) {
42
+ finish({
43
+ kind: "unavailable",
44
+ detail: error instanceof Error ? error.message : String(error),
45
+ });
46
+ return;
47
+ }
48
+ child.stdout?.setEncoding("utf8");
49
+ child.stderr?.setEncoding("utf8");
50
+ child.stdout?.on("data", (chunk) => {
51
+ stdout += chunk;
52
+ });
53
+ child.stderr?.on("data", (chunk) => {
54
+ stderr += chunk;
55
+ });
56
+ child.on("error", (error) => {
57
+ finish({ kind: "unavailable", detail: error.message });
58
+ });
59
+ timer = setTimeout(() => {
60
+ timedOut = true;
61
+ kill(child);
62
+ }, Math.max(1, request.timeoutMs));
63
+ interruptPoll = setInterval(() => {
64
+ if (request.shouldInterrupt()) {
65
+ interrupted = true;
66
+ kill(child);
67
+ }
68
+ }, 20);
69
+ child.on("close", (exitCode) => {
70
+ if (interrupted || request.shouldInterrupt()) {
71
+ finish({ kind: "interrupted" });
72
+ return;
73
+ }
74
+ if (timedOut) {
75
+ finish({
76
+ kind: "unavailable",
77
+ detail: `The Fetch was killed after ${request.timeoutMs}ms.`,
78
+ });
79
+ return;
80
+ }
81
+ if (exitCode !== 0) {
82
+ finish({
83
+ kind: "unavailable",
84
+ detail: `The Fetch exited ${exitCode}. ${truncate(stderr).trim()}`.trim(),
85
+ });
86
+ return;
87
+ }
88
+ finish(readFetchStdout(stdout));
89
+ });
90
+ });
91
+ }
92
+ /** Exported for tests: the stdout contract of the Fetch, without a process. */
93
+ export function readFetchStdout(stdout) {
94
+ const trimmed = stdout.trim();
95
+ if (trimmed.length === 0) {
96
+ return { kind: "empty" };
97
+ }
98
+ let parsed;
99
+ try {
100
+ parsed = JSON.parse(trimmed);
101
+ }
102
+ catch (error) {
103
+ const detail = error instanceof Error ? error.message : String(error);
104
+ return { kind: "unavailable", detail: `The Fetch stdout is not JSON: ${detail}` };
105
+ }
106
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
107
+ return { kind: "unavailable", detail: "The Fetch stdout is not a JSON object." };
108
+ }
109
+ return { kind: "merged", object: parsed };
110
+ }
111
+ function kill(child) {
112
+ try {
113
+ child.kill("SIGKILL");
114
+ }
115
+ catch {
116
+ // already gone
117
+ }
118
+ }
119
+ //# sourceMappingURL=run-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-fetch.js","sourceRoot":"","sources":["../../../src/adapter/fetch/run-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** JSON with object keys sorted, so two equal documents hash the same. */
2
+ export declare function canonicalJson(value: unknown): string;
3
+ /**
4
+ * Answers "did this intention change?". Covers every field of the
5
+ * FeatureStandard except the two that are not the intention itself.
6
+ */
7
+ export declare function fingerprintOf(document: Record<string, unknown>): string;
8
+ //# sourceMappingURL=fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/fingerprint.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYpD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAKvE"}
@@ -0,0 +1,26 @@
1
+ import { createHash } from "node:crypto";
2
+ /** JSON with object keys sorted, so two equal documents hash the same. */
3
+ export function canonicalJson(value) {
4
+ if (value === null || typeof value !== "object") {
5
+ return JSON.stringify(value) ?? "null";
6
+ }
7
+ if (Array.isArray(value)) {
8
+ return `[${value.map(canonicalJson).join(",")}]`;
9
+ }
10
+ const entries = Object.entries(value)
11
+ .filter(([, entryValue]) => entryValue !== undefined)
12
+ .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
13
+ .map(([key, entryValue]) => `${JSON.stringify(key)}:${canonicalJson(entryValue)}`);
14
+ return `{${entries.join(",")}}`;
15
+ }
16
+ /**
17
+ * Answers "did this intention change?". Covers every field of the
18
+ * FeatureStandard except the two that are not the intention itself.
19
+ */
20
+ export function fingerprintOf(document) {
21
+ const subject = { ...document };
22
+ delete subject.fingerprint;
23
+ delete subject.normalized_at;
24
+ return `sha256:${createHash("sha256").update(canonicalJson(subject)).digest("hex")}`;
25
+ }
26
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../../src/adapter/normalize/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IACzC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACnD,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;SAC7D,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,UAAU,KAAK,SAAS,CAAC;SACpD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACrE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACrF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAiC;IAC7D,MAAM,OAAO,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzD,OAAO,OAAO,CAAC,WAAW,CAAC;IAC3B,OAAO,OAAO,CAAC,aAAa,CAAC;IAC7B,OAAO,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACvF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { NormalizeResult } from "../types.js";
2
+ export type NormalizeOptions = {
3
+ manager: string;
4
+ defaultProject?: string;
5
+ defaultPriority: number;
6
+ normalizedAt: string;
7
+ };
8
+ /**
9
+ * Turn a parsed raw intention into a FeatureStandard, or say why it cannot be
10
+ * one. Pure: no clock, no child process, no file.
11
+ *
12
+ * Checks run in a fixed order — every recognised field's type first, then the
13
+ * kind, then the fields the intent requires, then the priority scale — so one
14
+ * raw intention always produces the same code.
15
+ */
16
+ export declare function normalize(raw: Record<string, unknown>, options: NormalizeOptions): NormalizeResult;
17
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoC,eAAe,EAAE,MAAM,aAAa,CAAC;AAGrF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAsHF;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,gBAAgB,GACxB,eAAe,CA2FjB"}
@@ -0,0 +1,199 @@
1
+ import { fingerprintOf } from "./fingerprint.js";
2
+ const KIND_TO_INTENT = {
3
+ create: "upsert",
4
+ update: "upsert",
5
+ ready: "ready",
6
+ cancel: "cancel",
7
+ delete: "cancel",
8
+ };
9
+ const PRIORITY_NAMES = {
10
+ low: 25,
11
+ normal: 50,
12
+ high: 75,
13
+ urgent: 100,
14
+ };
15
+ function badType(field, value) {
16
+ return {
17
+ code: "bad-field-type",
18
+ reason: `Field "${field}" is ${describe(value)}, which this Block cannot read.`,
19
+ };
20
+ }
21
+ function describe(value) {
22
+ if (value === null) {
23
+ return "null";
24
+ }
25
+ if (Array.isArray(value)) {
26
+ return "an array";
27
+ }
28
+ return `a ${typeof value}`;
29
+ }
30
+ function readString(raw, field) {
31
+ const value = raw[field];
32
+ if (value === undefined) {
33
+ return { ok: true };
34
+ }
35
+ if (typeof value !== "string") {
36
+ return { ok: false, invalid: badType(field, value) };
37
+ }
38
+ const trimmed = value.trim();
39
+ return trimmed.length === 0 ? { ok: true } : { ok: true, value: trimmed };
40
+ }
41
+ function readIdLike(raw, field) {
42
+ const value = raw[field];
43
+ if (value === undefined) {
44
+ return { ok: true };
45
+ }
46
+ if (typeof value === "number" && Number.isFinite(value)) {
47
+ return { ok: true, value: String(value) };
48
+ }
49
+ if (typeof value !== "string") {
50
+ return { ok: false, invalid: badType(field, value) };
51
+ }
52
+ const trimmed = value.trim();
53
+ return trimmed.length === 0 ? { ok: true } : { ok: true, value: trimmed };
54
+ }
55
+ function readPriority(raw) {
56
+ const value = raw.priority;
57
+ if (value === undefined) {
58
+ return { ok: true };
59
+ }
60
+ if (typeof value === "number") {
61
+ if (!Number.isInteger(value) || value < 0 || value > 100) {
62
+ return {
63
+ ok: false,
64
+ invalid: {
65
+ code: "bad-priority",
66
+ reason: `Priority ${value} is outside the 0…100 scale.`,
67
+ },
68
+ };
69
+ }
70
+ return { ok: true, value };
71
+ }
72
+ if (typeof value !== "string") {
73
+ return { ok: false, invalid: badType("priority", value) };
74
+ }
75
+ const named = PRIORITY_NAMES[value.trim().toLowerCase()];
76
+ if (named === undefined) {
77
+ return {
78
+ ok: false,
79
+ invalid: {
80
+ code: "bad-priority",
81
+ reason: `Priority "${value}" is not one of low, normal, high, urgent.`,
82
+ },
83
+ };
84
+ }
85
+ return { ok: true, value: named };
86
+ }
87
+ function readKind(raw) {
88
+ const value = raw.kind;
89
+ if (value === undefined) {
90
+ return { ok: true, value: "upsert" };
91
+ }
92
+ if (typeof value !== "string") {
93
+ return { ok: false, invalid: badType("kind", value) };
94
+ }
95
+ const intent = KIND_TO_INTENT[value.trim().toLowerCase()];
96
+ if (intent === undefined) {
97
+ return {
98
+ ok: false,
99
+ invalid: {
100
+ code: "unknown-kind",
101
+ reason: `Kind "${value}" is not one of create, update, ready, cancel, delete.`,
102
+ },
103
+ };
104
+ }
105
+ return { ok: true, value: intent };
106
+ }
107
+ /**
108
+ * Turn a parsed raw intention into a FeatureStandard, or say why it cannot be
109
+ * one. Pure: no clock, no child process, no file.
110
+ *
111
+ * Checks run in a fixed order — every recognised field's type first, then the
112
+ * kind, then the fields the intent requires, then the priority scale — so one
113
+ * raw intention always produces the same code.
114
+ */
115
+ export function normalize(raw, options) {
116
+ const externalId = readIdLike(raw, "id");
117
+ if (!externalId.ok) {
118
+ return { ok: false, invalid: externalId.invalid };
119
+ }
120
+ const project = readString(raw, "project");
121
+ if (!project.ok) {
122
+ return { ok: false, invalid: project.invalid };
123
+ }
124
+ const title = readString(raw, "title");
125
+ if (!title.ok) {
126
+ return { ok: false, invalid: title.invalid };
127
+ }
128
+ const intention = readString(raw, "intention");
129
+ if (!intention.ok) {
130
+ return { ok: false, invalid: intention.invalid };
131
+ }
132
+ const ref = readString(raw, "url");
133
+ if (!ref.ok) {
134
+ return { ok: false, invalid: ref.invalid };
135
+ }
136
+ const revision = readIdLike(raw, "revision");
137
+ if (!revision.ok) {
138
+ return { ok: false, invalid: revision.invalid };
139
+ }
140
+ const kind = readKind(raw);
141
+ if (!kind.ok) {
142
+ return { ok: false, invalid: kind.invalid };
143
+ }
144
+ const intent = kind.value ?? "upsert";
145
+ if (externalId.value === undefined) {
146
+ return {
147
+ ok: false,
148
+ invalid: { code: "missing-id", reason: 'The raw intention carries no usable "id".' },
149
+ };
150
+ }
151
+ const resolvedProject = project.value ?? options.defaultProject;
152
+ if (resolvedProject === undefined) {
153
+ return {
154
+ ok: false,
155
+ invalid: {
156
+ code: "missing-project",
157
+ reason: 'No "project" in the raw intention and no --default-project.',
158
+ },
159
+ };
160
+ }
161
+ const resolvedIntention = intention.value ?? title.value;
162
+ if (intent === "upsert" && resolvedIntention === undefined) {
163
+ return {
164
+ ok: false,
165
+ invalid: {
166
+ code: "missing-intention",
167
+ reason: 'An upsert needs an "intention" or, failing that, a "title".',
168
+ },
169
+ };
170
+ }
171
+ const priority = readPriority(raw);
172
+ if (!priority.ok) {
173
+ return { ok: false, invalid: priority.invalid };
174
+ }
175
+ const source = {};
176
+ if (ref.value !== undefined) {
177
+ source.ref = ref.value;
178
+ }
179
+ if (revision.value !== undefined) {
180
+ source.revision = revision.value;
181
+ }
182
+ // Built in the order the FeatureStandard documents, so stdout reads top-down.
183
+ const feature = {
184
+ key: `${options.manager}:${externalId.value}`,
185
+ manager: options.manager,
186
+ external_id: externalId.value,
187
+ intent,
188
+ project: resolvedProject,
189
+ ...(title.value !== undefined ? { title: title.value } : {}),
190
+ ...(resolvedIntention !== undefined ? { intention: resolvedIntention } : {}),
191
+ priority: priority.value ?? options.defaultPriority,
192
+ ...(Object.keys(source).length > 0 ? { source } : {}),
193
+ fingerprint: "",
194
+ normalized_at: options.normalizedAt,
195
+ };
196
+ feature.fingerprint = fingerprintOf(feature);
197
+ return { ok: true, feature };
198
+ }
199
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/adapter/normalize/normalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type ProgressWriter = (line: Record<string, unknown>) => void;
2
+ export declare function createStdoutProgressWriter(): ProgressWriter;
3
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/adapter/progress/emit.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAErE,wBAAgB,0BAA0B,IAAI,cAAc,CAI3D"}
@@ -0,0 +1,6 @@
1
+ export function createStdoutProgressWriter() {
2
+ return (line) => {
3
+ process.stdout.write(`${JSON.stringify(line)}\n`);
4
+ };
5
+ }
6
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/adapter/progress/emit.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Invalid } from "../types.js";
2
+ export type ParseRawResult = {
3
+ ok: true;
4
+ object: Record<string, unknown>;
5
+ } | {
6
+ ok: false;
7
+ invalid: Invalid;
8
+ };
9
+ /**
10
+ * Structural checks on the raw intention: size, then JSON, then object.
11
+ * Nothing here looks at a field — that is normalization's job.
12
+ */
13
+ export declare function parseRaw(raw: string, maxRawBytes: number): ParseRawResult;
14
+ //# sourceMappingURL=parse-raw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-raw.d.ts","sourceRoot":"","sources":["../../../src/adapter/raw/parse-raw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,CAkCzE"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Structural checks on the raw intention: size, then JSON, then object.
3
+ * Nothing here looks at a field — that is normalization's job.
4
+ */
5
+ export function parseRaw(raw, maxRawBytes) {
6
+ const bytes = Buffer.byteLength(raw, "utf8");
7
+ if (bytes > maxRawBytes) {
8
+ return {
9
+ ok: false,
10
+ invalid: {
11
+ code: "raw-too-large",
12
+ reason: `The raw intention is ${bytes} bytes, over the ${maxRawBytes} allowed.`,
13
+ },
14
+ };
15
+ }
16
+ let parsed;
17
+ try {
18
+ parsed = JSON.parse(raw);
19
+ }
20
+ catch (error) {
21
+ const detail = error instanceof Error ? error.message : String(error);
22
+ return {
23
+ ok: false,
24
+ invalid: { code: "raw-not-json", reason: `The raw intention is not JSON: ${detail}` },
25
+ };
26
+ }
27
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
28
+ return {
29
+ ok: false,
30
+ invalid: {
31
+ code: "raw-not-object",
32
+ reason: `The raw intention parsed to ${describe(parsed)}, not an object.`,
33
+ },
34
+ };
35
+ }
36
+ return { ok: true, object: parsed };
37
+ }
38
+ function describe(value) {
39
+ if (value === null) {
40
+ return "null";
41
+ }
42
+ if (Array.isArray(value)) {
43
+ return "an array";
44
+ }
45
+ return `a ${typeof value}`;
46
+ }
47
+ //# sourceMappingURL=parse-raw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-raw.js","sourceRoot":"","sources":["../../../src/adapter/raw/parse-raw.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,WAAmB;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,KAAK,GAAG,WAAW,EAAE,CAAC;QACxB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,wBAAwB,KAAK,oBAAoB,WAAW,WAAW;aAChF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,kCAAkC,MAAM,EAAE,EAAE;SACtF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,+BAA+B,QAAQ,CAAC,MAAM,CAAC,kBAAkB;aAC1E;SACF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAiC,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,OAAO,KAAK,EAAE,CAAC;AAC7B,CAAC"}