@miadi/episodic-memory-schema 0.3.0 → 0.4.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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The chronicle catalog — a list-of-episodes zone the app `/chronicle` surface
3
+ * and forgewright read identically (jgwill/Miadi#506, #507).
4
+ *
5
+ * Filesystem-free, like the rest of this package: it observes already-collected
6
+ * per-episode inputs (a folder name, and — when the episode is structured — its
7
+ * observed `episode.yaml`) and assembles the manifest. The enumerator that walks
8
+ * the chronicle root on disk and produces these inputs lives in
9
+ * `@miadi/inquiry-weave` (`catalog.ts`); this module only shapes and validates
10
+ * what it is handed, so the app and forgewright never fork the read-side.
11
+ */
12
+ import type { CompatibilityDiagnostic, EpisodeObservation, EpisodeRelation } from "./observation.js";
13
+ /** The medicine-wheel parent every chronicle episode node hangs under. */
14
+ export declare const CHRONICLE_PARENT_NODE_ID = "chronicle:miadi-chronicle";
15
+ export declare const CHRONICLE_SERIES = "miadi-chronicle";
16
+ /**
17
+ * The medicine-wheel projection id for one episode.
18
+ * Mirrors `@miadi/inquiry-weave`'s `episodeNodeId` — the shared convention both
19
+ * the writer and the readers key on. Keyed on the folder name, never the number
20
+ * (numbers collide; folder names do not).
21
+ */
22
+ export declare function chronicleEpisodeNodeId(name: string): string;
23
+ /** One row of the chronicle catalog, as both renderers consume it. */
24
+ export interface EpisodeManifestEntry {
25
+ /** Folder basename — the true key. */
26
+ name: string;
27
+ /** Medicine-wheel node id, `chronicle:<name>`. */
28
+ nodeId: string;
29
+ /** Path relative to the chronicle root, `<name>/episode.yaml`. */
30
+ relativePath: string;
31
+ /** Episode number when parseable from the folder name; may collide. */
32
+ number?: number;
33
+ slug?: string;
34
+ date?: string;
35
+ title?: string;
36
+ status?: string;
37
+ type?: string;
38
+ /** Lineage edges (`continues_from` / `relates_to` / `branch_of`) when structured. */
39
+ relations: EpisodeRelation[];
40
+ /** True when a structured `episode.yaml` was observed (vs. name-only). */
41
+ structured: boolean;
42
+ }
43
+ /** What the enumerator collects per folder before manifest assembly. */
44
+ export interface ChronicleManifestEntryInput {
45
+ name: string;
46
+ number?: number;
47
+ slug?: string;
48
+ date?: string;
49
+ /** Present when the episode carried a structured `episode.yaml`. */
50
+ observation?: EpisodeObservation;
51
+ }
52
+ export interface ChronicleManifest {
53
+ zone: "chronicle";
54
+ series: string;
55
+ /** Medicine-wheel parent node id all entries hang under. */
56
+ parentNodeId: string;
57
+ generatedAt?: string;
58
+ episodes: EpisodeManifestEntry[];
59
+ diagnostics: CompatibilityDiagnostic[];
60
+ }
61
+ export interface ObserveChronicleManifestOptions {
62
+ series?: string;
63
+ parentNodeId?: string;
64
+ /** When provided, stamps `generatedAt`; omit for a deterministic manifest. */
65
+ now?: () => Date;
66
+ }
67
+ /**
68
+ * Assemble a ChronicleManifest from per-episode inputs.
69
+ *
70
+ * Non-destructive and compatibility-first: name-only episodes (the older
71
+ * `script.md` era) are catalogued alongside structured ones; observation
72
+ * diagnostics are lifted and path-scoped; number collisions are reported as an
73
+ * `info` diagnostic, never dropped. Output is ordered by folder name so the
74
+ * manifest is stable across runs.
75
+ */
76
+ export declare function observeChronicleManifest(inputs: readonly ChronicleManifestEntryInput[], options?: ObserveChronicleManifestOptions): ChronicleManifest;
77
+ //# sourceMappingURL=chronicle-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chronicle-manifest.d.ts","sourceRoot":"","sources":["../src/chronicle-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAEzB,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,8BAA8B,CAAA;AACnE,eAAO,MAAM,gBAAgB,oBAAoB,CAAA;AAEjD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACnC,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAA;IACpB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,SAAS,EAAE,eAAe,EAAE,CAAA;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,wEAAwE;AACxE,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,WAAW,CAAC,EAAE,kBAAkB,CAAA;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,oBAAoB,EAAE,CAAA;IAChC,WAAW,EAAE,uBAAuB,EAAE,CAAA;CACvC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CACjB;AAOD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,2BAA2B,EAAE,EAC9C,OAAO,GAAE,+BAAoC,GAC5C,iBAAiB,CAwDnB"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The chronicle catalog — a list-of-episodes zone the app `/chronicle` surface
3
+ * and forgewright read identically (jgwill/Miadi#506, #507).
4
+ *
5
+ * Filesystem-free, like the rest of this package: it observes already-collected
6
+ * per-episode inputs (a folder name, and — when the episode is structured — its
7
+ * observed `episode.yaml`) and assembles the manifest. The enumerator that walks
8
+ * the chronicle root on disk and produces these inputs lives in
9
+ * `@miadi/inquiry-weave` (`catalog.ts`); this module only shapes and validates
10
+ * what it is handed, so the app and forgewright never fork the read-side.
11
+ */
12
+ /** The medicine-wheel parent every chronicle episode node hangs under. */
13
+ export const CHRONICLE_PARENT_NODE_ID = "chronicle:miadi-chronicle";
14
+ export const CHRONICLE_SERIES = "miadi-chronicle";
15
+ /**
16
+ * The medicine-wheel projection id for one episode.
17
+ * Mirrors `@miadi/inquiry-weave`'s `episodeNodeId` — the shared convention both
18
+ * the writer and the readers key on. Keyed on the folder name, never the number
19
+ * (numbers collide; folder names do not).
20
+ */
21
+ export function chronicleEpisodeNodeId(name) {
22
+ return `chronicle:${name}`;
23
+ }
24
+ function readStringField(fields, key) {
25
+ const value = fields[key];
26
+ return typeof value === "string" && value.trim() !== "" ? value : undefined;
27
+ }
28
+ /**
29
+ * Assemble a ChronicleManifest from per-episode inputs.
30
+ *
31
+ * Non-destructive and compatibility-first: name-only episodes (the older
32
+ * `script.md` era) are catalogued alongside structured ones; observation
33
+ * diagnostics are lifted and path-scoped; number collisions are reported as an
34
+ * `info` diagnostic, never dropped. Output is ordered by folder name so the
35
+ * manifest is stable across runs.
36
+ */
37
+ export function observeChronicleManifest(inputs, options = {}) {
38
+ const series = options.series ?? CHRONICLE_SERIES;
39
+ const parentNodeId = options.parentNodeId ?? CHRONICLE_PARENT_NODE_ID;
40
+ const diagnostics = [];
41
+ const episodes = inputs.map((input) => {
42
+ const obs = input.observation;
43
+ const entry = {
44
+ name: input.name,
45
+ nodeId: chronicleEpisodeNodeId(input.name),
46
+ relativePath: `${input.name}/episode.yaml`,
47
+ number: input.number,
48
+ slug: input.slug,
49
+ date: input.date ?? obs?.sourceMetadata.date,
50
+ title: obs?.sourceMetadata.title,
51
+ status: obs?.sourceMetadata.status,
52
+ type: obs ? readStringField(obs.unmappedFields, "type") : undefined,
53
+ relations: obs?.relations ?? [],
54
+ structured: obs !== undefined,
55
+ };
56
+ if (obs) {
57
+ for (const d of obs.diagnostics) {
58
+ diagnostics.push({ ...d, path: d.path ?? input.name });
59
+ }
60
+ }
61
+ return entry;
62
+ });
63
+ const byNumber = new Map();
64
+ for (const e of episodes) {
65
+ if (e.number === undefined)
66
+ continue;
67
+ const names = byNumber.get(e.number) ?? [];
68
+ names.push(e.name);
69
+ byNumber.set(e.number, names);
70
+ }
71
+ for (const [num, names] of byNumber) {
72
+ if (names.length > 1) {
73
+ diagnostics.push({
74
+ level: "info",
75
+ code: "chronicle.episode-number-collision",
76
+ message: `episode number ${num} is shared by ${names.length} folders; the folder name is the key (${names.join(", ")})`,
77
+ });
78
+ }
79
+ }
80
+ episodes.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
81
+ const manifest = {
82
+ zone: "chronicle",
83
+ series,
84
+ parentNodeId,
85
+ episodes,
86
+ diagnostics,
87
+ };
88
+ if (options.now)
89
+ manifest.generatedAt = options.now().toISOString();
90
+ return manifest;
91
+ }
92
+ //# sourceMappingURL=chronicle-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chronicle-manifest.js","sourceRoot":"","sources":["../src/chronicle-manifest.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./types.js";
2
2
  export * from "./narrative.js";
3
3
  export * from "./observation.js";
4
+ export * from "./chronicle-manifest.js";
4
5
  export * from "./adapters/composition.js";
5
6
  export * from "./adapters/episode-yaml.js";
6
7
  export * from "./adapters/directory.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AAEvC;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,GACb,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AAEvC;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,GACb,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./types.js";
2
2
  export * from "./narrative.js";
3
3
  export * from "./observation.js";
4
+ export * from "./chronicle-manifest.js";
4
5
  export * from "./adapters/composition.js";
5
6
  export * from "./adapters/episode-yaml.js";
6
7
  export * from "./adapters/directory.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AAEvC;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,GACb,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AAEvC;;;;GAIG;AACH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,GACb,MAAM,sBAAsB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miadi/episodic-memory-schema",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript types and JSON Schema for episodic memory — the durable session-to-session memory layer in the Miadi orchestration kit. Narrative layer is NCP-aligned; provenance layer is W3C PROV-DM and OAIS-informed.",
5
5
  "keywords": [
6
6
  "miadi",