@agentskit/doc-bridge 1.10.0 → 1.10.1

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.
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "doc-bridge",
4
4
  "display_name": "Doc Bridge",
5
- "version": "1.10.0",
5
+ "version": "1.10.1",
6
6
  "description": "Deterministic repository handoffs for coding agents, running locally without an LLM or API key.",
7
7
  "long_description": "Doc Bridge turns a repository's own documentation and ownership metadata into deterministic handoffs: where an agent should start, which paths it may edit, which checks it must run, and when a human must take over. The local connector exposes the same read-only contract available through Doc Bridge CLI and CI.",
8
8
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentskit/doc-bridge",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "mcpName": "io.github.AgentsKit-io/doc-bridge",
5
5
  "description": "Human↔agent documentation bridge — deterministic handoffs, doc-site links, memory→docs, optional AgentsKit RAG/chat.",
6
6
  "type": "module",
@@ -3,7 +3,7 @@
3
3
  import { spawnSync } from 'node:child_process'
4
4
  import { isAbsolute } from 'node:path'
5
5
 
6
- const VERSION = '1.10.0'
6
+ const VERSION = '1.10.1'
7
7
  const kinds = new Set(['package', 'ownership'])
8
8
  const args = process.argv.slice(2)
9
9
  const id = args[0]
package/src/index.ts CHANGED
@@ -104,6 +104,7 @@ export {
104
104
  RETRIEVAL_PROJECTION_VERSION,
105
105
  projectRetrievalIndex,
106
106
  relationConfidence,
107
+ snapshotObservationHash,
107
108
  toKnowledgeEntry,
108
109
  weakerConfidence,
109
110
  type CuratedDocument,
@@ -37,7 +37,7 @@ import { resolveSearchParams, resolveSearchWeights } from './weights.js'
37
37
  * from what the snapshot says about it rather than from what is on disk now.
38
38
  */
39
39
 
40
- export const RETRIEVAL_PROJECTION_VERSION = 1 as const
40
+ export const RETRIEVAL_PROJECTION_VERSION = 2 as const
41
41
 
42
42
  /** Documentation body kept for search. Long enough to answer a question, short enough to ship. */
43
43
  export const DOCUMENT_BODY_LIMIT = 4_000
@@ -51,6 +51,31 @@ const MAX_SUMMARY = 400
51
51
  /** The overlay hash when there is no overlay: the hash of an empty accepted set. */
52
52
  export const EMPTY_OVERLAY_HASH = sha256NormalizedV1({ accepted: [] })
53
53
 
54
+ /**
55
+ * What the snapshot observed, without the revision it observed it at.
56
+ *
57
+ * `snapshot.contentHash` seals the whole artifact, `sourceRevision` included — the commit SHA when
58
+ * the working tree is clean, a digest of the scanned files when it is not. That is right for an
59
+ * artifact whose job is to say what one revision looked like, and wrong as a projection input: the
60
+ * projection is a function of what was found, not of where it was found. Sealing the revision into
61
+ * it made an index that any commit invalidates without one thing it describes having changed — so
62
+ * an index committed to a repository was stale the moment it landed, because landing it is a
63
+ * commit, and a freshness gate could never pass twice.
64
+ *
65
+ * Entities and relations are the projection's whole input; the analyzer identity comes with them,
66
+ * because two analyzer versions that observe the same entities and relations have nothing left to
67
+ * disagree about, and one that observes different ones is caught by the entities.
68
+ */
69
+ export const snapshotObservationHash = (
70
+ snapshot: Pick<DiscoverySnapshotV1, 'entities' | 'relations' | 'pipelineVersion' | 'analyzerVersions'>,
71
+ ): string =>
72
+ sha256NormalizedV1({
73
+ pipelineVersion: snapshot.pipelineVersion,
74
+ analyzerVersions: snapshot.analyzerVersions,
75
+ entities: snapshot.entities,
76
+ relations: snapshot.relations,
77
+ })
78
+
54
79
  const CONFIDENCE_RANK: Readonly<Record<Confidence, number>> = { observed: 0, declared: 1, fuzzy: 2, proposed: 3 }
55
80
 
56
81
  /** The weaker of two confidences: a chain is as trustworthy as its least trustworthy link. */
@@ -115,7 +140,7 @@ export type RetrievalOverlayInput = {
115
140
  }
116
141
 
117
142
  export type ProjectRetrievalOptions = {
118
- readonly snapshot: Pick<DiscoverySnapshotV1, 'contentHash' | 'entities' | 'relations'>
143
+ readonly snapshot: Pick<DiscoverySnapshotV1, 'contentHash' | 'entities' | 'relations' | 'pipelineVersion' | 'analyzerVersions'>
119
144
  readonly config: DocBridgeConfigV1 | undefined
120
145
  readonly routes?: RetrievalRoutes
121
146
  readonly curated?: readonly CuratedDocument[]
@@ -459,13 +484,15 @@ export const projectRetrievalIndex = (options: ProjectRetrievalOptions): Retriev
459
484
  entries,
460
485
  }
461
486
  /*
462
- * The hash is over the inputs, not the output: the projection is a function, so three equal
463
- * input hashes mean an equal artifact, and a reader checking freshness compares three hashes
464
- * instead of re-projecting.
487
+ * The hash is over the inputs, not the output: the projection is a function, so equal input
488
+ * hashes mean an equal artifact, and a reader checking freshness compares hashes instead of
489
+ * re-projecting. `snapshotHash` stays on the artifact as provenance — which snapshot this came
490
+ * from — but the seal uses the observation, so the same repository projects to the same hash
491
+ * whatever revision it was scanned at.
465
492
  */
466
493
  const contentHash = sha256NormalizedV1({
467
494
  projectionVersion: RETRIEVAL_PROJECTION_VERSION,
468
- snapshotHash: base.snapshotHash,
495
+ observationHash: snapshotObservationHash(snapshot),
469
496
  overlayHash: base.overlayHash,
470
497
  configurationHash: base.configurationHash,
471
498
  lexiconVersion: base.lexiconVersion,
@@ -136,8 +136,13 @@ export const RetrievalIndexV1Schema = z
136
136
  schemaVersion: z.literal(RETRIEVAL_INDEX_SCHEMA_VERSION),
137
137
  contentHash: hash,
138
138
  contentHashAlgo: z.literal('sha256-normalized-v1'),
139
- /** The three inputs the projection is a function of. Same three hashes, same projection. */
139
+ /**
140
+ * Which snapshot this was projected from. Provenance, not a seal input: it carries the
141
+ * snapshot's `sourceRevision`, and the projection is a function of what the snapshot observed
142
+ * rather than of the revision it was observed at.
143
+ */
140
144
  snapshotHash: hash,
145
+ /** The inputs the projection is a function of. Same hashes, same projection. */
141
146
  overlayHash: hash,
142
147
  configurationHash: hash,
143
148
  lexiconVersion: z.number().int().nonnegative().max(1_000),
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = '1.10.0'
1
+ export const PACKAGE_VERSION = '1.10.1'