@refrakt-md/plan 0.9.6 → 0.9.8

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.
Files changed (45) hide show
  1. package/dist/cards.d.ts +23 -0
  2. package/dist/cards.d.ts.map +1 -0
  3. package/dist/cards.js +150 -0
  4. package/dist/cards.js.map +1 -0
  5. package/dist/cli-plugin.d.ts.map +1 -1
  6. package/dist/cli-plugin.js +14 -5
  7. package/dist/cli-plugin.js.map +1 -1
  8. package/dist/commands/create.js +3 -3
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/init.d.ts +7 -2
  11. package/dist/commands/init.d.ts.map +1 -1
  12. package/dist/commands/init.js +149 -26
  13. package/dist/commands/init.js.map +1 -1
  14. package/dist/commands/templates.js +9 -9
  15. package/dist/commands/templates.js.map +1 -1
  16. package/dist/diff.d.ts +35 -0
  17. package/dist/diff.d.ts.map +1 -0
  18. package/dist/diff.js +88 -0
  19. package/dist/diff.js.map +1 -0
  20. package/dist/history.d.ts +3 -35
  21. package/dist/history.d.ts.map +1 -1
  22. package/dist/history.js +3 -84
  23. package/dist/history.js.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/pipeline.d.ts +2 -11
  26. package/dist/pipeline.d.ts.map +1 -1
  27. package/dist/pipeline.js +5 -255
  28. package/dist/pipeline.js.map +1 -1
  29. package/dist/relationships.d.ts +36 -0
  30. package/dist/relationships.d.ts.map +1 -0
  31. package/dist/relationships.js +128 -0
  32. package/dist/relationships.js.map +1 -0
  33. package/dist/render.d.ts +31 -0
  34. package/dist/render.d.ts.map +1 -0
  35. package/dist/render.js +57 -0
  36. package/dist/render.js.map +1 -0
  37. package/dist/scanner-core.d.ts +10 -0
  38. package/dist/scanner-core.d.ts.map +1 -0
  39. package/dist/scanner-core.js +230 -0
  40. package/dist/scanner-core.js.map +1 -0
  41. package/dist/scanner.d.ts +2 -9
  42. package/dist/scanner.d.ts.map +1 -1
  43. package/dist/scanner.js +5 -230
  44. package/dist/scanner.js.map +1 -1
  45. package/package.json +28 -8
