@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.
- package/README.md +58 -0
- package/SPECS.md +65 -0
- package/dist/adapter/fetch/run-fetch.d.ts +24 -0
- package/dist/adapter/fetch/run-fetch.d.ts.map +1 -0
- package/dist/adapter/fetch/run-fetch.js +119 -0
- package/dist/adapter/fetch/run-fetch.js.map +1 -0
- package/dist/adapter/normalize/fingerprint.d.ts +8 -0
- package/dist/adapter/normalize/fingerprint.d.ts.map +1 -0
- package/dist/adapter/normalize/fingerprint.js +26 -0
- package/dist/adapter/normalize/fingerprint.js.map +1 -0
- package/dist/adapter/normalize/normalize.d.ts +17 -0
- package/dist/adapter/normalize/normalize.d.ts.map +1 -0
- package/dist/adapter/normalize/normalize.js +199 -0
- package/dist/adapter/normalize/normalize.js.map +1 -0
- package/dist/adapter/progress/emit.d.ts +3 -0
- package/dist/adapter/progress/emit.d.ts.map +1 -0
- package/dist/adapter/progress/emit.js +6 -0
- package/dist/adapter/progress/emit.js.map +1 -0
- package/dist/adapter/raw/parse-raw.d.ts +14 -0
- package/dist/adapter/raw/parse-raw.d.ts.map +1 -0
- package/dist/adapter/raw/parse-raw.js +47 -0
- package/dist/adapter/raw/parse-raw.js.map +1 -0
- package/dist/adapter/run/run-adapter.d.ts +25 -0
- package/dist/adapter/run/run-adapter.d.ts.map +1 -0
- package/dist/adapter/run/run-adapter.js +125 -0
- package/dist/adapter/run/run-adapter.js.map +1 -0
- package/dist/adapter/types.d.ts +51 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/types.js +3 -0
- package/dist/adapter/types.js.map +1 -0
- package/dist/emitter/event/field-matrix.d.ts +29 -0
- package/dist/emitter/event/field-matrix.d.ts.map +1 -0
- package/dist/emitter/event/field-matrix.js +93 -0
- package/dist/emitter/event/field-matrix.js.map +1 -0
- package/dist/emitter/progress/emit.d.ts +3 -0
- package/dist/emitter/progress/emit.d.ts.map +1 -0
- package/dist/emitter/progress/emit.js +6 -0
- package/dist/emitter/progress/emit.js.map +1 -0
- package/dist/emitter/render/render-event.d.ts +14 -0
- package/dist/emitter/render/render-event.d.ts.map +1 -0
- package/dist/emitter/render/render-event.js +116 -0
- package/dist/emitter/render/render-event.js.map +1 -0
- package/dist/emitter/render/truncate.d.ts +9 -0
- package/dist/emitter/render/truncate.d.ts.map +1 -0
- package/dist/emitter/render/truncate.js +10 -0
- package/dist/emitter/render/truncate.js.map +1 -0
- package/dist/emitter/run/run-emitter.d.ts +21 -0
- package/dist/emitter/run/run-emitter.d.ts.map +1 -0
- package/dist/emitter/run/run-emitter.js +89 -0
- package/dist/emitter/run/run-emitter.js.map +1 -0
- package/dist/emitter/thread/slug.d.ts +7 -0
- package/dist/emitter/thread/slug.d.ts.map +1 -0
- package/dist/emitter/thread/slug.js +18 -0
- package/dist/emitter/thread/slug.js.map +1 -0
- package/dist/emitter/thread/thread.d.ts +32 -0
- package/dist/emitter/thread/thread.d.ts.map +1 -0
- package/dist/emitter/thread/thread.js +58 -0
- package/dist/emitter/thread/thread.js.map +1 -0
- package/dist/emitter/types.d.ts +45 -0
- package/dist/emitter/types.d.ts.map +1 -0
- package/dist/emitter/types.js +3 -0
- package/dist/emitter/types.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/listener/delivery/run-hook.d.ts +8 -0
- package/dist/listener/delivery/run-hook.d.ts.map +1 -0
- package/dist/listener/delivery/run-hook.js +50 -0
- package/dist/listener/delivery/run-hook.js.map +1 -0
- package/dist/listener/progress/emit.d.ts +3 -0
- package/dist/listener/progress/emit.d.ts.map +1 -0
- package/dist/listener/progress/emit.js +6 -0
- package/dist/listener/progress/emit.js.map +1 -0
- package/dist/listener/run/run-listener.d.ts +31 -0
- package/dist/listener/run/run-listener.d.ts.map +1 -0
- package/dist/listener/run/run-listener.js +173 -0
- package/dist/listener/run/run-listener.js.map +1 -0
- package/dist/listener/source/list-source.d.ts +13 -0
- package/dist/listener/source/list-source.d.ts.map +1 -0
- package/dist/listener/source/list-source.js +35 -0
- package/dist/listener/source/list-source.js.map +1 -0
- package/dist/listener/source/read-event.d.ts +7 -0
- package/dist/listener/source/read-event.d.ts.map +1 -0
- package/dist/listener/source/read-event.js +47 -0
- package/dist/listener/source/read-event.js.map +1 -0
- package/dist/listener/source/select-events.d.ts +13 -0
- package/dist/listener/source/select-events.d.ts.map +1 -0
- package/dist/listener/source/select-events.js +23 -0
- package/dist/listener/source/select-events.js.map +1 -0
- package/dist/listener/types.d.ts +42 -0
- package/dist/listener/types.d.ts.map +1 -0
- package/dist/listener/types.js +3 -0
- package/dist/listener/types.js.map +1 -0
- package/dist/manager.d.ts +17 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +114 -0
- package/dist/manager.js.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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"}
|