@skill-map/testkit 0.3.0 → 0.3.2

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 (2) hide show
  1. package/README.md +22 -22
  2. package/package.json +2 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # `@skill-map/testkit`
2
2
 
3
- Kernel mocks and builders for plugin authors. Unit-test detectors, rules, and formatters without spinning up a real kernel or DB.
3
+ Kernel mocks and builders for plugin authors. Unit-test Extractors, Rules, and Formatters without spinning up a real kernel or DB.
4
4
 
5
5
  The full plugin contract lives in [`spec/plugin-author-guide.md`](../spec/plugin-author-guide.md). This README is a fast on-ramp: how to ship the smallest viable plugin and validate it with the testkit.
6
6
 
@@ -20,7 +20,7 @@ A plugin is a directory with one manifest and one extension file:
20
20
  my-plugin/
21
21
  ├── plugin.json
22
22
  └── extensions/
23
- └── my-detector.mjs
23
+ └── my-extractor.js
24
24
  ```
25
25
 
26
26
  `plugin.json`:
@@ -30,54 +30,54 @@ my-plugin/
30
30
  "id": "my-plugin",
31
31
  "version": "1.0.0",
32
32
  "specCompat": "^1.0.0",
33
- "extensions": ["./extensions/my-detector.mjs"]
33
+ "extensions": ["./extensions/my-extractor.js"]
34
34
  }
35
35
  ```
36
36
 
37
37
  The directory name MUST equal `id`. Cross-root id collisions block both plugins.
38
38
 
39
- `extensions/my-detector.mjs` — a detector that emits one `references` link per `[[ref:<name>]]` token in the body:
39
+ `extensions/my-extractor.js` — an Extractor that emits one `references` link per `[[ref:<name>]]` token in the body:
40
40
 
41
41
  ```javascript
42
42
  export default {
43
- id: 'my-detector',
44
- kind: 'detector',
43
+ id: 'my-extractor',
44
+ kind: 'extractor',
45
45
  version: '1.0.0',
46
46
  emitsLinkKinds: ['references'],
47
47
  defaultConfidence: 'medium',
48
48
  scope: 'body',
49
- detect(ctx) {
50
- const out = [];
49
+ extract(ctx) {
51
50
  for (const m of ctx.body.matchAll(/\[\[ref:([a-z0-9-]+)\]\]/gi)) {
52
- out.push({
51
+ ctx.emitLink({
53
52
  source: ctx.node.path,
54
53
  target: m[1].toLowerCase(),
55
54
  kind: 'references',
56
55
  confidence: 'medium',
57
- sources: ['my-detector'],
56
+ sources: ['my-extractor'],
58
57
  trigger: { originalTrigger: m[0], normalizedTrigger: m[0].toLowerCase() },
59
58
  });
60
59
  }
61
- return out;
62
60
  },
63
61
  };
64
62
  ```
65
63
 
66
- The extension's `id` is short (`my-detector`); the kernel composes the qualified id `my-plugin/my-detector` from the manifest. Pick a token syntax that does not collide with the built-in `@<token>` and `/<token>` detectors.
64
+ The extension's `id` is short (`my-extractor`); the kernel composes the qualified id `my-plugin/my-extractor` from the manifest. Pick a token syntax that does not collide with the built-in `@<token>` and `/<token>` Extractors.
67
65
 
