@specferret/core 0.1.4 → 0.2.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.
@@ -8,6 +8,10 @@ export interface ExtractionResult {
8
8
  shape: object;
9
9
  shape_hash: string;
10
10
  imports: string[];
11
+ /** Path to the TypeScript source file (code-first contracts only). */
12
+ sourceFile?: string;
13
+ /** TypeScript symbol name (code-first contracts only). */
14
+ sourceSymbol?: string;
11
15
  }>;
12
16
  extractedBy: 'gray-matter' | 'tree-sitter';
13
17
  extractedAt: number;
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;IACH,WAAW,EAAE,aAAa,GAAG,aAAa,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CA4C3F"}
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,sEAAsE;QACtE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,0DAA0D;QAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,WAAW,EAAE,aAAa,GAAG,aAAa,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAkD3F"}
@@ -36,6 +36,9 @@ export function extractFromSpecFile(filePath, fileContent) {
36
36
  // validateFerretSchema never throws — only warns on unsupported keywords
37
37
  const validation = validateFerretSchema(ferret.shape, filePath);
38
38
  validation.warnings.forEach((w) => process.stderr.write(w + '\n'));
39
+ const source = ferret.source;
40
+ const sourceFile = typeof source?.file === 'string' ? source.file : undefined;
41
+ const sourceSymbol = typeof source?.symbol === 'string' ? source.symbol : undefined;
39
42
  return {
40
43
  filePath,
41
44
  fileType: 'spec',
@@ -46,6 +49,8 @@ export function extractFromSpecFile(filePath, fileContent) {
46
49
  shape: ferret.shape,
47
50
  shape_hash: hashSchema(ferret.shape),
48
51
  imports: Array.isArray(ferret.imports) ? ferret.imports : [],
52
+ ...(sourceFile !== undefined && { sourceFile }),
53
+ ...(sourceSymbol !== undefined && { sourceSymbol }),
49
54
  },
50
55
  ],
51
56
  extractedBy: 'gray-matter',
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kFAAkF;AAElF,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAkBvC;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAmB;IACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAChE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,MAAM,CAAC,EAAY;gBACvB,IAAI,EAAE,cAAc,CAAC,KAAK;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAe;gBAC7B,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,OAAoB,CAAC,CAAC,CAAC,EAAE;aAC3E;SACF;QACD,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/extractor/frontmatter.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kFAAkF;AAElF,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAsBvC;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,WAAmB;IACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,QAAQ;YACR,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,MAAM,UAAU,GAAG,oBAAoB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAChE,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,CAAC,MAA0D,CAAC;IACjF,MAAM,UAAU,GAAG,OAAO,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,YAAY,GAAG,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpF,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE;YACT;gBACE,EAAE,EAAE,MAAM,CAAC,EAAY;gBACvB,IAAI,EAAE,cAAc,CAAC,KAAK;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAe;gBAC7B,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,OAAoB,CAAC,CAAC,CAAC,EAAE;gBAC1E,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;gBAC/C,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,CAAC;aACpD;SACF;QACD,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ export type UpwardDriftClass = 'BREAKING' | 'NON_BREAKING' | 'NOOP';
2
+ export interface UpwardDriftResult {
3
+ contractId: string;
4
+ driftClass: UpwardDriftClass;
5
+ sourceFile: string;
6
+ sourceSymbol: string;
7
+ reason: string;
8
+ }
9
+ /**
10
+ * Classifies the drift between a declared contract schema and the live code-derived schema.
11
+ *
12
+ * Input:
13
+ * - declaredSchema: the schema declared in the .contract.md frontmatter (the spec)
14
+ * - codeSchema: the schema extracted from the TypeScript source at lint time
15
+ *
16
+ * Output:
17
+ * - BREAKING: code change breaks the declared contract (required field removed, type changed, etc.)
18
+ * - NON_BREAKING: code change is additive but not declared (optional field added, enum value added)
19
+ * - NOOP: code and declared schema are semantically identical (hash-stable, no action needed)
20
+ *
21
+ * Uses the same classification taxonomy as compareSchemas for consistency.
22
+ * No-op formatting changes (property reorder with stable hash) return NOOP.
23
+ */
24
+ export declare function classifyUpwardDrift(contractId: string, declaredSchema: unknown, codeSchema: unknown, sourceFile: string, sourceSymbol: string): UpwardDriftResult;
25
+ //# sourceMappingURL=upward-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upward-classifier.d.ts","sourceRoot":"","sources":["../../src/extractor/upward-classifier.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,cAAc,GAAG,MAAM,CAAC;AAEpE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,OAAO,EACvB,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,iBAAiB,CA8BnB"}
@@ -0,0 +1,48 @@
1
+ // Pure function. No I/O. No side effects. Ever.
2
+ // Upward drift classifier — detects when a TypeScript implementation diverges from
3
+ // its declared contract schema (code → spec direction).
4
+ import { compareSchemas } from './validator.js';
5
+ /**
6
+ * Classifies the drift between a declared contract schema and the live code-derived schema.
7
+ *
8
+ * Input:
9
+ * - declaredSchema: the schema declared in the .contract.md frontmatter (the spec)
10
+ * - codeSchema: the schema extracted from the TypeScript source at lint time
11
+ *
12
+ * Output:
13
+ * - BREAKING: code change breaks the declared contract (required field removed, type changed, etc.)
14
+ * - NON_BREAKING: code change is additive but not declared (optional field added, enum value added)
15
+ * - NOOP: code and declared schema are semantically identical (hash-stable, no action needed)
16
+ *
17
+ * Uses the same classification taxonomy as compareSchemas for consistency.
18
+ * No-op formatting changes (property reorder with stable hash) return NOOP.
19
+ */
20
+ export function classifyUpwardDrift(contractId, declaredSchema, codeSchema, sourceFile, sourceSymbol) {
21
+ const comparison = compareSchemas(declaredSchema, codeSchema);
22
+ if (comparison.classification === 'no-change') {
23
+ return {
24
+ contractId,
25
+ driftClass: 'NOOP',
26
+ sourceFile,
27
+ sourceSymbol,
28
+ reason: comparison.reason,
29
+ };
30
+ }
31
+ if (comparison.classification === 'breaking') {
32
+ return {
33
+ contractId,
34
+ driftClass: 'BREAKING',
35
+ sourceFile,
36
+ sourceSymbol,
37
+ reason: comparison.reason,
38
+ };
39
+ }
40
+ return {
41
+ contractId,
42
+ driftClass: 'NON_BREAKING',
43
+ sourceFile,
44
+ sourceSymbol,
45
+ reason: comparison.reason,
46
+ };
47
+ }
48
+ //# sourceMappingURL=upward-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upward-classifier.js","sourceRoot":"","sources":["../../src/extractor/upward-classifier.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,mFAAmF;AACnF,wDAAwD;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAYhD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,cAAuB,EACvB,UAAmB,EACnB,UAAkB,EAClB,YAAoB;IAEpB,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAE9D,IAAI,UAAU,CAAC,cAAc,KAAK,WAAW,EAAE,CAAC;QAC9C,OAAO;YACL,UAAU;YACV,UAAU,EAAE,MAAM;YAClB,UAAU;YACV,YAAY;YACZ,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;QAC7C,OAAO;YACL,UAAU;YACV,UAAU,EAAE,UAAU;YACtB,UAAU;YACV,YAAY;YACZ,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU;QACV,UAAU,EAAE,cAAc;QAC1B,UAAU;QACV,YAAY;QACZ,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from './extractor/typescript.js';
3
3
  export * from './extractor/validator.js';
4
4
  export * from './extractor/contract-types.js';
5
5
  export * from './extractor/hash.js';
6
+ export * from './extractor/upward-classifier.js';
6
7
  export * from './context/index.js';
7
8
  export * from './store/types.js';
8
9
  export * from './store/sqlite.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,kCAAkC,CAAC;AACjD,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './extractor/typescript.js';
5
5
  export * from './extractor/validator.js';
6
6
  export * from './extractor/contract-types.js';
7
7
  export * from './extractor/hash.js';
8
+ export * from './extractor/upward-classifier.js';
8
9
  export * from './context/index.js';
9
10
  export * from './store/types.js';
10
11
  export * from './store/sqlite.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,4EAA4E;AAE5E,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,4EAA4E;AAE5E,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,cAAc,kCAAkC,CAAC;AACjD,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { DBStore, FerretNode, FerretContract, FerretDependency, FerretReconciliationLog, FerretPlacementDecision, NodeStatus } from "./types.js";
1
+ import type { DBStore, FerretNode, FerretContract, FerretDependency, FerretReconciliationLog, FerretPlacementDecision, NodeStatus } from './types.js';
2
2
  export declare class SqliteStore implements DBStore {
3
3
  private db;
4
4
  private dbPath;
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/store/sqlite.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,OAAO,EACP,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAY,YAAW,OAAO;IACzC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,UAAU,CAAC,EAAE,MAAM;IAWzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyErB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAO/D,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3C,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAMtC,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBvD,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7D,gCAAgC,CACpC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC;IAsBV,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAMjC,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAM3D,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAMzC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAOvD,eAAe,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAM9C,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE,uBAAuB,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAepE,qBAAqB,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAM3D,uBAAuB,CAC3B,QAAQ,EAAE,uBAAuB,GAChC,OAAO,CAAC,IAAI,CAAC;IAcV,qBAAqB,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;CAKlE"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/store/sqlite.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtJ,qBAAa,WAAY,YAAW,OAAO;IACzC,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,UAAU,CAAC,EAAE,MAAM;IAMzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA2ErB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAK/D,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3C,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAItC,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BvD,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7D,gCAAgC,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBlG,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAIjC,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAI3D,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAIzC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAKvD,eAAe,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI9C,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,uBAAuB,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IASpE,qBAAqB,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAM3D,uBAAuB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IASzE,qBAAqB,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;CAGlE"}
@@ -1,38 +1,33 @@
1
- import { Database } from "bun:sqlite";
2
- import * as path from "node:path";
3
- import * as fs from "node:fs";
4
- import { randomUUID } from "node:crypto";
5
- import { findProjectRoot } from "../utils/paths.js";
1
+ import { Database } from 'bun:sqlite';
2
+ import * as path from 'node:path';
3
+ import * as fs from 'node:fs';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { findProjectRoot } from '../utils/paths.js';
6
6
  export class SqliteStore {
7
7
  db = null;
8
8
  dbPath;
9
9
  constructor(customPath) {
10
10
  const root = findProjectRoot();
11
- const defaultPath = path.join(root, ".ferret", "graph.db");
12
- this.dbPath =
13
- customPath === ":memory:"
14
- ? ":memory:"
15
- : customPath
16
- ? path.resolve(root, customPath)
17
- : defaultPath;
11
+ const defaultPath = path.join(root, '.ferret', 'graph.db');
12
+ this.dbPath = customPath === ':memory:' ? ':memory:' : customPath ? path.resolve(root, customPath) : defaultPath;
18
13
  }
19
14
  async init() {
20
15
  if (this.db)
21
16
  return;
22
- if (this.dbPath !== ":memory:") {
17
+ if (this.dbPath !== ':memory:') {
23
18
  const ferretDir = path.dirname(this.dbPath);
24
19
  if (!fs.existsSync(ferretDir)) {
25
20
  fs.mkdirSync(ferretDir, { recursive: true });
26
21
  }
27
- const gitignorePath = path.join(ferretDir, ".gitignore");
22
+ const gitignorePath = path.join(ferretDir, '.gitignore');
28
23
  try {
29
- fs.writeFileSync(gitignorePath, "*\n!.gitignore\n!context.json\n", "utf-8");
24
+ fs.writeFileSync(gitignorePath, '*\n!.gitignore\n!context.json\n', 'utf-8');
30
25
  }
31
26
  catch { }
32
27
  }
33
28
  this.db = new Database(this.dbPath);
34
- this.db.exec("PRAGMA journal_mode = WAL;");
35
- this.db.exec("PRAGMA foreign_keys = ON;");
29
+ this.db.exec('PRAGMA journal_mode = WAL;');
30
+ this.db.exec('PRAGMA foreign_keys = ON;');
36
31
  this.db.exec(`
37
32
  CREATE TABLE IF NOT EXISTS ferret_nodes (
38
33
  id TEXT PRIMARY KEY,
@@ -80,6 +75,14 @@ export class SqliteStore {
80
75
  this.db.exec(`ALTER TABLE ferret_contracts ADD COLUMN shape_schema TEXT NOT NULL DEFAULT '{}';`);
81
76
  }
82
77
  catch { }
78
+ try {
79
+ this.db.exec(`ALTER TABLE ferret_contracts ADD COLUMN code_source_file TEXT;`);
80
+ }
81
+ catch { }
82
+ try {
83
+ this.db.exec(`ALTER TABLE ferret_contracts ADD COLUMN code_source_symbol TEXT;`);
84
+ }
85
+ catch { }
83
86
  }
84
87
  async close() {
85
88
  if (this.db) {
@@ -88,7 +91,7 @@ export class SqliteStore {
88
91
  }
89
92
  }
90
93
  async getNodeByFilePath(filePath) {
91
- const row = this.db.prepare("SELECT * FROM ferret_nodes WHERE file_path = ?").get(filePath);
94
+ const row = this.db.prepare('SELECT * FROM ferret_nodes WHERE file_path = ?').get(filePath);
92
95
  return row ?? null;
93
96
  }
94
97
  async upsertNode(node) {
@@ -103,19 +106,21 @@ export class SqliteStore {
103
106
  `).run(node.id, node.file_path, node.hash, node.status);
104
107
  }
105
108
  async getAllContractIds() {
106
- return this.db.prepare("SELECT id FROM ferret_contracts").all().map((r) => r.id);
109
+ return this.db.prepare('SELECT id FROM ferret_contracts').all().map((r) => r.id);
107
110
  }
108
111
  async upsertContract(contract) {
109
112
  this.db.prepare(`
110
- INSERT INTO ferret_contracts (id, node_id, shape_hash, shape_schema, type, status)
111
- VALUES (?, ?, ?, ?, ?, ?)
113
+ INSERT INTO ferret_contracts (id, node_id, shape_hash, shape_schema, type, status, code_source_file, code_source_symbol)
114
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
112
115
  ON CONFLICT(id) DO UPDATE SET
113
116
  node_id = excluded.node_id,
114
117
  shape_hash = excluded.shape_hash,
115
118
  shape_schema = excluded.shape_schema,
116
119
  type = excluded.type,
117
- status = excluded.status
118
- `).run(contract.id, contract.node_id, contract.shape_hash, contract.shape_schema, contract.type, contract.status);
120
+ status = excluded.status,
121
+ code_source_file = excluded.code_source_file,
122
+ code_source_symbol = excluded.code_source_symbol
123
+ `).run(contract.id, contract.node_id, contract.shape_hash, contract.shape_schema, contract.type, contract.status, contract.code_source_file ?? null, contract.code_source_symbol ?? null);
119
124
  }
120
125
  async upsertDependency(dependency) {
121
126
  this.db.prepare(`
@@ -126,7 +131,7 @@ export class SqliteStore {
126
131
  }
127
132
  async replaceDependenciesForSourceNode(sourceNodeId, targetContractIds) {
128
133
  const uniqueTargets = [...new Set(targetContractIds)].sort();
129
- const deleteStatement = this.db.prepare("DELETE FROM ferret_dependencies WHERE source_node_id = ?");
134
+ const deleteStatement = this.db.prepare('DELETE FROM ferret_dependencies WHERE source_node_id = ?');
130
135
  const insertStatement = this.db.prepare(`
131
136
  INSERT INTO ferret_dependencies (id, source_node_id, target_contract_id)
132
137
  VALUES (?, ?, ?)
@@ -140,23 +145,23 @@ export class SqliteStore {
140
145
  transaction(sourceNodeId);
141
146
  }
142
147
  async getNodes() {
143
- return this.db.prepare("SELECT * FROM ferret_nodes").all();
148
+ return this.db.prepare('SELECT * FROM ferret_nodes').all();
144
149
  }
145
150
  async getNodesByStatus(status) {
146
- return this.db.prepare("SELECT * FROM ferret_nodes WHERE status = ?").all(status);
151
+ return this.db.prepare('SELECT * FROM ferret_nodes WHERE status = ?').all(status);
147
152
  }
148
153
  async getContracts() {
149
- return this.db.prepare("SELECT * FROM ferret_contracts").all();
154
+ return this.db.prepare('SELECT * FROM ferret_contracts').all();
150
155
  }
151
156
  async getContract(id) {
152
- const row = this.db.prepare("SELECT * FROM ferret_contracts WHERE id = ?").get(id);
157
+ const row = this.db.prepare('SELECT * FROM ferret_contracts WHERE id = ?').get(id);
153
158
  return row ?? null;
154
159
  }
155
160
  async getDependencies() {
156
- return this.db.prepare("SELECT * FROM ferret_dependencies").all();
161
+ return this.db.prepare('SELECT * FROM ferret_dependencies').all();
157
162
  }
158
163
  async updateNodeStatus(nodeId, status) {
159
- this.db.prepare("UPDATE ferret_nodes SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(status, nodeId);
164
+ this.db.prepare('UPDATE ferret_nodes SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(status, nodeId);
160
165
  }
161
166
  async insertReconciliationLog(log) {
162
167
  this.db.prepare(`
@@ -165,7 +170,7 @@ export class SqliteStore {
165
170
  `).run(log.id, log.node_id, log.triggered_by, log.resolved_by ?? null, log.resolution_notes ?? null);
166
171
  }
167
172
  async getReconciliationLogs() {
168
- return this.db.prepare("SELECT id, node_id, triggered_by, resolved_by, resolution_notes FROM ferret_reconciliation_log").all();
173
+ return this.db.prepare('SELECT id, node_id, triggered_by, resolved_by, resolution_notes FROM ferret_reconciliation_log').all();
169
174
  }
170
175
  async insertPlacementDecision(decision) {
171
176
  this.db.prepare(`
@@ -174,7 +179,7 @@ export class SqliteStore {
174
179
  `).run(decision.id, decision.node_id, decision.placed_by, decision.reasoning ?? null);
175
180
  }
176
181
  async getPlacementDecisions() {
177
- return this.db.prepare("SELECT id, node_id, placed_by, reasoning FROM ferret_placement_decisions").all();
182
+ return this.db.prepare('SELECT id, node_id, placed_by, reasoning FROM ferret_placement_decisions').all();
178
183
  }
179
184
  }
180
185
  //# sourceMappingURL=sqlite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/store/sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/store/sqlite.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- export type NodeStatus = "stable" | "needs-review" | "roadmap" | "blocked";
2
- export type ContractStatus = "stable" | "roadmap" | "needs-review";
1
+ export type NodeStatus = 'stable' | 'needs-review' | 'roadmap' | 'blocked';
2
+ export type ContractStatus = 'stable' | 'roadmap' | 'needs-review';
3
3
  export interface FerretNode {
4
4
  id: string;
5
5
  file_path: string;
@@ -14,6 +14,10 @@ export interface FerretContract {
14
14
  shape_schema: string;
15
15
  type: string;
16
16
  status: ContractStatus;
17
+ /** Path to the TypeScript file this contract was generated from (code-first contracts only). */
18
+ code_source_file?: string;
19
+ /** TypeScript symbol name this contract was generated from (code-first contracts only). */
20
+ code_source_symbol?: string;
17
21
  }
18
22
  export interface FerretDependency {
19
23
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/store/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/store/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specferret/core",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "SpecFerret core engine — spec drift detection.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -215,3 +215,77 @@ ferret:
215
215
  assert.equal(r1.contracts[0].shape_hash, r2.contracts[0].shape_hash);
216
216
  });
217
217
  });
218
+
219
+ describe('extractFromSpecFile — S50 source block', () => {
220
+ const SPEC_WITH_SOURCE = `---
221
+ ferret:
222
+ id: auth.jwt
223
+ type: type
224
+ source:
225
+ file: src/auth/jwt.ts
226
+ symbol: JwtPayload
227
+ shape:
228
+ type: object
229
+ properties:
230
+ sub:
231
+ type: string
232
+ required: [sub]
233
+ ---
234
+ `;
235
+
236
+ const SPEC_WITHOUT_SOURCE = `---
237
+ ferret:
238
+ id: auth.jwt
239
+ type: type
240
+ shape:
241
+ type: object
242
+ properties:
243
+ sub:
244
+ type: string
245
+ required: [sub]
246
+ ---
247
+ `;
248
+
249
+ it('parses source.file and source.symbol when present', () => {
250
+ const result = extractFromSpecFile('contracts/auth/jwt.contract.md', SPEC_WITH_SOURCE);
251
+ assert.equal(result.contracts.length, 1);
252
+ assert.equal(result.contracts[0].sourceFile, 'src/auth/jwt.ts');
253
+ assert.equal(result.contracts[0].sourceSymbol, 'JwtPayload');
254
+ });
255
+
256
+ it('has undefined sourceFile and sourceSymbol when source block absent', () => {
257
+ const result = extractFromSpecFile('contracts/auth/jwt.contract.md', SPEC_WITHOUT_SOURCE);
258
+ assert.equal(result.contracts.length, 1);
259
+ assert.equal(result.contracts[0].sourceFile, undefined);
260
+ assert.equal(result.contracts[0].sourceSymbol, undefined);
261
+ });
262
+
263
+ it('ignores source block with non-string fields gracefully', () => {
264
+ const specBadSource = `---
265
+ ferret:
266
+ id: auth.jwt
267
+ type: type
268
+ source:
269
+ file: 42
270
+ symbol: [not, a, string]
271
+ shape:
272
+ type: object
273
+ ---
274
+ `;
275
+ const result = extractFromSpecFile('contracts/auth/jwt.contract.md', specBadSource);
276
+ assert.equal(result.contracts[0].sourceFile, undefined);
277
+ assert.equal(result.contracts[0].sourceSymbol, undefined);
278
+ });
279
+
280
+ it('source block does not affect shape_hash', () => {
281
+ const r1 = extractFromSpecFile('contracts/a.contract.md', SPEC_WITH_SOURCE);
282
+ const r2 = extractFromSpecFile('contracts/b.contract.md', SPEC_WITHOUT_SOURCE);
283
+ assert.equal(r1.contracts[0].shape_hash, r2.contracts[0].shape_hash);
284
+ });
285
+
286
+ it('identical source blocks produce identical shape_hash (deterministic snapshot)', () => {
287
+ const r1 = extractFromSpecFile('contracts/a.contract.md', SPEC_WITH_SOURCE);
288
+ const r2 = extractFromSpecFile('contracts/b.contract.md', SPEC_WITH_SOURCE);
289
+ assert.equal(r1.contracts[0].shape_hash, r2.contracts[0].shape_hash);
290
+ });
291
+ });
@@ -15,6 +15,10 @@ export interface ExtractionResult {
15
15
  shape: object;
16
16
  shape_hash: string;
17
17
  imports: string[];
18
+ /** Path to the TypeScript source file (code-first contracts only). */
19
+ sourceFile?: string;
20
+ /** TypeScript symbol name (code-first contracts only). */
21
+ sourceSymbol?: string;
18
22
  }>;
19
23
  extractedBy: 'gray-matter' | 'tree-sitter';
20
24
  extractedAt: number; // unix ms
@@ -59,6 +63,10 @@ export function extractFromSpecFile(filePath: string, fileContent: string): Extr
59
63
  const validation = validateFerretSchema(ferret.shape, filePath);
60
64
  validation.warnings.forEach((w) => process.stderr.write(w + '\n'));
61
65
 
66
+ const source = ferret.source as { file?: unknown; symbol?: unknown } | undefined;
67
+ const sourceFile = typeof source?.file === 'string' ? source.file : undefined;
68
+ const sourceSymbol = typeof source?.symbol === 'string' ? source.symbol : undefined;
69
+
62
70
  return {
63
71
  filePath,
64
72
  fileType: 'spec',
@@ -69,6 +77,8 @@ export function extractFromSpecFile(filePath: string, fileContent: string): Extr
69
77
  shape: ferret.shape as object,
70
78
  shape_hash: hashSchema(ferret.shape),
71
79
  imports: Array.isArray(ferret.imports) ? (ferret.imports as string[]) : [],
80
+ ...(sourceFile !== undefined && { sourceFile }),
81
+ ...(sourceSymbol !== undefined && { sourceSymbol }),
72
82
  },
73
83
  ],
74
84
  extractedBy: 'gray-matter',