@inflexa-ai/harness 0.7.0 → 0.7.2

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.
@@ -8,10 +8,20 @@
8
8
  * `runs/{priorRunId}/...`) so `classifyReadPath` and the collector's
9
9
  * `stepPrefix` normalization see the shapes they expect.
10
10
  *
11
+ * A read naming a same-run sibling this step never declared is refused here,
12
+ * before it reaches the collector: a ref the collector never holds cannot
13
+ * become an attestation target, so the edge is unrepresentable rather than
14
+ * merely filtered downstream. Each refused path is logged once per step — an
15
+ * edge asserted over a step that was still writing is invisible by nature, so a
16
+ * silent drop would rebuild exactly the blind spot the refusal exists to close,
17
+ * while re-narrating a path already reported adds no fact and buries the rest.
18
+ *
11
19
  * Degrades safely: a disabled or absent frame records the command with no
12
- * inputs and no writes (its outputs fall back to leaves at registration).
13
- * It never throws — provenance is best-effort and must not fail an exec.
20
+ * inputs and no writes (its outputs fall back to leaves at registration), and a
21
+ * frame whose every read is refused still records its command. It never throws —
22
+ * provenance is best-effort and must not fail an exec.
14
23
  */
24
+ import { createNoopLogger } from "../lib/console-logger.js";
15
25
  import { classifyReadPath } from "./collector.js";
16
26
  /**
17
27
  * Strip the `/{resourceId}/` mount prefix from an absolute frame path.
@@ -40,11 +50,24 @@ export function feedExecFrame(args) {
40
50
  collector.recordCommandExecution(cmd, [...cmdArgs], code, duration, [], undefined, []);
41
51
  return;
42
52
  }
53
+ // Resolved once so the read loop logs unconditionally instead of threading
54
+ // `?.` through every diagnostic.
55
+ const logger = (args.logger ?? createNoopLogger()).named("exec-frame");
43
56
  const commandReads = [];
44
57
  for (const read of provenance.reads) {
45
58
  const rel = stripMountPrefix(mountRoot, read.path);
46
- const context = classifyReadPath(rel, collector.stepId, collector.runId, collector.dependsOn);
47
- commandReads.push(collector.trackInputAccess(mountRoot, rel, null, context));
59
+ const classification = classifyReadPath(rel, collector.stepId, collector.runId, collector.dependsOn);
60
+ if (!classification.admissible) {
61
+ if (collector.claimRefusalNarration(rel)) {
62
+ logger.warn("refusing lineage edge to an undeclared same-run path", {
63
+ path: rel,
64
+ refRunId: classification.refRunId,
65
+ refStepId: classification.refStepId,
66
+ });
67
+ }
68
+ continue;
69
+ }
70
+ commandReads.push(collector.trackInputAccess(mountRoot, rel, null, classification.context));
48
71
  }
49
72
  const writes = provenance.writes.map((w) => ({
50
73
  path: stripMountPrefix(mountRoot, w.path),