@@ -0,0 +1,36 @@
1
+ /** A directed reference from one entity to another */
2
+ export interface EntityRelationship {
3
+ /** The entity that contains the reference */
4
+ fromId: string;
5
+ fromType: string;
6
+ /** The entity being referenced */
7
+ toId: string;
8
+ toType: string;
9
+ /** Relationship kind */
10
+ kind: 'blocks' | 'blocked-by' | 'depends-on' | 'dependency-of' | 'implements' | 'implemented-by' | 'informs' | 'informed-by' | 'related';
11
+ }
12
+ /** Minimal entity shape needed for relationship building */
13
+ export interface RelationshipEntity {
14
+ type: string;
15
+ data: Record<string, unknown>;
16
+ }
17
+ /**
18
+ * Build a bidirectional relationship index from entity references.
19
+ *
20
+ * Three sources of relationships are processed:
21
+ * 1. **Source references** (from source= attribute): produce `implements`/`implemented-by` edges
22
+ * (or `informs`/`informed-by` for decisions)
23
+ * 2. **Scanner dependencies** (from ## Dependencies sections): produce `depends-on`/`dependency-of` edges
24
+ * 3. **ID references** (text-pattern matches like WORK-042): produce `related` edges
25
+ * (or `blocked-by`/`blocks` when the referencing entity has status "blocked")
26
+ *
27
+ * Edges from sources 1 and 2 suppress duplicate edges from source 3.
28
+ */
29
+ export declare function buildRelationships(entities: Map<string, RelationshipEntity>, sourceReferences: Map<string, Array<{
30
+ id: string;
31
+ type: string;
32
+ }>>, scannerDependencies: Map<string, string[]>, idReferences: Map<string, Array<{
33
+ id: string;
34
+ type: string;
35
+ }>>): Map<string, EntityRelationship[]>;
36
+ //# sourceMappingURL=relationships.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../src/relationships.ts"],"names":[],"mappings":"AAIA,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IAClC,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,IAAI,EAAE,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,eAAe,GAAG,YAAY,GAAG,gBAAgB,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;CACzI;AAED,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACzC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,EAClE,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC1C,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,GAC5D,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAuHnC"}
@@ -0,0 +1,128 @@
1
+ // ─── Relationship Builder ───
2
+ // Constructs bidirectional relationship graphs from entity references.
3
+ // No Node.js API dependencies — safe for edge runtimes.
4
+ /**
5
+ * Build a bidirectional relationship index from entity references.
6
+ *
7
+ * Three sources of relationships are processed:
8
+ * 1. **Source references** (from source= attribute): produce `implements`/`implemented-by` edges
9
+ * (or `informs`/`informed-by` for decisions)
10
+ * 2. **Scanner dependencies** (from ## Dependencies sections): produce `depends-on`/`dependency-of` edges
11
+ * 3. **ID references** (text-pattern matches like WORK-042): produce `related` edges
12
+ * (or `blocked-by`/`blocks` when the referencing entity has status "blocked")
13
+ *
14
+ * Edges from sources 1 and 2 suppress duplicate edges from source 3.
15
+ */
16
+ export function buildRelationships(entities, sourceReferences, scannerDependencies, idReferences) {
17
+ const relationships = new Map();
18
+ function addRel(id, rel) {
19
+ if (!relationships.has(id))
20
+ relationships.set(id, []);
21
+ relationships.get(id).push(rel);
22
+ }
23
+ // Track IDs already linked via source= to avoid duplicate 'related' edges
24
+ const sourceLinked = new Set();
25
+ // Process structured source= references → implements / implemented-by (or informs / informed-by for decisions)
26
+ for (const [fromId, refs] of sourceReferences) {
27
+ const fromEntity = entities.get(fromId);
28
+ if (!fromEntity)
29
+ continue;
30
+ // Decisions use informs/informed-by; work/bug use implements/implemented-by
31
+ const isDecision = fromEntity.type === 'decision';
32
+ const forwardKind = isDecision ? 'informs' : 'implements';
33
+ const reverseKind = isDecision ? 'informed-by' : 'implemented-by';
34
+ for (const ref of refs) {
35
+ const toEntity = entities.get(ref.id);
36
+ if (!toEntity)
37
+ continue;
38
+ sourceLinked.add(`${fromId}→${ref.id}`);
39
+ // A implements/informs B
40
+ addRel(fromId, {
41
+ fromId, fromType: fromEntity.type,
42
+ toId: ref.id, toType: toEntity.type,
43
+ kind: forwardKind,
44
+ });
45
+ // B is implemented-by/informed-by A
46
+ addRel(ref.id, {
47
+ fromId: ref.id, fromType: toEntity.type,
48
+ toId: fromId, toType: fromEntity.type,
49
+ kind: reverseKind,
50
+ });
51
+ }
52
+ }
53
+ // Track IDs already linked via depends-on to avoid duplicate 'related' edges
54
+ const depLinked = new Set();
55
+ // Process scanner dependency data → depends-on / dependency-of
56
+ for (const [fromId, depIds] of scannerDependencies) {
57
+ const fromEntity = entities.get(fromId);
58
+ if (!fromEntity)
59
+ continue;
60
+ for (const depId of depIds) {
61
+ const toEntity = entities.get(depId);
62
+ if (!toEntity)
63
+ continue;
64
+ depLinked.add(`${fromId}→${depId}`);
65
+ // A depends-on B
66
+ addRel(fromId, {
67
+ fromId, fromType: fromEntity.type,
68
+ toId: depId, toType: toEntity.type,
69
+ kind: 'depends-on',
70
+ });
71
+ // B is dependency-of A
72
+ addRel(depId, {
73
+ fromId: depId, fromType: toEntity.type,
74
+ toId: fromId, toType: fromEntity.type,
75
+ kind: 'dependency-of',
76
+ });
77
+ }
78
+ }
79
+ // Process text-based ID references → blocks / blocked-by / related
80
+ for (const [fromId, refs] of idReferences) {
81
+ const fromEntity = entities.get(fromId);
82
+ if (!fromEntity)
83
+ continue;
84
+ for (const ref of refs) {
85
+ const toEntity = entities.get(ref.id);
86
+ if (!toEntity)
87
+ continue; // Reference to unknown entity — skip
88
+ // Skip if already linked via source= attribute or dependency
89
+ if (sourceLinked.has(`${fromId}→${ref.id}`))
90
+ continue;
91
+ if (depLinked.has(`${fromId}→${ref.id}`))
92
+ continue;
93
+ // Determine relationship kind
94
+ // If entity A has status "blocked" and references entity B, A is "blocked-by" B
95
+ const fromStatus = String(fromEntity.data.status ?? '');
96
+ const isBlockedBy = fromStatus === 'blocked';
97
+ if (isBlockedBy) {
98
+ // A is blocked by B
99
+ addRel(fromId, {
100
+ fromId, fromType: fromEntity.type,
101
+ toId: ref.id, toType: toEntity.type,
102
+ kind: 'blocked-by',
103
+ });
104
+ // B blocks A
105
+ addRel(ref.id, {
106
+ fromId: ref.id, fromType: toEntity.type,
107
+ toId: fromId, toType: fromEntity.type,
108
+ kind: 'blocks',
109
+ });
110
+ }
111
+ else {
112
+ // General related reference (bidirectional)
113
+ addRel(fromId, {
114
+ fromId, fromType: fromEntity.type,
115
+ toId: ref.id, toType: toEntity.type,
116
+ kind: 'related',
117
+ });
118
+ addRel(ref.id, {
119
+ fromId: ref.id, fromType: toEntity.type,
120
+ toId: fromId, toType: fromEntity.type,
121
+ kind: 'related',
122
+ });
123
+ }
124
+ }
125
+ }
126
+ return relationships;
127
+ }
128
+ //# sourceMappingURL=relationships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationships.js","sourceRoot":"","sources":["../src/relationships.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Edge-safe entity rendering module.
3
+ *
4
+ * Renders a single plan entity's Markdoc source to a serialized tree
5
+ * (RendererNode) that can be identity-transformed by any theme and
6
+ * rendered to HTML.
7
+ *
8
+ * This module has NO Node.js dependencies and runs on Cloudflare Workers.
9
+ *
10
+ * Usage:
11
+ * import { renderEntity } from '@refrakt-md/plan/render';
12
+ * import { identityTransform } from '@refrakt-md/lumina/transform';
13
+ * import { renderToHtml } from '@refrakt-md/transform';
14
+ *
15
+ * const tree = renderEntity(source);
16
+ * const html = renderToHtml(identityTransform(tree));
17
+ */
18
+ import type { RendererNode } from '@refrakt-md/transform';
19
+ /**
20
+ * Render a plan entity's Markdoc source to a serialized tree (RendererNode).
21
+ *
22
+ * The returned tree has the same structure as the static plan site produces
23
+ * before the identity transform — preamble, body sections, meta fields, etc.
24
+ *
25
+ * The consumer is responsible for:
26
+ * 1. Applying the theme's identity transform (e.g. lumina)
27
+ * 2. Rendering to HTML (e.g. renderToHtml from @refrakt-md/transform)
28
+ * 3. Any presentation wrapping (tabs, panels, etc.)
29
+ */
30
+ export declare function renderEntity(source: string): RendererNode;
31
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAuB1D;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAUzD"}
package/dist/render.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Edge-safe entity rendering module.
3
+ *
4
+ * Renders a single plan entity's Markdoc source to a serialized tree
5
+ * (RendererNode) that can be identity-transformed by any theme and
6
+ * rendered to HTML.
7
+ *
8
+ * This module has NO Node.js dependencies and runs on Cloudflare Workers.
9
+ *
10
+ * Usage:
11
+ * import { renderEntity } from '@refrakt-md/plan/render';
12
+ * import { identityTransform } from '@refrakt-md/lumina/transform';
13
+ * import { renderToHtml } from '@refrakt-md/transform';
14
+ *
15
+ * const tree = renderEntity(source);
16
+ * const html = renderToHtml(identityTransform(tree));
17
+ */
18
+ import Markdoc from '@markdoc/markdoc';
19
+ import { serializeTree } from '@refrakt-md/runes';
20
+ import { tags as coreTagOverrides, nodes as coreNodes } from '@refrakt-md/runes';
21
+ import { spec } from './tags/spec.js';
22
+ import { work } from './tags/work.js';
23
+ import { bug } from './tags/bug.js';
24
+ import { decision } from './tags/decision.js';
25
+ import { milestone } from './tags/milestone.js';
26
+ // ── Tag Schemas ─────────────────────────────────────────────
27
+ const planTags = {
28
+ spec,
29
+ work,
30
+ task: work,
31
+ bug,
32
+ decision,
33
+ adr: decision,
34
+ milestone,
35
+ };
36
+ // ── Main API ────────────────────────────────────────────────
37
+ /**
38
+ * Render a plan entity's Markdoc source to a serialized tree (RendererNode).
39
+ *
40
+ * The returned tree has the same structure as the static plan site produces
41
+ * before the identity transform — preamble, body sections, meta fields, etc.
42
+ *
43
+ * The consumer is responsible for:
44
+ * 1. Applying the theme's identity transform (e.g. lumina)
45
+ * 2. Rendering to HTML (e.g. renderToHtml from @refrakt-md/transform)
46
+ * 3. Any presentation wrapping (tabs, panels, etc.)
47
+ */
48
+ export function renderEntity(source) {
49
+ const tags = { ...coreTagOverrides, ...planTags };
50
+ const ast = Markdoc.parse(source);
51
+ const renderable = Markdoc.transform(ast, {
52
+ tags,
53
+ nodes: coreNodes,
54
+ });
55
+ return serializeTree(renderable);
56
+ }
57
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,IAAI,IAAI,gBAAgB,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,+DAA+D;AAE/D,MAAM,QAAQ,GAAwB;IACrC,IAAI;IACJ,IAAI;IACJ,IAAI,EAAE,IAAI;IACV,GAAG;IACH,QAAQ;IACR,GAAG,EAAE,QAAQ;IACb,SAAS;CACT,CAAC;AAEF,+DAA+D;AAE/D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IAC1C,MAAM,IAAI,GAAG,EAAE,GAAG,gBAAgB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAElD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;QACzC,IAAI;QACJ,KAAK,EAAE,SAAS;KAChB,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC,UAAgC,CAAiB,CAAC;AACxE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { PlanEntity, FileSource } from './types.js';
2
+ /** Parse plan content from a string and return PlanEntity if it contains a plan rune, or null */
3
+ export declare function parseFileContent(source: string, relPath: string): PlanEntity | null;
4
+ /**
5
+ * Scan plan entities from pre-fetched file contents.
6
+ * Use this when files come from an external source (e.g. GitHub API)
7
+ * rather than the local filesystem.
8
+ */
9
+ export declare function scanPlanSources(sources: FileSource[]): PlanEntity[];
10
+ //# sourceMappingURL=scanner-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner-core.d.ts","sourceRoot":"","sources":["../src/scanner-core.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAkD,UAAU,EAAE,MAAM,YAAY,CAAC;AAuMzG,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA0BnF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAUnE"}
@@ -0,0 +1,230 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ import { escapeFenceTags } from '@refrakt-md/runes';
3
+ const PLAN_RUNE_TYPES = new Set(['spec', 'work', 'bug', 'decision', 'milestone']);
4
+ const REF_TAG_NAMES = new Set(['ref', 'xref']);
5
+ /** Known sections per rune type: canonical name → lowercase aliases */
6
+ const KNOWN_SECTIONS = {
7
+ work: {
8
+ 'Acceptance Criteria': ['criteria', 'ac', 'done when'],
9
+ 'Dependencies': ['deps', 'depends on', 'blocked by', 'requires'],
10
+ 'Approach': ['technical notes', 'implementation notes', 'how'],
11
+ 'References': ['refs', 'related', 'context'],
12
+ 'Edge Cases': ['exceptions', 'corner cases'],
13
+ 'Verification': ['test cases', 'tests'],
14
+ },
15
+ bug: {
16
+ 'Steps to Reproduce': ['reproduction', 'steps', 'repro'],
17
+ 'Expected': ['expected behaviour'],
18
+ 'Actual': ['actual behaviour'],
19
+ 'Environment': ['env'],
20
+ },
21
+ decision: {
22
+ 'Context': ['background'],
23
+ 'Options Considered': ['options', 'alternatives'],
24
+ 'Decision': [],
25
+ 'Rationale': ['reasoning'],
26
+ 'Consequences': ['impact', 'trade-offs'],
27
+ },
28
+ };
29
+ /** Match a heading text to a canonical known section name for a given rune type */
30
+ function matchKnownSection(runeType, headingText) {
31
+ const sections = KNOWN_SECTIONS[runeType];
32
+ if (!sections)
33
+ return undefined;
34
+ const normalized = headingText.toLowerCase().trim();
35
+ for (const [canonical, aliases] of Object.entries(sections)) {
36
+ if (canonical.toLowerCase() === normalized)
37
+ return canonical;
38
+ if (aliases.some(a => a === normalized))
39
+ return canonical;
40
+ }
41
+ return undefined;
42
+ }
43
+ /** Walk the AST and collect all nodes matching a predicate */
44
+ function walkNodes(node, predicate) {
45
+ const results = [];
46
+ if (predicate(node))
47
+ results.push(node);
48
+ if (node.children) {
49
+ for (const child of node.children) {
50
+ results.push(...walkNodes(child, predicate));
51
+ }
52
+ }
53
+ return results;
54
+ }
55
+ /** Extract the title from the first H1 heading's text content */
56
+ function extractTitle(ast) {
57
+ const headings = walkNodes(ast, n => n.type === 'heading' && n.attributes.level === 1);
58
+ if (headings.length === 0)
59
+ return undefined;
60
+ const texts = [];
61
+ walkNodes(headings[0], n => {
62
+ if (n.type === 'text' && n.attributes.content) {
63
+ texts.push(n.attributes.content);
64
+ }
65
+ return false;
66
+ });
67
+ return texts.join('').trim() || undefined;
68
+ }
69
+ /** Extract acceptance criteria checkboxes from the raw source lines within a plan rune */
70
+ function extractCriteria(source, runeStartLine, runeEndLine) {
71
+ const lines = source.split('\n');
72
+ const criteria = [];
73
+ for (let i = runeStartLine; i < runeEndLine && i < lines.length; i++) {
74
+ const match = lines[i].match(/^[\s]*-\s+\[([ xX])\]\s+(.+)/);
75
+ if (match) {
76
+ criteria.push({
77
+ text: match[2].trim(),
78
+ checked: match[1] !== ' ',
79
+ });
80
+ }
81
+ }
82
+ return criteria;
83
+ }
84
+ /** Extract the Resolution section from the raw source within the rune's line range */
85
+ function extractResolution(source, runeStartLine, runeEndLine) {
86
+ const lines = source.split('\n');
87
+ // Find the first ## Resolution heading within the rune range
88
+ let resolutionStart = -1;
89
+ for (let i = runeStartLine; i < runeEndLine && i < lines.length; i++) {
90
+ if (/^##\s+Resolution\s*$/.test(lines[i])) {
91
+ resolutionStart = i;
92
+ break;
93
+ }
94
+ }
95
+ if (resolutionStart === -1)
96
+ return undefined;
97
+ // Collect all lines from after the heading to the end of the rune (or next ## heading)
98
+ const contentLines = [];
99
+ for (let i = resolutionStart + 1; i < runeEndLine && i < lines.length; i++) {
100
+ // Stop at the next H2 heading (but not H3+)
101
+ if (/^##\s+[^#]/.test(lines[i]))
102
+ break;
103
+ contentLines.push(lines[i]);
104
+ }
105
+ const content = contentLines.join('\n').trim();
106
+ // Parse metadata lines
107
+ let date;
108
+ let branch;
109
+ let pr;
110
+ const bodyLines = [];
111
+ for (const line of contentLines) {
112
+ const dateMatch = line.match(/^Completed:\s*(.+)$/);
113
+ if (dateMatch) {
114
+ date = dateMatch[1].trim();
115
+ continue;
116
+ }
117
+ const branchMatch = line.match(/^Branch:\s*(.+)$/);
118
+ if (branchMatch) {
119
+ branch = branchMatch[1].trim().replace(/^`|`$/g, '');
120
+ continue;
121
+ }
122
+ const prMatch = line.match(/^PR:\s*(.+)$/);
123
+ if (prMatch) {
124
+ pr = prMatch[1].trim();
125
+ continue;
126
+ }
127
+ bodyLines.push(line);
128
+ }
129
+ const body = bodyLines.join('\n').trim();
130
+ return { date, branch, pr, body };
131
+ }
132
+ /** Extract all referenced entity IDs from ref/xref tag nodes in the AST */
133
+ function extractRefs(ast) {
134
+ const refNodes = walkNodes(ast, n => n.type === 'tag' && REF_TAG_NAMES.has(n.tag));
135
+ const ids = [];
136
+ for (const node of refNodes) {
137
+ const primary = node.attributes.primary;
138
+ if (primary)
139
+ ids.push(primary);
140
+ }
141
+ // Deduplicate while preserving order
142
+ return [...new Set(ids)];
143
+ }
144
+ /** Extract heading text from an AST heading node */
145
+ function extractHeadingText(node) {
146
+ const texts = [];
147
+ walkNodes(node, n => {
148
+ if (n.type === 'text' && n.attributes.content) {
149
+ texts.push(n.attributes.content);
150
+ }
151
+ return false;
152
+ });
153
+ return texts.join('').trim();
154
+ }
155
+ /**
156
+ * Extract section-scoped refs and known section presence from the AST.
157
+ * Walks the plan tag's children, tracking which H2 section each ref falls in.
158
+ */
159
+ function extractScopedRefs(planTag, runeType) {
160
+ const scopedRefs = [];
161
+ const knownSectionsPresent = [];
162
+ let currentSection;
163
+ for (const child of planTag.children ?? []) {
164
+ if (child.type === 'heading' && child.attributes?.level === 2) {
165
+ const headingText = extractHeadingText(child);
166
+ const canonical = matchKnownSection(runeType, headingText);
167
+ currentSection = canonical;
168
+ if (canonical && !knownSectionsPresent.includes(canonical)) {
169
+ knownSectionsPresent.push(canonical);
170
+ }
171
+ }
172
+ // Find refs in this node (including deeply nested ones)
173
+ const refNodes = walkNodes(child, n => n.type === 'tag' && REF_TAG_NAMES.has(n.tag));
174
+ for (const refNode of refNodes) {
175
+ const id = refNode.attributes.primary;
176
+ if (id) {
177
+ scopedRefs.push({ id, section: currentSection });
178
+ }
179
+ }
180
+ }
181
+ // Deduplicate scopedRefs by id+section
182
+ const seen = new Set();
183
+ const deduped = [];
184
+ for (const ref of scopedRefs) {
185
+ const key = `${ref.id}:${ref.section ?? ''}`;
186
+ if (!seen.has(key)) {
187
+ seen.add(key);
188
+ deduped.push(ref);
189
+ }
190
+ }
191
+ return { scopedRefs: deduped, knownSectionsPresent };
192
+ }
193
+ /** Parse plan content from a string and return PlanEntity if it contains a plan rune, or null */
194
+ export function parseFileContent(source, relPath) {
195
+ const ast = Markdoc.parse(escapeFenceTags(source));
196
+ // Find the first plan rune tag at the top level
197
+ const planTag = ast.children.find((n) => n.type === 'tag' && PLAN_RUNE_TYPES.has(n.tag));
198
+ if (!planTag)
199
+ return null;
200
+ const runeType = planTag.tag;
201
+ const attributes = {};
202
+ for (const [key, value] of Object.entries(planTag.attributes)) {
203
+ attributes[key] = String(value);
204
+ }
205
+ const title = extractTitle(planTag);
206
+ const startLine = planTag.lines?.[0] ?? 0;
207
+ const endLine = planTag.lines?.[planTag.lines.length - 1] ?? source.split('\n').length;
208
+ const criteria = extractCriteria(source, startLine, endLine);
209
+ const refs = extractRefs(planTag);
210
+ const { scopedRefs, knownSectionsPresent } = extractScopedRefs(planTag, runeType);
211
+ const resolution = extractResolution(source, startLine, endLine);
212
+ return { file: relPath, type: runeType, attributes, title, criteria, refs, scopedRefs, knownSectionsPresent, resolution };
213
+ }
214
+ /**
215
+ * Scan plan entities from pre-fetched file contents.
216
+ * Use this when files come from an external source (e.g. GitHub API)
217
+ * rather than the local filesystem.
218
+ */
219
+ export function scanPlanSources(sources) {
220
+ const entities = [];
221
+ for (const source of sources) {
222
+ const entity = parseFileContent(source.content, source.path);
223
+ if (entity) {
224
+ entity.mtime = source.mtime;
225
+ entities.push(entity);
226
+ }
227
+ }
228
+ return entities;
229
+ }
230
+ //# sourceMappingURL=scanner-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner-core.js","sourceRoot":"","sources":["../src/scanner-core.ts"],"names":[],"mappings":"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"}
package/dist/scanner.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import type { PlanEntity, ScanOptions, FileSource } from './types.js';
2
- /** Parse plan content from a string and return PlanEntity if it contains a plan rune, or null */
3
- export declare function parseFileContent(source: string, relPath: string): PlanEntity | null;
1
+ import type { PlanEntity, ScanOptions } from './types.js';
2
+ export { parseFileContent, scanPlanSources } from './scanner-core.js';
4
3
  /** Parse a single file from disk and return PlanEntity if it contains a plan rune, or null */
5
4
  export declare function parseFile(filePath: string, relPath: string): PlanEntity | null;
6
5
  /**
@@ -8,10 +7,4 @@ export declare function parseFile(filePath: string, relPath: string): PlanEntity
8
7
  * Returns typed PlanEntity objects for each discovered entity.
9
8
  */
10
9
  export declare function scanPlanFiles(dir: string, options?: ScanOptions): PlanEntity[];
11
- /**
12
- * Scan plan entities from pre-fetched file contents.
13
- * Use this when files come from an external source (e.g. GitHub API)
14
- * rather than the local filesystem.
15
- */
16
- export declare function scanPlanSources(sources: FileSource[]): PlanEntity[];
17
10
  //# sourceMappingURL=scanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAA6E,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAuNjJ,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA0BnF;AAED,8FAA8F;AAC9F,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAG9E;AAmCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,EAAE,CAyClF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAUnE"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAa,WAAW,EAAE,MAAM,YAAY,CAAC;AAIrE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAmBtE,8FAA8F;AAC9F,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAG9E;AAmCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,EAAE,CA0ClF"}