68
- The four other extension kinds (`provider`, `rule`, `formatter`, `action`) follow the same shape see [`spec/plugin-author-guide.md`](../spec/plugin-author-guide.md#the-five-extension-kinds).
66
+ The `extract(ctx) void` shape is normative: Extractors emit through three callbacks (`ctx.emitLink`, `ctx.enrichNode`, `ctx.store`) instead of returning links. See [`spec/architecture.md` §Extractor · output callbacks](../spec/architecture.md#extractor--output-callbacks).
67
+
68
+ The five other extension kinds (`provider`, `rule`, `formatter`, `action`, `hook`) follow the same shape — see [`spec/plugin-author-guide.md`](../spec/plugin-author-guide.md#the-six-extension-kinds).
69
69
 
70
70
  ## Test it
71
71
 
72
72
  ```javascript
73
- // test/my-detector.test.mjs
73
+ // test/my-extractor.test.js
74
74
  import { test } from 'node:test';
75
75
  import { strictEqual } from 'node:assert';
76
- import { node, runDetectorOnFixture } from '@skill-map/testkit';
77
- import detector from '../extensions/my-detector.mjs';
76
+ import { node, runExtractorOnFixture } from '@skill-map/testkit';
77
+ import extractor from '../extensions/my-extractor.js';
78
78
 
79
79
  test('emits one link per [[ref:<name>]]', async () => {
80
- const links = await runDetectorOnFixture(detector, {
80
+ const { links } = await runExtractorOnFixture(extractor, {
81
81
  body: 'See [[ref:architect]] and [[ref:sre]].',
82
82
  context: { node: node({ path: 'sample.md' }) },
83
83
  });
@@ -87,23 +87,23 @@ test('emits one link per [[ref:<name>]]', async () => {
87
87
  ```
88
88
 
89
89
  ```bash
90
- node --test test/my-detector.test.mjs
90
+ node --test test/my-extractor.test.js
91
91
  ```
92
92
 
93
- The testkit also ships `runRuleOnGraph` (rules), `runFormatterOnGraph` (formatters), `makeFakeStorage` (KV storage), and `makeFakeRunner` (probabilistic mode). Full surface in [`index.ts`](./index.ts).
93
+ The testkit also ships `runRuleOnGraph` (Rules), `runFormatterOnGraph` (Formatters), `makeFakeStorage` (KV storage), and `makeFakeRunner` (probabilistic mode). Full surface in [`index.ts`](./index.ts).
94
94
 
95
95
  ## Run it under the real CLI
96
96
 
97
97
  ```bash
98
98
  mkdir -p .skill-map/plugins
99
99
  cp -r my-plugin .skill-map/plugins/
100
- sm plugins list # status should be: loaded
100
+ sm plugins list # status should be: enabled
101
101
  sm scan
102
102
  ```
103
103
 
104
104
  Discovery roots (in order): `<project>/.skill-map/plugins/`, then `~/.skill-map/plugins/`. Override with `--plugin-dir <path>`.
105
105
 
106
- If `sm plugins list` shows anything other than `loaded` / `disabled`, run `sm plugins doctor` for the diagnostic and check the [Diagnostics table](../spec/plugin-author-guide.md#diagnostics).
106
+ If `sm plugins list` shows anything other than `enabled` / `disabled`, run `sm plugins doctor` for the diagnostic and check the [Diagnostics table](../spec/plugin-author-guide.md#diagnostics).
107
107
 
108
108
  ## A complete worked example
109
109
 
@@ -118,4 +118,4 @@ If `sm plugins list` shows anything other than `loaded` / `disabled`, run `sm pl
118
118
 
119
119
  ## Stability
120
120
 
121
- `experimental` while Step 9 is in flight. The detector / rule / formatter helpers and builders are intended to stay stable through v1.0; `makeFakeRunner` may change to track the Step 10 job subsystem contract.
121
+ `experimental` while Step 9 is in flight. The Extractor / Rule / Formatter helpers and builders are intended to stay stable through v1.0; `makeFakeRunner` may change to track the Step 10 job subsystem contract.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skill-map/testkit",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Kernel mocks + builders for plugin authors. Test detectors, rules, and formatters without spinning up the full skill-map runtime.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,6 +36,7 @@
36
36
  "test": "tsc --noEmit && node --import tsx --test --test-reporter=spec 'test/**/*.test.ts'",
37
37
  "test:ci": "tsc --noEmit && node --import tsx --test 'test/**/*.test.ts'",
38
38
  "test:coverage": "tsc --noEmit && node --experimental-default-config-file --import tsx --test --experimental-test-coverage 'test/**/*.test.ts'",
39
+ "validate": "npm run typecheck && npm run build && npm run test:ci",
39
40
  "clean": "rm -rf dist"
40
41
  },
41
42
  "dependencies": {