@stravica-ai/digital-operator-pa 0.1.30 → 0.1.31

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.
@@ -90,21 +90,37 @@ export function guessKindFromPath(sourcePath) {
90
90
  }
91
91
 
92
92
  /**
93
- * Build a `knowledge.observation.staged` envelope for a staging file.
94
- * The payload carries `path` (destination hint — the worker's apply
95
- * function decides the actual write path) and the raw markdown body.
96
- * `frontmatter` is left absent; the worker parses it if present in the
97
- * body.
93
+ * Build an EventInput envelope for one file.
94
+ *
95
+ * The envelope construction is uniform across every kind (clientEventId,
96
+ * occurredAt, producer, tier, provenance, contentSha). Only the
97
+ * `payload` sub-object is per-kind: `knowledge.doc.delete` carries
98
+ * `{path, source?}` (deletion — no content field; the ingest schema
99
+ * refuses `content` as an additionalProperty for this kind, spec §3.1 +
100
+ * `remote-library` `src/schema/payloads.ts`), while every other kind
101
+ * currently ships as `{path, content}` (content-bearing). This mapping
102
+ * is intentionally narrow: only the delete branch differs. Every
103
+ * non-delete kind's payload shape is preserved byte-for-byte from the
104
+ * pre-cure encoding, so nothing else can regress (asserted by the
105
+ * envelope regression test).
106
+ *
107
+ * For the `knowledge.observation.staged` default the payload carries
108
+ * `path` (destination hint — the worker's apply function decides the
109
+ * actual write path) and the raw markdown body. `frontmatter` is left
110
+ * absent; the worker parses it if present in the body.
98
111
  *
99
112
  * @param {object} args
100
113
  * @param {string} args.repoRoot
101
114
  * @param {string} args.sourcePath absolute or repo-relative
102
- * @param {string} args.content
115
+ * @param {string} [args.content] ignored for `knowledge.doc.delete`
103
116
  * @param {object} args.producer { operator, agent, host?, session?, subkeyId }
104
117
  * @param {string} [args.kind] overrides guess; must be in KNOWN_KINDS
105
118
  * @param {string} [args.tier] default "auto" sentinel (spec §2.3)
106
119
  * @param {'staging'|'flush'|'role-output'|'manual'|'synthesis'} [args.sourceKind]
107
120
  * default "manual"; `library flush` passes "flush"
121
+ * @param {string} [args.source] optional routing hint; only encoded
122
+ * into the payload for `knowledge.doc.delete` (mirrors the schema's
123
+ * optional `source` field for the delete kind — spec §3.1 shape).
108
124
  * @param {() => Date} [args.clock] test seam
109
125
  * @returns {object} EventInput ready for POST /events
110
126
  */
@@ -116,6 +132,7 @@ export function buildEnvelope({
116
132
  kind,
117
133
  tier = 'auto',
118
134
  sourceKind = 'manual',
135
+ source,
119
136
  clock = () => new Date(),
120
137
  }) {
121
138
  // Repo-relative resolution + refusal for anything that would encode as
@@ -152,10 +169,27 @@ export function buildEnvelope({
152
169
  }
153
170
 
154
171
  const now = clock();
155
- const payload = {
156
- path: relPath ?? null,
157
- content,
158
- };
172
+ // Per-kind payload construction (spec §3.1 + `remote-library` payload
173
+ // schema). Fix Wave E (w-2026-08-24-dave-029): before this branch the
174
+ // envelope encoded `{path, content}` for every kind, and the ingest
175
+ // schema for `knowledge.doc.delete` refused the `content` key with
176
+ // 422 (additionalProperties:false, required=["path"]). Result: the
177
+ // delete verb structurally could not succeed via the CLI — the same
178
+ // deferred-defect class the retirement programme is here to close.
179
+ // The delete branch omits `content` and (optionally) attaches
180
+ // `source`. Every other kind keeps the pre-cure `{path, content}`
181
+ // shape byte-for-byte; the regression test in envelope.test.mjs
182
+ // asserts that determinism against a frozen contentSha.
183
+ const payload =
184
+ resolvedKind === 'knowledge.doc.delete'
185
+ ? {
186
+ path: relPath ?? null,
187
+ ...(source !== undefined ? { source } : {}),
188
+ }
189
+ : {
190
+ path: relPath ?? null,
191
+ content,
192
+ };
159
193
 
160
194
  const envelope = {
161
195
  clientEventId: randomUUID(),
@@ -26,7 +26,14 @@ export async function runPut({ config, args, fetchImpl, log = defaultLog }) {
26
26
  log('usage: library put <path> [--kind <kind>] [--tier auto|<tier>]');
27
27
  return 1;
28
28
  }
29
- const content = await readFile(path, 'utf8');
29
+ // Delete events carry no content by spec (§3.1 payload schema); the
30
+ // operator can and typically will have removed the file locally before
31
+ // asking the tier remote to catch up. Reading a file that does not
32
+ // exist would be a spurious ENOENT — so we skip the read entirely for
33
+ // delete. Every other kind still reads the file to populate
34
+ // payload.content. Fix Wave E (w-2026-08-24-dave-029) partner cure to
35
+ // the envelope kind-aware branch.
36
+ const content = kind === 'knowledge.doc.delete' ? undefined : await readFile(path, 'utf8');
30
37
 
31
38
  const producer = producerFromPreferences(config);
32
39
  const envelope = buildEnvelope({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stravica-ai/digital-operator-pa",
3
- "version": "0.1.30",
3
+ "version": "0.1.31",
4
4
  "description": "Digital Operator PA \u2014 single-bundled public package surface (bins + library) for the platform.",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",