@skill-map/spec 0.1.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/CHANGELOG.md +96 -0
- package/README.md +105 -0
- package/architecture.md +218 -0
- package/cli-contract.md +336 -0
- package/conformance/README.md +140 -0
- package/conformance/cases/basic-scan.json +17 -0
- package/conformance/cases/kernel-empty-boot.json +24 -0
- package/conformance/fixtures/minimal-claude/agents/reviewer.md +16 -0
- package/conformance/fixtures/minimal-claude/commands/status.md +17 -0
- package/conformance/fixtures/minimal-claude/hooks/pre-commit.md +13 -0
- package/conformance/fixtures/minimal-claude/notes/architecture.md +11 -0
- package/conformance/fixtures/minimal-claude/skills/hello.md +22 -0
- package/conformance/fixtures/preamble-v1.txt +54 -0
- package/db-schema.md +359 -0
- package/dispatch-lifecycle.md +213 -0
- package/index.json +205 -0
- package/interfaces/security-scanner.md +233 -0
- package/job-events.md +322 -0
- package/package.json +49 -0
- package/plugin-kv-api.md +208 -0
- package/prompt-preamble.md +152 -0
- package/schemas/conformance-case.schema.json +185 -0
- package/schemas/execution-record.schema.json +88 -0
- package/schemas/frontmatter/agent.schema.json +22 -0
- package/schemas/frontmatter/base.schema.json +136 -0
- package/schemas/frontmatter/command.schema.json +39 -0
- package/schemas/frontmatter/hook.schema.json +29 -0
- package/schemas/frontmatter/note.schema.json +11 -0
- package/schemas/frontmatter/skill.schema.json +37 -0
- package/schemas/issue.schema.json +54 -0
- package/schemas/job.schema.json +75 -0
- package/schemas/link.schema.json +66 -0
- package/schemas/node.schema.json +95 -0
- package/schemas/plugins-registry.schema.json +99 -0
- package/schemas/project-config.schema.json +87 -0
- package/schemas/report-base.schema.json +41 -0
- package/schemas/scan-result.schema.json +71 -0
- package/schemas/summaries/agent.schema.json +46 -0
- package/schemas/summaries/command.schema.json +50 -0
- package/schemas/summaries/hook.schema.json +43 -0
- package/schemas/summaries/note.schema.json +37 -0
- package/schemas/summaries/skill.schema.json +57 -0
- package/versioning.md +94 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Spec changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5b3829a: Add conformance case `kernel-empty-boot`:
|
|
8
|
+
|
|
9
|
+
- New file: `spec/conformance/cases/kernel-empty-boot.json`.
|
|
10
|
+
- Exercises the boot invariant from `architecture.md`: with every adapter, detector, and rule disabled, scanning an empty scope MUST return a valid `ScanResult` with `schemaVersion: 1` and zero-filled stats.
|
|
11
|
+
- Referenced in `conformance/README.md` (§"Cases explicitly referenced elsewhere in the spec"). Entry moved from "pending" to "current" in the case inventory.
|
|
12
|
+
- Registered in `spec/index.json` and the integrity block (SHA256 regenerated).
|
|
13
|
+
|
|
14
|
+
The second pending case, `preamble-bitwise-match`, is deferred to Step 9 (requires `sm job preview` from the job subsystem).
|
|
15
|
+
|
|
16
|
+
- 4e0aec4: Initial public spec surface (`v0.1.0`):
|
|
17
|
+
|
|
18
|
+
- 21 JSON Schemas (draft 2020-12): 10 top-level, 6 frontmatter, 5 summaries.
|
|
19
|
+
- 7 prose contracts (architecture, cli-contract, dispatch-lifecycle, job-events, prompt-preamble, db-schema, plugin-kv-api).
|
|
20
|
+
- 1 interface doc (security-scanner).
|
|
21
|
+
- Conformance stub: `basic-scan` case, `minimal-claude` fixture, verbatim `preamble-v1.txt`.
|
|
22
|
+
- Machine-readable `index.json` with integrity hashes per file.
|
|
23
|
+
|
|
24
|
+
This is the first tagged release of the skill-map specification.
|
|
25
|
+
|
|
26
|
+
Changelog for the **skill-map specification**, tracked independently from the reference CLI. See `versioning.md` for the policy that governs what constitutes a patch / minor / major change.
|
|
27
|
+
|
|
28
|
+
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) as refined in `versioning.md`.
|
|
29
|
+
|
|
30
|
+
Each entry classifies changes into four sections:
|
|
31
|
+
|
|
32
|
+
- **Added** — new optional fields, schemas, or contracts.
|
|
33
|
+
- **Changed** — modifications to existing normative content. Breaking changes are called out explicitly.
|
|
34
|
+
- **Deprecated** — features scheduled for removal in a future major.
|
|
35
|
+
- **Removed** — features removed in a major bump.
|
|
36
|
+
|
|
37
|
+
Tag convention: `spec-vX.Y.Z` (distinct from CLI tags `cli-vX.Y.Z`).
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## [Unreleased]
|
|
42
|
+
|
|
43
|
+
Initial public spec bootstrap (Step 0a phases 1–3).
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Foundation:
|
|
48
|
+
- `README.md` — human-readable introduction and repo layout.
|
|
49
|
+
- `versioning.md` — evolution policy, stability tags, 3-minor deprecation window.
|
|
50
|
+
- `CHANGELOG.md` — this file.
|
|
51
|
+
- JSON Schemas (21 files, all draft 2020-12, camelCase keys):
|
|
52
|
+
- Top-level (10): `node`, `link`, `issue`, `scan-result`, `execution-record`, `project-config`, `plugins-registry`, `job`, `report-base`, `conformance-case`.
|
|
53
|
+
- Frontmatter (6): `base` + per-kind `skill` / `agent` / `command` / `hook` / `note`. Per-kind schemas extend `base` via `allOf`.
|
|
54
|
+
- Summaries (5): per-kind `skill` / `agent` / `command` / `hook` / `note`. All extend `report-base` via `allOf`.
|
|
55
|
+
- Prose contracts:
|
|
56
|
+
- `architecture.md` — hexagonal ports & adapters; 5 ports (`StoragePort`, `FilesystemPort`, `PluginLoaderPort`, `RunnerPort`, `ProgressEmitterPort`); 6 extension kinds (Adapter, Detector, Rule, Action, Audit, Renderer); kernel boundary + forbidden/permitted imports.
|
|
57
|
+
- `cli-contract.md` — CLI surface: global flags, env vars, 30+ verbs (`sm init`, `sm scan`, `sm list`, `sm show`, `sm check`, `sm findings`, `sm graph`, `sm export`, `sm job *`, `sm record`, `sm history`, `sm plugins *`, `sm audit *`, `sm db *`, `sm serve`, `sm help`), exit codes (0–5 defined, 6–15 reserved), `--json` output rules, `--format json|md|human` introspection.
|
|
58
|
+
- `dispatch-lifecycle.md` — job state machine (queued → running → completed | failed), atomic claim (`UPDATE ... RETURNING id`), duplicate prevention via `contentHash`, TTL with auto-reap, nonce authentication for `sm record`, sequential concurrency for MVP, retention and GC.
|
|
59
|
+
- `job-events.md` — canonical event stream: envelope (`type`, `timestamp`, `runId`, `jobId`, `data`), 10 event types (`run.started`, `run.reap.started`, `run.reap.completed`, `job.claimed`, `job.skipped`, `job.spawning`, `model.delta`, `job.callback.received`, `job.completed`, `job.failed`, `run.summary`), three output adapters (`pretty`, `stream-output`, `json`), ordering rules.
|
|
60
|
+
- `prompt-preamble.md` — verbatim normative preamble text that the kernel prepends to every rendered job file; `<user-content id="...">` delimiter contract with zero-width-space escaping; `safety` + `confidence` contract on model output; conformance fixture at `conformance/fixtures/preamble-v1.txt`.
|
|
61
|
+
- `db-schema.md` — engine-agnostic table catalog: three zones (`scan_*`, `state_*`, `config_*`), naming conventions (snake*case, zone prefix, `_at` / `_ms` / `_hash` / `_json` / `_count` suffixes, `is*`/`has\_` prefixes), kernel table list per zone, migration rules (`.sql`files,`NNN_snake_case.sql`, up-only, auto-backup), plugin storage modes.
|
|
62
|
+
- `plugin-kv-api.md` — `ctx.store` contract for mode A (`KvStore.get/set/delete/list`, plugin-scoped, optional node-scoped), mode B dedicated-tables rules (prefix injection, DDL validation, scoped Database wrapper), typed errors (`KvKeyInvalidError`, `KvValueNotSerializableError`, `KvValueTooLargeError`, `KvOperationFailedError`, `ScopedDbViolationError`). Mixing modes in a plugin is forbidden.
|
|
63
|
+
- Interfaces:
|
|
64
|
+
- `interfaces/security-scanner.md` — convention over the Action kind (id prefix `security-`) for third-party security scanners (Snyk, Socket, custom). Defines `SecurityReport` shape extending `report-base.schema.json`, normative finding categories, deduplication rules, aggregation via `sm findings --security`. Marked `Stability: experimental` through v0.x.
|
|
65
|
+
|
|
66
|
+
### Conventions locked (normative)
|
|
67
|
+
|
|
68
|
+
- JSON Schema dialect: draft 2020-12.
|
|
69
|
+
- Casing: camelCase for all JSON keys (domain, configs, manifests, reports); kebab-case for filenames.
|
|
70
|
+
- `$id` scheme: `https://skill-map.dev/spec/v<major>/<path>.schema.json`. `v0` throughout pre-1.0; bumps to `v1` at the first stable cut.
|
|
71
|
+
- Identity: `node.path` (relative to scope root) is the canonical node identifier in v0. Future UUID-based `node.id` lands with write-back.
|
|
72
|
+
- Required frontmatter: `name`, `description`, `metadata`, `metadata.version`.
|
|
73
|
+
- Frontmatter: `additionalProperties: true` (rules handle unknown fields). Summaries: `additionalProperties: false` (strict).
|
|
74
|
+
- Id prefixes: job `d-`, execution record `e-`, run `r-` (all `PREFIX-YYYYMMDD-HHMMSS-XXXX`).
|
|
75
|
+
- Exit codes: 0 ok / 1 issues / 2 error / 3 duplicate / 4 nonce-mismatch / 5 not-found.
|
|
76
|
+
- Deprecation window: 3 minor releases between `stable → deprecated` and removal.
|
|
77
|
+
- Storage modes: a plugin declares exactly one (`kv` or `dedicated`). Mixing forbidden.
|
|
78
|
+
|
|
79
|
+
### Conformance (stub)
|
|
80
|
+
|
|
81
|
+
- `conformance/README.md` — suite layout, case format, assertion types (`exit-code`, `json-path`, `file-exists`, `file-contains-verbatim`, `file-matches-schema`, `stderr-matches`), runner pseudocode.
|
|
82
|
+
- `conformance/fixtures/minimal-claude/` — 5 MDs (one per kind: skill, agent, command, hook, note) used as the first controlled corpus.
|
|
83
|
+
- `conformance/fixtures/preamble-v1.txt` — verbatim extraction of the preamble from `prompt-preamble.md`, checked byte-for-byte by the future `preamble-bitwise-match` case.
|
|
84
|
+
- `conformance/cases/basic-scan.json` — first declarative case. Scans the `minimal-claude` fixture; asserts `schemaVersion: 1`, 5 nodes, 0 issues.
|
|
85
|
+
|
|
86
|
+
### Packaging
|
|
87
|
+
|
|
88
|
+
- `package.json` at the spec root. Name: `@skill-map/spec`. Version `0.0.1` (first release line; spec versioning is strict pre-1.0 per `versioning.md`). `exports` surfaces `.` → `index.json`, plus every `./schemas/*.json`.
|
|
89
|
+
- `index.json` at the spec root. Machine-readable manifest of schemas, prose, interfaces, and conformance. Carries an `integrity` block with a sha256 per shipped file, deterministically regenerated by `scripts/build-spec-index.mjs`. CI blocks drift via `npm run spec:check`.
|
|
90
|
+
- `schemas/conformance-case.schema.json` — formal schema for entries under `conformance/cases/*.json`. Defines the `invoke` object and the six assertion types (`exit-code`, `json-path`, `file-exists`, `file-contains-verbatim`, `file-matches-schema`, `stderr-matches`) as a discriminated union via `oneOf`.
|
|
91
|
+
|
|
92
|
+
### Notes
|
|
93
|
+
|
|
94
|
+
- Pending for `spec-v0.1.0`: cases `kernel-empty-boot` and `preamble-bitwise-match` (referenced normatively in `architecture.md` and `prompt-preamble.md`). Land alongside Step 0b when the reference implementation exists to run them against.
|
|
95
|
+
- No tagged spec release yet. First tag (`spec-v0.1.0`) lands after Step 0b CI validates the implementation against this stub.
|
|
96
|
+
- Release pipeline: `@skill-map/spec` is published via [changesets](https://github.com/changesets/changesets). Every PR that touches `spec/` includes a `.changeset/*.md` declaring the bump; merging to `main` opens a "Version Packages" PR; merging that PR publishes to npm and tags the release. See `CONTRIBUTING.md`.
|
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# skill-map spec
|
|
2
|
+
|
|
3
|
+
The **skill-map specification** defines a vendor-neutral standard for mapping, inspecting, and managing collections of interrelated Markdown files — skills, agents, commands, hooks, and notes that compose AI-agent ecosystems (Claude Code, Codex, Gemini, Obsidian vaults, docs sites, and any future platform).
|
|
4
|
+
|
|
5
|
+
This document is the **source of truth**. The reference implementation under `../src/` conforms to this spec. Third parties can build alternative implementations (any language, any UI, any CLI) using only `spec/`, without reading the reference source.
|
|
6
|
+
|
|
7
|
+
## What this spec defines
|
|
8
|
+
|
|
9
|
+
- The **domain model**: nodes, links, issues, scan results.
|
|
10
|
+
- The **extension contract**: six extension kinds (detector, adapter, rule, action, audit, renderer) with their input/output shapes.
|
|
11
|
+
- The **CLI contract**: verb set, flags, exit codes, JSON introspection.
|
|
12
|
+
- The **persistence contract**: table catalog owned by the kernel, plugin key-value API.
|
|
13
|
+
- The **job contract**: lifecycle states, event stream, prompt preamble, dispatch semantics.
|
|
14
|
+
- The **frontmatter standard**: base fields and per-kind extensions.
|
|
15
|
+
- The **summary standard**: shape of action-produced summaries per kind.
|
|
16
|
+
- The **plugin manifest**: metadata, spec-compat range, storage mode, security declarations.
|
|
17
|
+
|
|
18
|
+
## What this spec does not define
|
|
19
|
+
|
|
20
|
+
- Language or runtime of the implementation.
|
|
21
|
+
- Database engine (spec assumes a relational, SQL-like store; engine-agnostic).
|
|
22
|
+
- UI framework, theming, layout.
|
|
23
|
+
- Test framework (conformance suite is language-neutral data, not code).
|
|
24
|
+
- Logging format, telemetry, or distribution channels.
|
|
25
|
+
- Plugin marketplace mechanics.
|
|
26
|
+
|
|
27
|
+
These are implementation decisions. The reference impl picks them (see `../CLAUDE.md` and `../ROADMAP.md`); other implementations may pick differently and still conform.
|
|
28
|
+
|
|
29
|
+
## Properties
|
|
30
|
+
|
|
31
|
+
- **Machine-readable**: all domain shapes are JSON Schemas. Validate from any language that has a JSON Schema validator.
|
|
32
|
+
- **Human-readable**: prose documents for each subsystem, with examples.
|
|
33
|
+
- **Independently versioned**: spec `v1.0.0` can be implemented by CLI `v0.3.2`. See `versioning.md`.
|
|
34
|
+
- **Platform-neutral**: no platform (Claude Code, Obsidian, …) is privileged. Each is expressed as an adapter extension.
|
|
35
|
+
- **Conformance-tested**: every conforming implementation passes the suite under `conformance/`. Pass/fail is binary.
|
|
36
|
+
|
|
37
|
+
## Repo layout
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
spec/
|
|
41
|
+
├── README.md ← this file
|
|
42
|
+
├── CHANGELOG.md ← spec history (independent from CLI)
|
|
43
|
+
├── versioning.md ← evolution policy
|
|
44
|
+
├── architecture.md ← hexagonal ports & adapters (Step 0a phase 3)
|
|
45
|
+
├── cli-contract.md ← verbs, flags, exit codes, JSON introspection (Step 0a phase 3)
|
|
46
|
+
├── job-events.md ← canonical event stream schema (Step 0a phase 3)
|
|
47
|
+
├── prompt-preamble.md ← canonical injection-mitigation preamble (Step 0a phase 3)
|
|
48
|
+
├── db-schema.md ← table catalog (kernel-owned) (Step 0a phase 3)
|
|
49
|
+
├── plugin-kv-api.md ← ctx.store contract for storage mode A (Step 0a phase 3)
|
|
50
|
+
├── dispatch-lifecycle.md ← queued → running → completed | failed (Step 0a phase 3)
|
|
51
|
+
├── schemas/ ← JSON Schemas (Step 0a phase 2)
|
|
52
|
+
│ ├── node.schema.json
|
|
53
|
+
│ ├── link.schema.json
|
|
54
|
+
│ ├── issue.schema.json
|
|
55
|
+
│ ├── scan-result.schema.json
|
|
56
|
+
│ ├── execution-record.schema.json
|
|
57
|
+
│ ├── project-config.schema.json
|
|
58
|
+
│ ├── plugins-registry.schema.json
|
|
59
|
+
│ ├── job.schema.json
|
|
60
|
+
│ ├── report-base.schema.json
|
|
61
|
+
│ ├── frontmatter/
|
|
62
|
+
│ │ ├── base.schema.json
|
|
63
|
+
│ │ ├── skill.schema.json
|
|
64
|
+
│ │ ├── agent.schema.json
|
|
65
|
+
│ │ ├── command.schema.json
|
|
66
|
+
│ │ ├── hook.schema.json
|
|
67
|
+
│ │ └── note.schema.json
|
|
68
|
+
│ └── summaries/
|
|
69
|
+
│ ├── skill.schema.json
|
|
70
|
+
│ ├── agent.schema.json
|
|
71
|
+
│ ├── command.schema.json
|
|
72
|
+
│ ├── hook.schema.json
|
|
73
|
+
│ └── note.schema.json
|
|
74
|
+
├── interfaces/
|
|
75
|
+
│ └── security-scanner.md ← contract for third-party security plugins
|
|
76
|
+
└── conformance/
|
|
77
|
+
├── fixtures/ ← controlled MD corpora
|
|
78
|
+
└── cases/ ← declarative test cases (JSON)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## How to read this spec
|
|
82
|
+
|
|
83
|
+
- **Building a tool or plugin that consumes skill-map output?** Start with `schemas/scan-result.schema.json` and `schemas/node.schema.json`.
|
|
84
|
+
- **Building a custom detector, rule, or renderer?** Read `architecture.md`, then the relevant schema.
|
|
85
|
+
- **Building an alternative CLI implementation?** Read `cli-contract.md` and run `conformance/`.
|
|
86
|
+
- **Integrating a new platform (adapter)?** Read `architecture.md` §adapters, then the Claude adapter source in `../src/extensions/adapters/claude/` as a worked example.
|
|
87
|
+
- **Shipping a job-running runner?** Read `job-events.md`, `dispatch-lifecycle.md`, `prompt-preamble.md`.
|
|
88
|
+
|
|
89
|
+
## Relationship to the reference implementation
|
|
90
|
+
|
|
91
|
+
The reference implementation (`../src/`) is one conforming consumer of this spec. It ships the CLI binary `sm`, a built-in SQLite storage adapter, and a bundle of default extensions.
|
|
92
|
+
|
|
93
|
+
The reference impl has no privileged access to the spec. Breaking changes to the spec must follow `versioning.md` regardless of reference-impl convenience.
|
|
94
|
+
|
|
95
|
+
When spec and reference impl disagree, the spec wins. File an issue; one of them is wrong.
|
|
96
|
+
|
|
97
|
+
## Distribution
|
|
98
|
+
|
|
99
|
+
- This directory is published to npm as `@skill-map/spec`.
|
|
100
|
+
- Schemas are also published to JSON Schema Store when the domain is live.
|
|
101
|
+
- Canonical URLs (stable across versions) land with Step 13.
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT. See `../LICENSE`.
|
package/architecture.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Normative description of skill-map's internal boundaries: the **kernel**, the **ports** it exposes, the **adapters** that drive and serve it, and the six **extension kinds** that live outside the kernel.
|
|
4
|
+
|
|
5
|
+
Any conforming implementation — reference or third-party — MUST respect these boundaries. The conformance suite under `conformance/` enforces them.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Layering
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Driving adapters (primary)
|
|
13
|
+
│
|
|
14
|
+
┌─────────┐ ┌─────────┐ ┌──────┐
|
|
15
|
+
│ CLI │ │ Server │ │Skill │
|
|
16
|
+
└────┬────┘ └────┬────┘ └───┬──┘
|
|
17
|
+
│ │ │
|
|
18
|
+
└─────────────────┼────────────────┘
|
|
19
|
+
▼
|
|
20
|
+
┌──────────────┐
|
|
21
|
+
│ Kernel │ ← domain core
|
|
22
|
+
│ │
|
|
23
|
+
│ Registry │
|
|
24
|
+
│ Orchestrator│
|
|
25
|
+
│ Use cases │
|
|
26
|
+
└──┬───┬───┬───┘
|
|
27
|
+
│ │ │
|
|
28
|
+
┌─────────────┘ │ └──────────────┐
|
|
29
|
+
▼ ▼ ▼
|
|
30
|
+
┌────────┐ ┌─────────┐ ┌─────────┐
|
|
31
|
+
│ Storage│ │ FS │ │ Plugins │
|
|
32
|
+
└────────┘ └─────────┘ └─────────┘
|
|
33
|
+
Driven adapters (secondary)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- **Driving adapters** call into the kernel. The spec defines three: `CLI`, `Server`, `Skill`. A fourth driving adapter MAY be built by third parties (IDE extension, VSCode command palette, TUI) without spec changes.
|
|
37
|
+
- **Driven adapters** implement ports the kernel declares. An implementation MUST ship adapters for every port — no port may be left unimplemented at runtime.
|
|
38
|
+
- **Kernel** is domain-pure. It never imports a filesystem API, a database driver, or a subprocess spawner directly. All IO crosses a port.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Ports
|
|
43
|
+
|
|
44
|
+
An implementation MUST expose these five ports. Each is an interface (TypeScript, in the reference impl; equivalent in other languages).
|
|
45
|
+
|
|
46
|
+
### `StoragePort`
|
|
47
|
+
|
|
48
|
+
Persistence for all kernel tables in all three zones (`scan_*`, `state_*`, `config_*`). Exposes typed repositories, not raw SQL. Implementations MAY back this with SQLite, Postgres, in-memory, or anything else, as long as:
|
|
49
|
+
|
|
50
|
+
- Transactional semantics for atomic claim (see `dispatch-lifecycle.md`).
|
|
51
|
+
- Migration application with `PRAGMA user_version`-equivalent tracking.
|
|
52
|
+
- Read isolation sufficient to avoid phantom reads across a single scan write.
|
|
53
|
+
|
|
54
|
+
The reference impl backs this with `node:sqlite` + Kysely + `CamelCasePlugin`.
|
|
55
|
+
|
|
56
|
+
### `FilesystemPort`
|
|
57
|
+
|
|
58
|
+
Walks roots, reads node files, reports mtime/size. Abstracts away platform-specific path handling and test fixtures.
|
|
59
|
+
|
|
60
|
+
Operations: `walk(roots, ignore)`, `readNode(path)`, `stat(path)`, `writeJobFile(path, content)`, `ensureDir(path)`.
|
|
61
|
+
|
|
62
|
+
The reference impl uses real `node:fs` in production and an in-memory fixture in tests.
|
|
63
|
+
|
|
64
|
+
### `PluginLoaderPort`
|
|
65
|
+
|
|
66
|
+
Discovers plugin directories, reads `plugin.json`, checks `specCompat`, dynamically imports extension files, returns loaded extension descriptors ready to register.
|
|
67
|
+
|
|
68
|
+
Operations: `discover(scopes)`, `load(pluginPath)`, `validateManifest(json)`.
|
|
69
|
+
|
|
70
|
+
### `RunnerPort`
|
|
71
|
+
|
|
72
|
+
Executes an action against a job file. Returns a report reference (or an error) plus runner-side metrics (duration, tokens, exit code).
|
|
73
|
+
|
|
74
|
+
Operations: `run(jobFilePath, options)` → `{ reportPath, tokensIn, tokensOut, durationMs, exitCode } | Error`.
|
|
75
|
+
|
|
76
|
+
Two reference implementations:
|
|
77
|
+
- `ClaudeCliRunner` — subprocess `claude -p < jobfile`.
|
|
78
|
+
- `MockRunner` — deterministic fake for tests.
|
|
79
|
+
|
|
80
|
+
The Skill runner does NOT implement this port: it runs inside an agent session and closes jobs via `sm record` callback. See `dispatch-lifecycle.md`.
|
|
81
|
+
|
|
82
|
+
### `ProgressEmitterPort`
|
|
83
|
+
|
|
84
|
+
Emits progress events during long operations (scans, job runs). Consumers: CLI pretty printer, `--json` ndjson, Server's WebSocket broadcaster.
|
|
85
|
+
|
|
86
|
+
Operations: `emit(event)`, `subscribe(listener)`. Events are defined in `job-events.md`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Kernel
|
|
91
|
+
|
|
92
|
+
The kernel is the only component that:
|
|
93
|
+
- Maintains the extension registry.
|
|
94
|
+
- Runs the scan orchestrator.
|
|
95
|
+
- Validates scan output against `scan-result.schema.json`.
|
|
96
|
+
- Applies the canonical prompt preamble to job files (`prompt-preamble.md`).
|
|
97
|
+
- Enforces duplicate-prevention and atomic-claim invariants for jobs.
|
|
98
|
+
- Persists execution records.
|
|
99
|
+
|
|
100
|
+
The kernel is the only component that MAY:
|
|
101
|
+
- Import schemas.
|
|
102
|
+
- Call `validate(data, schema)`.
|
|
103
|
+
- Dispatch extension hooks.
|
|
104
|
+
|
|
105
|
+
The kernel MUST NOT:
|
|
106
|
+
- Know which adapter produced an event.
|
|
107
|
+
- Know which platform a node belongs to (that is the `Adapter` extension's job).
|
|
108
|
+
- Contain any platform-specific branching (e.g., `if (platform === 'claude')`).
|
|
109
|
+
|
|
110
|
+
### Boot invariant
|
|
111
|
+
|
|
112
|
+
**With all extensions removed, the kernel MUST boot and return an empty graph.** This is enforced by the conformance suite case `kernel-empty-boot`.
|
|
113
|
+
|
|
114
|
+
No extension is privileged. The Claude adapter ships bundled with the reference impl but is removable, same as any third-party plugin.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Extension kinds
|
|
119
|
+
|
|
120
|
+
Six kinds, all first-class, all loaded through the same registry. Each kind has a JSON Schema describing its manifest shape (`spec/schemas/extensions/<kind>.schema.json`, landing with step 3 of the spec bootstrap).
|
|
121
|
+
|
|
122
|
+
| Kind | Role | Input | Output |
|
|
123
|
+
|---|---|---|---|
|
|
124
|
+
| **Adapter** | Recognizes a platform. Decides which files are nodes and what kind they are. | Filesystem walk results, candidate path. | `{ kind, adapter } \| null`. |
|
|
125
|
+
| **Detector** | Extracts signals from a node body. | Parsed node (frontmatter + body). | `Link[]`. |
|
|
126
|
+
| **Rule** | Evaluates the graph. | Full graph (nodes + links). | `Issue[]`. |
|
|
127
|
+
| **Action** | Operates on one or more nodes. Two modes: `local` (code) or `invocation-template` (LLM prompt). | Node(s), optional args. | Local: report JSON. Template: rendered prompt that a runner executes. |
|
|
128
|
+
| **Audit** | Deterministic workflow that composes rules and actions. Produces a structured report. | Graph + optional scope filter. | Audit report (hardcoded shape, kind-specific). |
|
|
129
|
+
| **Renderer** | Serializes the graph. | Graph + optional filter. | String (ASCII / Mermaid / DOT / JSON / user-defined). |
|
|
130
|
+
|
|
131
|
+
### Contract rules
|
|
132
|
+
|
|
133
|
+
1. An extension declares its kind in its module export and its manifest. Kind mismatch → load-error.
|
|
134
|
+
2. An extension MAY declare `preconditions` — predicates that must be satisfied for the extension to be offered (e.g., `action.requires: ["kind=skill"]`).
|
|
135
|
+
3. An extension MUST NOT retain state across invocations. Scoped persistence goes through `ctx.store` (storage mode `kv`) or the plugin's dedicated tables (`dedicated`).
|
|
136
|
+
4. An extension MUST NOT import another extension directly. Cross-extension communication goes through the kernel's registry lookup.
|
|
137
|
+
5. An extension MUST provide a sibling test file. The reference impl treats a missing test as a contract-check failure; other impls MAY relax this to a warning.
|
|
138
|
+
|
|
139
|
+
### Locality
|
|
140
|
+
|
|
141
|
+
- **Drop-in**: extensions live inside plugins, discovered at boot from `.skill-map/plugins/<id>/` and `~/.skill-map/plugins/<id>/`.
|
|
142
|
+
- **Built-in**: the reference impl bundles a default extension set (one adapter, three detectors, three rules, one audit, one renderer). These are loaded from `src/extensions/` and are indistinguishable from plugin-supplied extensions from the kernel's point of view.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Dependency rules
|
|
147
|
+
|
|
148
|
+
The following imports are NORMATIVELY FORBIDDEN:
|
|
149
|
+
|
|
150
|
+
- `kernel/*` → any `adapters/*` module.
|
|
151
|
+
- `kernel/*` → `node:fs`, `node:sqlite`, `node:child_process`, or equivalent IO libraries.
|
|
152
|
+
- Any extension → another extension.
|
|
153
|
+
- Any extension → `adapters/*`.
|
|
154
|
+
- `cli/*` or `server/*` → `adapters/*`. Driving adapters wire adapters into the kernel at startup; they do not import adapters directly in their command code.
|
|
155
|
+
|
|
156
|
+
The following imports are permitted:
|
|
157
|
+
|
|
158
|
+
- `kernel/*` → `spec/schemas/*` (type imports, JSON Schema files at runtime).
|
|
159
|
+
- `adapters/*` → `kernel/*` (ports are declared in the kernel and implemented in adapters).
|
|
160
|
+
- `cli/*`, `server/*`, extensions → `kernel/*` (consuming kernel APIs).
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Testability consequences
|
|
165
|
+
|
|
166
|
+
Because the kernel depends only on ports:
|
|
167
|
+
|
|
168
|
+
- Unit tests inject `InMemoryStorageAdapter`, `FixtureFilesystemAdapter`, `MockRunner`.
|
|
169
|
+
- Integration tests wire real adapters.
|
|
170
|
+
- Conformance tests exercise the kernel directly, bypassing the CLI entirely.
|
|
171
|
+
- A driving adapter (CLI/Server/Skill) can be tested by asserting the kernel calls it makes, with all ports mocked.
|
|
172
|
+
|
|
173
|
+
This collapses cleanly onto the test pyramid mandated by `CLAUDE.md`: contract tests exercise kind schemas; unit tests exercise the kernel in isolation; integration tests exercise adapter pairs; CLI tests spawn the binary.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Package layout (reference impl)
|
|
178
|
+
|
|
179
|
+
The spec does not prescribe package layout. The reference impl uses a single npm package with multiple `exports` entries:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
src/
|
|
183
|
+
├── kernel/ Registry, Orchestrator, domain types, use cases, port interfaces
|
|
184
|
+
├── cli/ Clipanion commands, thin wrappers over kernel
|
|
185
|
+
├── server/ Hono + WebSocket, thin wrapper over kernel
|
|
186
|
+
├── testkit/ Kernel mocks for plugin authors
|
|
187
|
+
└── adapters/
|
|
188
|
+
├── sqlite/ node:sqlite + Kysely + CamelCasePlugin (StoragePort)
|
|
189
|
+
├── filesystem/ real fs (FilesystemPort)
|
|
190
|
+
├── plugin-loader/ drop-in discovery (PluginLoaderPort)
|
|
191
|
+
└── runner/ claude -p subprocess (RunnerPort)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Alternative implementations MAY use workspaces, separate packages, or a compiled monolith. The spec has no opinion.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Driving-adapter peer rule
|
|
199
|
+
|
|
200
|
+
The CLI, Server, and Skill driving adapters are **peers**. None depends on another.
|
|
201
|
+
|
|
202
|
+
- The Server MUST NOT call the CLI (no `child_process.spawn('sm', ...)`).
|
|
203
|
+
- The Skill runner MUST NOT depend on the Server (it can be used offline).
|
|
204
|
+
- The CLI MUST NOT embed HTTP logic.
|
|
205
|
+
|
|
206
|
+
All three consume the same kernel API. Any use case a driving adapter needs MUST be available as a kernel function — if it isn't, the gap is a kernel bug, not a driving-adapter workaround.
|
|
207
|
+
|
|
208
|
+
This is what makes "CLI-first" a coherent rule: every CLI verb is a kernel function call. The UI does not reimplement business logic; it calls the same functions.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Stability
|
|
213
|
+
|
|
214
|
+
The **port list** is stable as of spec v1.0.0. Adding a sixth port is a major bump.
|
|
215
|
+
|
|
216
|
+
The **extension kind list** (6 kinds) is stable as of spec v1.0.0. Adding a seventh kind is a major bump.
|
|
217
|
+
|
|
218
|
+
The **dependency rules** above are stable as of spec v1.0.0. Relaxing any is a major bump; tightening (forbidding an allowed import) is a minor bump.
|