@agentskit/doc-bridge 1.9.0 → 1.10.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.
@@ -478,6 +478,8 @@ areas?: {
478
478
  depth?: number
479
479
  /** Directories that contain areas rather than being one. */
480
480
  roots?: string[]
481
+ /** Glob patterns for directories that hold code without being a unit of architecture. */
482
+ exclude?: string[]
481
483
  }
482
484
  ```
483
485
 
@@ -486,8 +488,16 @@ modules. `src` is not an area in any useful sense; `src/query` is. So `roots` na
486
488
  directories that hold areas — by default `src`, `lib`, `app`, `source`, `server`, `client`,
487
489
  `packages`, `apps` — and `depth` says how many levels below such a root an area sits.
488
490
 
491
+ `exclude` names what the convention gets wrong in the other direction. A monorepo where every
492
+ package keeps `tests/` and `fixtures/` beside `src/` derives an area per directory, and
493
+ connectivity then asks for a document about a folder of test data — on one 26-package monorepo,
494
+ 43 of 81 undocumented areas were exactly that. A candidate matching an exclude pattern is not
495
+ derived, and its modules fall to the most specific area that still encloses them, or to none,
496
+ which is the honest answer for a folder of fixtures.
497
+
489
498
  Areas are derived, never declared, with one exception that matters: **any path an ownership record
490
- names becomes an area**, whatever the convention says. A configuration that reads
499
+ names becomes an area**, whatever the convention says — including a path `exclude` matches, because
500
+ a person saying a directory is a unit outranks a pattern saying it is not. A configuration that reads
491
501
  `path: "src/mcp"` is a human stating that the directory is a unit, and the graph should have an
492
502
  entity for it. Such an area carries `metadata.ownershipId`, which is what lets an agent document
493
503
  declaring `id` plus `editRoot` resolve to the thing it owns.
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "doc-bridge",
4
4
  "display_name": "Doc Bridge",
5
- "version": "1.9.0",
5
+ "version": "1.10.0",
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.9.0",
3
+ "version": "1.10.0",
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",
@@ -123,28 +123,28 @@
123
123
  },
124
124
  "devDependencies": {
125
125
  "@agentskit/chat": "0.4.1",
126
- "@agentskit/core": "1.12.8",
126
+ "@agentskit/core": "1.12.9",
127
127
  "@agentskit/ink": "0.10.9",
128
128
  "@agentskit/react": "0.8.3",
129
129
  "@anthropic-ai/mcpb": "2.1.2",
130
130
  "@changesets/cli": "^3.0.1",
131
131
  "@lhci/cli": "^0.15.1",
132
- "@playwright/test": "1.62.1",
132
+ "@playwright/test": "1.63.0",
133
133
  "@tailwindcss/postcss": "4.3.3",
134
134
  "@types/mdast": "^4.0.4",
135
135
  "@types/node": "^26.4.0",
136
- "@types/react": "19.2.18",
137
- "@types/react-dom": "19.2.5",
136
+ "@types/react": "19.3.0",
137
+ "@types/react-dom": "19.3.0",
138
138
  "@vitest/coverage-v8": "4.1.11",
139
139
  "esbuild": "^0.28.2",
140
- "fumadocs-core": "16.15.4",
140
+ "fumadocs-core": "16.15.10",
141
141
  "fumadocs-mdx": "15.4.0",
142
- "fumadocs-ui": "16.15.4",
143
- "lucide-react": "1.38.0",
144
- "next": "16.3.3",
142
+ "fumadocs-ui": "16.15.10",
143
+ "lucide-react": "1.45.0",
144
+ "next": "16.3.5",
145
145
  "proxy-agent": "8.0.2",
146
- "react": "19.2.8",
147
- "react-dom": "19.2.8",
146
+ "react": "19.3.0",
147
+ "react-dom": "19.3.0",
148
148
  "tailwindcss": "4.3.3",
149
149
  "tsup": "^8.5.0",
150
150
  "vitest": "^4.1.11"
@@ -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.9.0'
6
+ const VERSION = '1.10.0'
7
7
  const kinds = new Set(['package', 'ownership'])
8
8
  const args = process.argv.slice(2)
9
9
  const id = args[0]
@@ -249,12 +249,21 @@ export const AnalysisConfigSchema = z
249
249
  /**
250
250
  * How code areas are derived — the unit of architecture between a package and a file.
251
251
  * `roots` names directories that contain areas rather than being one (`src` holds
252
- * `src/query`); `depth` is how many levels below such a root an area sits.
252
+ * `src/query`); `depth` is how many levels below such a root an area sits; `exclude`
253
+ * names directories that hold code without being a unit of architecture.
253
254
  */
254
255
  areas: z
255
256
  .object({
256
257
  depth: z.number().int().min(1).max(8).optional(),
257
258
  roots: z.array(z.string().min(1).max(128)).max(32).optional(),
259
+ /**
260
+ * Glob patterns for directories that are not areas. A monorepo where every package
261
+ * keeps `tests/` and `fixtures/` beside `src/` derives one area per directory, and
262
+ * then connectivity asks for a document about a folder of test data. An ownership
263
+ * record naming an excluded path still makes it an area: a person saying a directory
264
+ * is a unit outranks a pattern saying it is not.
265
+ */
266
+ exclude: z.array(z.string().min(1).max(256)).max(64).optional(),
258
267
  })
259
268
  .strict()
260
269
  .optional(),
@@ -1,3 +1,5 @@
1
+ import { minimatch } from 'minimatch'
2
+
1
3
  import { toPosix } from '../lib/paths.js'
2
4
  import { entityId } from './identity.js'
3
5
 
@@ -58,6 +60,15 @@ export type DeriveAreasOptions = {
58
60
  readonly ownership?: readonly AreaOwnership[]
59
61
  readonly depth?: number
60
62
  readonly roots?: readonly string[]
63
+ /**
64
+ * Glob patterns for directories that hold code without being a unit of architecture.
65
+ *
66
+ * A candidate that matches is not derived as an area, and its modules fall to the most
67
+ * specific area that still encloses them — or to none, which is the honest answer for a
68
+ * folder of fixtures. An ownership record naming the same path still wins: a person saying
69
+ * a directory is a unit outranks a pattern saying it is not.
70
+ */
71
+ readonly exclude?: readonly string[]
61
72
  }
62
73
 
63
74
  /*
@@ -124,11 +135,15 @@ export const deriveAreas = (options: DeriveAreasOptions): readonly DerivedArea[]
124
135
  const roots = options.roots ?? [...DEFAULT_AREA_ROOTS]
125
136
  const ownership = (options.ownership ?? []).map((record) => ({ ...record, path: normalize(record.path) }))
126
137
 
138
+ const excluded = options.exclude ?? []
139
+ const isExcluded = (path: string): boolean =>
140
+ excluded.some((pattern) => minimatch(path, pattern, { dot: true }))
141
+
127
142
  /** Candidate path to the package it belongs to. */
128
143
  const candidates = new Map<string, string>()
129
144
  for (const module of options.modules) {
130
145
  const path = conventionalAreaPath(module, depth, roots)
131
- if (path && !candidates.has(path)) candidates.set(path, module.packageId)
146
+ if (path && !candidates.has(path) && !isExcluded(path)) candidates.set(path, module.packageId)
132
147
  }
133
148
  // An ownership record naming a directory that holds observed code is an area by declaration.
134
149
  for (const record of ownership) {
@@ -648,6 +648,7 @@ export const discoverRepository = (opts: DiscoveryOptions = {}): DiscoverySnapsh
648
648
  ownership: Object.entries(opts.config?.routing?.options?.ownership ?? {}).map(([id, record]) => ({ id, path: record.path })),
649
649
  ...(opts.config?.analysis?.areas?.depth !== undefined ? { depth: opts.config.analysis.areas.depth } : {}),
650
650
  ...(opts.config?.analysis?.areas?.roots !== undefined ? { roots: opts.config.analysis.areas.roots } : {}),
651
+ ...(opts.config?.analysis?.areas?.exclude !== undefined ? { exclude: opts.config.analysis.areas.exclude } : {}),
651
652
  })
652
653
  const areasById = new Map(areas.map((area) => [area.id, area]))
653
654
  const areasByPath = new Map(areas.map((area) => [area.path, area.id]))
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = '1.9.0'
1
+ export const PACKAGE_VERSION = '1.10.0'