docbridge 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.
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "docbridge",
3
+ "version": "0.4.0",
4
+ "description": "A Bun CLI that links Markdown specifications and code declarations.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "docbridge": "./dist/index.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/salan70/docbridge.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/salan70/docbridge/issues"
16
+ },
17
+ "homepage": "https://github.com/salan70/docbridge#readme",
18
+ "keywords": [
19
+ "documentation",
20
+ "markdown",
21
+ "specification",
22
+ "cli",
23
+ "bun",
24
+ "lsp"
25
+ ],
26
+ "engines": {
27
+ "bun": ">=1.1.31"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "schemas",
32
+ "templates/skills",
33
+ "README.md",
34
+ "CHANGELOG.md",
35
+ "LICENSE"
36
+ ],
37
+ "scripts": {
38
+ "docbridge": "bun run src/cli/index.ts",
39
+ "check": "bun run src/cli/index.ts check",
40
+ "check:example": "bun run src/cli/index.ts check --root examples/typescript",
41
+ "test": "bun test",
42
+ "build": "bun build src/cli/index.ts --outdir dist --target bun"
43
+ },
44
+ "devDependencies": {
45
+ "@types/bun": "^1.3.14",
46
+ "typescript": "^5.9.0"
47
+ }
48
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DocBridge Context Output",
4
+ "description": "Shape of `docbridge context --json` output. See docs/specs/cli.md#context-command.",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["contexts", "diagnostics", "summary"],
8
+ "properties": {
9
+ "contexts": {
10
+ "type": "array",
11
+ "items": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["endpoint", "kind", "filePath", "startLine", "endLine", "linkedFrom", "content"],
15
+ "properties": {
16
+ "endpoint": {
17
+ "type": "string",
18
+ "description": "Counterpart endpoint in `file#fragment` form."
19
+ },
20
+ "kind": {
21
+ "type": "string",
22
+ "enum": ["code", "doc"]
23
+ },
24
+ "filePath": {
25
+ "type": "string",
26
+ "description": "Project-root-relative POSIX path of the counterpart file."
27
+ },
28
+ "language": {
29
+ "type": "string",
30
+ "enum": ["typescript", "swift", "dart"],
31
+ "description": "Code language for code context blocks."
32
+ },
33
+ "startLine": {
34
+ "type": "integer",
35
+ "minimum": 1,
36
+ "description": "1-based first line of `content` within `filePath`."
37
+ },
38
+ "endLine": {
39
+ "type": "integer",
40
+ "minimum": 1,
41
+ "description": "1-based last line of `content` within `filePath`, inclusive."
42
+ },
43
+ "linkedFrom": {
44
+ "type": "array",
45
+ "minItems": 1,
46
+ "items": {
47
+ "type": "string"
48
+ },
49
+ "description": "Endpoints in the input files that link to this counterpart, sorted."
50
+ },
51
+ "content": {
52
+ "type": "string",
53
+ "description": "Full Markdown section (doc) or full declaration source including JSDoc (code)."
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "diagnostics": {
59
+ "type": "array",
60
+ "description": "Check diagnostics located in the input files, in check order.",
61
+ "items": {
62
+ "type": "object",
63
+ "required": ["severity", "code", "target", "message"],
64
+ "properties": {
65
+ "severity": {
66
+ "type": "string",
67
+ "enum": ["error", "warning"]
68
+ },
69
+ "code": {
70
+ "type": "string"
71
+ },
72
+ "target": {
73
+ "type": "string"
74
+ },
75
+ "source": {
76
+ "type": "string"
77
+ },
78
+ "message": {
79
+ "type": "string"
80
+ },
81
+ "location": {
82
+ "type": "object",
83
+ "required": ["filePath", "line", "column"],
84
+ "properties": {
85
+ "filePath": { "type": "string" },
86
+ "line": { "type": "integer", "minimum": 1 },
87
+ "column": { "type": "integer", "minimum": 1 }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "summary": {
94
+ "type": "object",
95
+ "additionalProperties": false,
96
+ "required": ["inputFiles", "contexts"],
97
+ "properties": {
98
+ "inputFiles": {
99
+ "type": "integer",
100
+ "minimum": 0,
101
+ "description": "Distinct input files after normalization."
102
+ },
103
+ "contexts": {
104
+ "type": "integer",
105
+ "minimum": 0,
106
+ "description": "Number of context blocks."
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DocBridge Configuration",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["include"],
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string"
10
+ },
11
+ "include": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["code", "docs"],
15
+ "properties": {
16
+ "code": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "minProperties": 1,
20
+ "properties": {
21
+ "typescript": { "$ref": "#/$defs/codeLanguageEntry" },
22
+ "swift": { "$ref": "#/$defs/codeLanguageEntry" },
23
+ "dart": { "$ref": "#/$defs/codeLanguageEntry" }
24
+ }
25
+ },
26
+ "docs": {
27
+ "type": "array",
28
+ "minItems": 1,
29
+ "items": {
30
+ "type": "string"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ },
36
+ "$defs": {
37
+ "codeLanguageEntry": {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["patterns"],
41
+ "properties": {
42
+ "patterns": {
43
+ "type": "array",
44
+ "minItems": 1,
45
+ "items": {
46
+ "type": "string"
47
+ }
48
+ },
49
+ "visibility": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "string"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,186 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "DocBridge Graph Output",
4
+ "description": "Shape of `docbridge graph --json` output. See docs/specs/cli.md#graph-command.",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["nodes", "edges", "pairs", "diagnostics", "summary"],
8
+ "properties": {
9
+ "nodes": {
10
+ "type": "array",
11
+ "items": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["id", "kind", "endpoint", "filePath", "location"],
15
+ "properties": {
16
+ "id": {
17
+ "type": "string",
18
+ "description": "Stable node identifier; equal to `endpoint`."
19
+ },
20
+ "kind": {
21
+ "type": "string",
22
+ "enum": ["code", "doc"]
23
+ },
24
+ "endpoint": {
25
+ "type": "string",
26
+ "description": "Endpoint in `file#fragment` form."
27
+ },
28
+ "filePath": {
29
+ "type": "string",
30
+ "description": "Project-root-relative POSIX path of the endpoint file."
31
+ },
32
+ "language": {
33
+ "type": "string",
34
+ "enum": ["typescript", "swift", "dart"],
35
+ "description": "Code language for code nodes."
36
+ },
37
+ "location": { "$ref": "#/$defs/location" },
38
+ "range": { "$ref": "#/$defs/range" },
39
+ "content": {
40
+ "oneOf": [
41
+ {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "required": ["kind", "symbolName", "signature"],
45
+ "properties": {
46
+ "kind": { "const": "code" },
47
+ "symbolName": { "type": "string" },
48
+ "signature": {
49
+ "type": "string",
50
+ "description": "JSDoc plus declaration signature; implementation body is omitted."
51
+ }
52
+ }
53
+ },
54
+ {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "required": ["kind", "headingText"],
58
+ "properties": {
59
+ "kind": { "const": "doc" },
60
+ "headingText": { "type": "string" }
61
+ }
62
+ }
63
+ ]
64
+ }
65
+ }
66
+ }
67
+ },
68
+ "edges": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "additionalProperties": false,
73
+ "required": ["kind", "source", "target", "location"],
74
+ "properties": {
75
+ "kind": {
76
+ "type": "string",
77
+ "enum": ["doc", "code"],
78
+ "description": "`doc` is a code-to-doc @doc annotation; `code` is a doc-to-code @code annotation."
79
+ },
80
+ "source": {
81
+ "type": "string",
82
+ "description": "Source endpoint of the annotation edge."
83
+ },
84
+ "target": {
85
+ "type": "string",
86
+ "description": "Resolved target endpoint of the annotation edge."
87
+ },
88
+ "location": { "$ref": "#/$defs/location" },
89
+ "range": { "$ref": "#/$defs/range" }
90
+ }
91
+ }
92
+ },
93
+ "pairs": {
94
+ "type": "array",
95
+ "items": {
96
+ "type": "object",
97
+ "additionalProperties": false,
98
+ "required": ["codeEndpoint", "docEndpoint", "hasDocEdge", "hasCodeEdge"],
99
+ "properties": {
100
+ "codeEndpoint": { "type": "string" },
101
+ "docEndpoint": { "type": "string" },
102
+ "hasDocEdge": {
103
+ "type": "boolean",
104
+ "description": "True when a resolved @doc annotation exists from code to doc."
105
+ },
106
+ "hasCodeEdge": {
107
+ "type": "boolean",
108
+ "description": "True when a resolved @code annotation exists from doc to code."
109
+ }
110
+ }
111
+ }
112
+ },
113
+ "diagnostics": {
114
+ "type": "array",
115
+ "items": { "$ref": "#/$defs/diagnostic" }
116
+ },
117
+ "summary": {
118
+ "type": "object",
119
+ "additionalProperties": false,
120
+ "required": [
121
+ "nodes",
122
+ "edges",
123
+ "codeNodes",
124
+ "docNodes",
125
+ "bidirectionalPairs",
126
+ "oneWayEdges",
127
+ "diagnostics"
128
+ ],
129
+ "properties": {
130
+ "nodes": { "type": "integer", "minimum": 0 },
131
+ "edges": { "type": "integer", "minimum": 0 },
132
+ "codeNodes": { "type": "integer", "minimum": 0 },
133
+ "docNodes": { "type": "integer", "minimum": 0 },
134
+ "bidirectionalPairs": { "type": "integer", "minimum": 0 },
135
+ "oneWayEdges": { "type": "integer", "minimum": 0 },
136
+ "diagnostics": { "type": "integer", "minimum": 0 }
137
+ }
138
+ }
139
+ },
140
+ "$defs": {
141
+ "location": {
142
+ "type": "object",
143
+ "additionalProperties": false,
144
+ "required": ["filePath", "line", "column"],
145
+ "properties": {
146
+ "filePath": { "type": "string" },
147
+ "line": { "type": "integer", "minimum": 1 },
148
+ "column": { "type": "integer", "minimum": 1 }
149
+ }
150
+ },
151
+ "position": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["line", "column"],
155
+ "properties": {
156
+ "line": { "type": "integer", "minimum": 1 },
157
+ "column": { "type": "integer", "minimum": 1 }
158
+ }
159
+ },
160
+ "range": {
161
+ "type": "object",
162
+ "additionalProperties": false,
163
+ "required": ["start", "end"],
164
+ "properties": {
165
+ "start": { "$ref": "#/$defs/position" },
166
+ "end": { "$ref": "#/$defs/position" }
167
+ }
168
+ },
169
+ "diagnostic": {
170
+ "type": "object",
171
+ "required": ["severity", "code", "target", "message"],
172
+ "properties": {
173
+ "severity": {
174
+ "type": "string",
175
+ "enum": ["error", "warning"]
176
+ },
177
+ "code": { "type": "string" },
178
+ "target": { "type": "string" },
179
+ "source": { "type": "string" },
180
+ "message": { "type": "string" },
181
+ "location": { "$ref": "#/$defs/location" },
182
+ "range": { "$ref": "#/$defs/range" }
183
+ }
184
+ }
185
+ }
186
+ }
@@ -0,0 +1,31 @@
1
+ # DocBridge skill templates
2
+
3
+ Distributable agent skills for projects that use DocBridge. Installation is
4
+ copy-based: copy a skill directory into your repository's skill location
5
+ (`.claude/skills/` for Claude Code or `.agents/skills/` for Codex-style
6
+ project skills) and adjust nothing unless your DocBridge invocation differs
7
+ from the examples inside.
8
+
9
+ - [`docbridge-annotate`](docbridge-annotate/SKILL.md) — create correct
10
+ `@doc`/`@code` link pairs and verify them with `docbridge check`.
11
+ - [`docbridge-sync`](docbridge-sync/SKILL.md) — triage `related --gate`
12
+ findings: fetch the flagged counterpart content with `docbridge context`,
13
+ then update the counterpart or justify leaving it unchanged.
14
+ - [`docbridge-adopt`](docbridge-adopt/SKILL.md) — adopt DocBridge in an existing
15
+ TypeScript, Swift, or Dart project by confirming docs/code scope, creating
16
+ or improving config, and handling simple CI/hook setup.
17
+ - [`docbridge-link`](docbridge-link/SKILL.md) — link existing docs sections to
18
+ existing supported code declarations through docs-first candidate discovery
19
+ and section-level confirmation.
20
+ - [`docbridge-review`](docbridge-review/SKILL.md) — review the whole DocBridge
21
+ graph for semantic validity using `docbridge graph --json --include-content`.
22
+
23
+ This repository dogfoods the distributable DocBridge skills from both
24
+ `.claude/skills/` and `.agents/skills/` as skill-level symlinks to this
25
+ directory. The template is the source of truth; do not edit the symlinked
26
+ copies in place. In-repository dogfood links require symlink-capable checkouts;
27
+ external projects should use the copy-based installation above.
28
+
29
+ The hook-side integration that complements these skills lives in
30
+ [`examples/hooks/`](../../examples/hooks/) with recipes under
31
+ [`docs/integrations/`](../../docs/integrations/).
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: docbridge-adopt
3
+ description: Adopt DocBridge in an existing TypeScript, Swift, or Dart project. Use when asked to introduce DocBridge into a repository, choose docs/code scope, create or improve docbridge.config.json, and optionally wire simple CI or agent hooks.
4
+ ---
5
+
6
+ # docbridge-adopt
7
+
8
+ Adopt DocBridge in an existing project. This skill assumes it is already
9
+ installed in the agent environment; installing agent skills into another
10
+ project is documented outside this skill.
11
+
12
+ The goal is to make the repository ready for DocBridge links, then continue
13
+ into an initial docs-first link-candidate pass. Do not assume a pull request.
14
+
15
+ Run DocBridge with the project's native invocation: `docbridge` on `PATH`, a
16
+ repo recipe such as `just check`, or
17
+ `bun run /path/to/docbridge/src/cli/index.ts`.
18
+
19
+ ## Procedure
20
+
21
+ 1. **Survey the repository.** Inspect:
22
+ - existing `docbridge.config.json`
23
+ - Markdown docs structure and likely specification directories
24
+ - TypeScript, Swift, or Dart source structure and public API locations
25
+ - existing `@doc` / `@code` annotations
26
+ - package scripts, CI files, git hooks, and agent hooks
27
+
28
+ 2. **Recommend scope, then ask for confirmation.** Present concise options and
29
+ your recommendation for:
30
+ - docs scope: directories/files whose sections are likely specifications,
31
+ contracts, behavior, constraints, or design decisions
32
+ - code scope: language-keyed TypeScript, Swift, or Dart directories/files
33
+ whose supported declarations should be linkable
34
+ - CI/hook mode: if any integration should be added now
35
+
36
+ Do not ask the user to rediscover obvious facts from the repository. Show
37
+ your recommendation and the tradeoff, then wait for confirmation.
38
+
39
+ 3. **Create or improve config.**
40
+ - If no config exists, create `docbridge.config.json` with the confirmed
41
+ `include.code` and `include.docs` globs.
42
+ - Use the language-keyed `include.code` object. Do not write the old
43
+ array form; for example, use `{ "typescript": { "patterns": [...] } }`,
44
+ `{ "swift": { "patterns": [...] } }`, or
45
+ `{ "dart": { "patterns": [...] } }`.
46
+ - If config exists, read it, explain the current scope, propose any
47
+ improvement, and edit only after confirmation.
48
+ - Never replace a user-authored config blindly.
49
+
50
+ 4. **Handle CI/hooks conservatively.**
51
+ - If the existing setup is simple and the user confirmed the mode, implement
52
+ it.
53
+ - If the setup is complex or ambiguous, provide a concrete patch plan or
54
+ snippet instead of editing.
55
+ - Prefer non-blocking awareness early in adoption unless the user requests a
56
+ hard gate.
57
+
58
+ 5. **Verify the setup.** Run `docbridge check` or the repository's equivalent.
59
+ If the project intentionally has no links yet, a clean zero-link result is
60
+ acceptable. Surface config or scanning diagnostics before proceeding.
61
+
62
+ 6. **Continue into initial candidate discovery.** After setup, inspect the
63
+ confirmed docs scope and present 5-10 high-value section candidates using
64
+ the `docbridge-link` rules. Candidate discovery may continue in the same
65
+ turn, but annotation edits still require section-level user confirmation.
66
+
67
+ ## Scope Rules
68
+
69
+ - Prefer docs sections that state behavior, contracts, inputs/outputs,
70
+ constraints, user-visible behavior, or design decisions.
71
+ - Treat README, changelogs, contribution docs, runbooks, logs, and release
72
+ notes as exclusions by default unless the user identifies specific sections
73
+ as specifications.
74
+ - Prefer supported public API declarations as link targets. TypeScript starts
75
+ with top-level exported declarations; Swift and Dart also support member
76
+ endpoints with scanner-produced canonical IDs.
77
+ - Do not decide project workflow policy such as branch or PR strategy. Mention
78
+ only what affects DocBridge adoption.
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: docbridge-annotate
3
+ description: Create bidirectional DocBridge links between supported code declarations and Markdown sections. Use when asked to link code to its specification, add @doc or @code annotations, annotate new code with docs, or fix DocBridge link diagnostics.
4
+ ---
5
+
6
+ # docbridge-annotate
7
+
8
+ Create a DocBridge link pair: a `@doc` tag in the code documentation comment
9
+ and a `@code` comment above the Markdown heading. A link is valid only when
10
+ both directions exist and point at each other.
11
+
12
+ Run DocBridge with the project's native invocation: `docbridge` on `PATH`, a
13
+ repo recipe such as `just check`, or
14
+ `bun run /path/to/docbridge/src/cli/index.ts`.
15
+
16
+ ## Link anatomy
17
+
18
+ Code side — a `@doc` tag in the documentation comment of a supported
19
+ declaration:
20
+
21
+ ```ts
22
+ /**
23
+ * @doc docs/auth.md#login-spec
24
+ */
25
+ export async function login() {}
26
+ ```
27
+
28
+ ```swift
29
+ /// @doc docs/auth.md#login-spec
30
+ public struct AuthService {
31
+ public func login(email: String, password: String) {}
32
+ }
33
+ ```
34
+
35
+ Markdown side — a standalone HTML comment directly above the heading of the
36
+ section:
37
+
38
+ ```md
39
+ <!-- @code src/auth/login.ts#login -->
40
+ ## Login Spec
41
+ ```
42
+
43
+ Both targets are `file#fragment`: the file path is project-root-relative with
44
+ `/` separators (no `./`, `../`, or absolute paths), and the fragment is
45
+ required. Optional text after the target is allowed and ignored
46
+ (`@doc docs/auth.md#login-spec human note`).
47
+
48
+ ## Rules that decide whether the link resolves
49
+
50
+ - `@doc` works only on top-level exported declarations: `function`, `class`,
51
+ `abstract class`, `interface`, `type`, `enum`, `const enum`, `const` with a
52
+ single declarator, named default `function`/`class`, and their `declare`
53
+ forms. Anything else (anonymous default exports, multi-declarator `const`,
54
+ namespaces, re-exports, non-exported declarations) produces
55
+ `unsupported_declaration`.
56
+ - Swift `@doc` works on supported public/open declarations and configured
57
+ internal declarations. Member endpoints are type-qualified and include
58
+ argument labels, for example `AuthService.login(email:password:)`.
59
+ - Dart `@doc` works on supported public declarations. Member endpoints are
60
+ type-qualified without parameter signatures, for example
61
+ `AuthService.login`; setters carry a trailing `=`.
62
+ - The code-side fragment is the scanner-produced canonical ID.
63
+ - The doc-side fragment is the anchor generated from the ATX heading
64
+ (`#`–`######`): lowercase via JavaScript `toLowerCase()`, Unicode letters
65
+ and numbers preserved, whitespace and punctuation runs collapsed to `-`,
66
+ leading/trailing `-` removed. Example: `## Login Spec (v2)` →
67
+ `#login-spec-v2`. Setext headings have no anchors.
68
+ - The `@code` comment must be standalone, indented at most 3 spaces, with the
69
+ body starting with `@code`. Blank lines between the comment and its heading
70
+ are fine; any other text in between makes it `dangling_code_annotation`.
71
+ - One declaration may carry multiple `@doc` tags and one heading multiple
72
+ `@code` comments; each pair is an independent link.
73
+ - Anchors must be unique within one Markdown file; symbols must be unique
74
+ among annotated declarations in one TypeScript file.
75
+
76
+ ## Procedure
77
+
78
+ 1. Identify the two endpoints: the exported declaration and the Markdown
79
+ section. If the section does not exist yet, write it first — the heading
80
+ text fixes the anchor.
81
+ 2. Add the `@doc` tag to the declaration's documentation comment (create the
82
+ documentation comment if missing), pointing at the doc file and the
83
+ generated heading anchor.
84
+ 3. Add the `@code` comment directly above the heading, pointing back at the
85
+ code file and the scanner-produced canonical ID.
86
+ 4. Verify with `docbridge check`. The link is correct only when no diagnostic
87
+ mentions either endpoint.
88
+
89
+ ## Diagnosing check failures
90
+
91
+ | Diagnostic | Meaning | Usual fix |
92
+ | --- | --- | --- |
93
+ | `doc_file_not_found` / `code_file_not_found` | target file not in the managed set | fix the path, or extend `docbridge.config.json` globs |
94
+ | `doc_anchor_not_found` | file found, anchor wrong | regenerate the anchor from the exact heading text |
95
+ | `doc_backlink_not_found` / `code_backlink_not_found` | one direction missing | add the missing `@code` or `@doc` side |
96
+ | `unsupported_declaration` | `@doc` on an unsupported declaration | move the tag to a supported declaration |
97
+ | `dangling_code_annotation` | text between `@code` and the heading | move the comment directly above the heading |
98
+ | `invalid_link_target` | malformed `file#fragment` | rewrite the target per the rules above |