chore: version packages#23
Merged
Merged
Conversation
163e8d3 to
b39cd3b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@skill-map/spec@0.12.0
Minor Changes
68c5e28: Step 14.1 —
sm serve+ Hono BFF skeletonAdds
src/server/Hono workspace with single-port wiring (/api/healthreal,/api/*404 stubs,/wsno-op upgrade,serveStatic+ SPA fallback). RealServeCommandextracted from stub atcli/commands/stubs.tsto dedicatedcli/commands/serve.tsextendingSmCommand. Loopback-only through v0.6.0(Decision #119). Boot resilient to missing DB —
/api/healthreportsdb: 'missing'. Speccli-contract.mdsm serverow updated to full flagset; new
### Serversubsection (skeleton — endpoints fill at 14.2).Files added (server)
src/server/index.ts—createServer(opts)factory returningServerHandle({ address, close }); resolves spec version, builds the Hono app, instantiates aWebSocketServer({ noServer: true }), hands both to@hono/node-server'sserve({ websocket: { server: wss } }). Closing the http server tears down the WSS automatically (node-server registers the'close'hook internally);close()callswss.close()defensively for forward-compatibility.src/server/app.ts— Hono app construction. Routes registered in single-port order:GET /api/health→ real,ALL /api/*→ structured 404,GET /wsvia the injectedattachWsregistrar, static handler + SPA fallback. Globalapp.onErrorformats every uncaught throw into the error envelope.src/server/options.ts—IServerOptions+validateServerOptions(input). Loopback-only check for--dev-cors; port range check[0, 65535]; scope validation.src/server/paths.ts—resolveDefaultUiDist(ctx)walks upwards from cwd looking forui/dist/browser/index.html;resolveExplicitUiDist(ctx, raw)honours absolute paths for--ui-dist.src/server/static.ts— wraps@hono/node-server'sserveStaticmiddleware with the SPA-fallback layer (serveStaticdoes not do SPA fallback — itnext()s on miss, which is exactly the seam we hook into). Absoluterootpaths work on POSIX in node-server@2.0.1 (verified runtime probe — implementation ispath.join(root, filename)); the.d.ts"Absolute paths are not supported" string is stale (upstream issue add support for absolute path to serveStatic root honojs/node-server#187 still open). When the bundle is missing (uiDist === null), a tiny placeholder middleware serves the boot-without-bundle hint at/.src/server/ws.ts—noopWebSocketRoute(app)registersGET /wsvia the officialupgradeWebSocketre-exported from@hono/node-server@2.x. The 14.1 handler closes the connection inonOpenwith code 1000 + reason'no broadcaster yet'. 14.4 swaps this registrar for the chokidar-fed broadcaster — one-line change inindex.ts,app.tsuntouched.src/server/health.ts—buildHealth(deps)synchronous;resolveSpecVersion()async, called once at boot.src/server/i18n/server.texts.ts—SERVER_TEXTScatalog.Files added (CLI)
src/cli/commands/serve.ts—ServeCommand extends SmCommand. Parses flags, validates, callscreateServer, registers SIGINT/SIGTERM handlers, awaits shutdown.protected emitElapsed = false(long-running daemon).src/cli/i18n/serve.texts.ts—SERVE_TEXTScatalog.Tests added (15)
src/test/server-boot.test.ts(7) — boot/listen/health JSON, custom port, db state present/missing, structured 404, /ws upgrade closes with code 1000 + reason 'no broadcaster yet' (uses realWebSocketclient fromws), shutdown < 1s + idempotent close, inline placeholder when uiDist null.src/test/server-flags.test.ts(6) — host non-loopback + dev-cors rejection, port out-of-range, port non-numeric, scope invalid, ui-dist missing, ui-dist with valid bundle.src/test/server-db-missing.test.ts(2) —--db <missing>exits 5, default boots cleanly with db:missing.Files edited
src/cli/commands/stubs.ts—ServeCommandremoved; replaced with a comment pointer.src/cli/entry.ts— registers the newServeCommand.src/package.json— addshono@4.12.16,@hono/node-server@2.0.1,ws@8.20.0(deps);@types/ws@8.18.1(dev). All exact-pinned per AGENTS.md.spec/cli-contract.md—sm serverow replaced with the full 14.1 flag set; new#### Serversubsection (stability: experimental).spec/CHANGELOG.md—[Unreleased]### Minorentry for the spec change.spec/index.json— regenerated (40 files hashed; previous head was 215 lines).Decisions during implementation (flag for orchestrator)
@hono/node-server@2.x's built-inupgradeWebSocketplus the canonicalws@8.20.0Node WebSocket library, per the official README pattern. The previously-published@hono/node-wsadapter was deprecated when node-server@2.0 absorbed WebSocket support natively (PR feat: first class support for websockets honojs/node-server#328). The 14.4 broadcaster will replacenoopWebSocketRoutewith its own one-line registrar — no API churn between 14.1 and 14.4./api/*catch-all is wired withapp.all('/api/*', ...)BEFORE the/wsregistrar and the static handler so neither aserveStaticfilesystem hit nor the SPA fallback can shadow API endpoints./wsis registered BEFORE the static handler so a literal/wspath on disk insideuiDistcannot accidentally shadow the upgrade route.serveStaticfrom@hono/node-server/serve-staticaccepts absolute root paths at runtime on POSIX (its implementation ispath.join(root, filename)); the.d.tsstring saying otherwise is documentation drift, not a runtime contract. Verified with a runtime probe and cross-referenced against the open upstream issue (add support for absolute path to serveStatic root honojs/node-server#187). Documented insrc/server/static.tsso future contributors don't re-investigate.@skill-map/cli@0.10.0
Minor Changes
9b55981: cli-architect review follow-up —
SmCommandbase class wires every spec § Global flag (-q/--quiet,-v/--verbose,--no-color, env vars), every read-side verb now emitsdone in <…>per spec § Elapsed time, watch grows a circuit breaker, scan extracts the runner, and two invariant tests gate future regressions.HIGH — spec § Global flags / Elapsed time gaps
Audit found the CLI honoured only a subset of the spec's global flags and emitted
done in <…>from a handful of verbs ad-hoc. Closed structurally:cli/util/sm-command.ts— abstractSmCommand extends Command. Declares-g/--global,--json,-q/--quiet,--no-color,-v/--verbose,--dbonce. Subclasses implementprotected run()instead ofexecute(); the base wraps it withapplyEnvOverrides()(promotesSKILL_MAP_SCOPE=global,SKILL_MAP_JSON=1,NO_COLOR,SKILL_MAP_DB=<path>to flags when the CLI flag is at default — spec precedence: CLI > env > config) +startElapsed()+ afinallythat emitsdone in <…>(suppressed by--quiet). Verbs opt out viaprotected emitElapsed = false(today:sm version,sm watch,sm db shell,sm config list/get/show).-v/-vv/-vvvreconfigures the kernel logger toinfo/debug/tracerespectively;--log-levelfromentry.tsstays as the legacy escape hatch.init,scan,check,list,show,export,refresh,history,history stats,db backup/restore/reset/shell/dump/migrate,plugins list/show/doctor/enable/disable,orphans/orphans reconcile/orphans undo-rename,graph,scan-compare,version,conformance run,config list/get/show/set/reset,jobs prune,watch. Each drops its locally-declared globals (global,db,json,quiet) and renamesexecute()→run().MEDIUM — watch circuit breaker
runWatchLooppreviously caught every per-batch error, logged one line, and continued forever. A permanent failure (write-protected DB, schema corruption discovered post-init) repeated indefinitely with no exit signal. New--max-consecutive-failures=Nflag (default 5; 0 disables) shuts the watcher down with exit 2 after N back-to-back failures. A successful batch resets the counter so transient errors never trip the breaker. Also removes the inner try/catch inrunOnePassthat was duplicating the per-batch error path — failures now propagate toonBatchso the breaker can count them.MEDIUM —
cli/util/scan-runner.tsextractionScanCommand.executewas 340 LOC inside one allowedeslint-disable complexity. The wiring chain (plugin runtime, config + ignore filter, prior-snapshot load, single-withSqliteopen for persist, dry-run / non-persist branch) moved torunScanForCommand(opts: IScanRunOpts): IScanRunResult— a kernel-thin runner the verb consumes viaparse flags → runScanForCommand → render → exit code. MirrorsrunWatchLoop's shape forsm watch.MEDIUM — quick wins
cli/util/fs.ts— lifts thepathExists/statOrNullhelpers that were duplicated incli/commands/db.tsandcli/commands/init.ts. ENOENT remains the only swallowed errno; every other code propagates so the caller sees the real reason.cli/util/db-path.ts— addsdefaultDbPath(scopeRoot),defaultSettingsPath,defaultLocalSettingsPath,defaultIgnoreFilePath, and a frozenGITIGNORE_ENTRIESconstant.cli/commands/init.tsconsumes them; the spirit of "no hardcoded.skill-map/...literals" now applies to settings / ignore paths the same way it already applied to the DB path.kernel/util/ajv-interop.ts— singleapplyAjvFormats(ajv)helper. Theajv-formats as unknown as ...ESM/CJS workaround that used to live in bothplugin-loader.tsandschema-validators.tsis now in one place.cli/commands/plugins.ts— everytx(PLUGINS_TEXTS.*, { ... })interpolation that splices a user-suppliedid/bundleId/extId(CLI flag input, untrusted) wraps the value insanitizeForTerminal(). Closes the audit's note thatplugins.ts:304and the surroundingresolveToggleTargetcall sites were the one remaining gap in CLI output sanitization.cli/commands/db.ts—db migratedeclares-n,--dry-run(was--dry-runonly); aligns withdb resetand the rest of the verb family.cli/commands/show.ts— drops the speculativefindings: never[]/summary: nullreserved slots. The spec §sm show --jsonshape is{ node, linksOut, linksIn, issues }until Step 10 (findings) and Step 11 (summary) ship; the placeholders narrow consumer types in a way the eventualunknown[]/unknown | nullwiden could not be additive over. Test updated to assert the fields are absent.Invariant tests (catch future regressions)
test/elapsed-invariant.test.ts(10 tests) — for every read-side verb in spec § Elapsed time scope (check,list,show,export,history,history stats,db migrate --status,plugins list,plugins doctor), captures stderr and asserts/^done in (\d+ms|\d+\.\d+s|\d+m \d+s)\n?$/m. Plus one negative test that--quietsuppresses the line.test/render-sanitize-invariant.test.ts(5 tests) — plants\x1b[2J(ANSI clear-screen) and\x07(BEL) insideNode.titleandIssue.message, persists them, then runscheck,show,list,export --format md/jsonand asserts no C0 / C1 control byte (other than\n/\t) reaches stdout. Catches any future render path that forgets to wrap a plugin / DB / FS string insanitizeForTerminal.Out of scope (deferred)
sm export --format mermaidexit code — currently2(operational error). Audit suggested a dedicated "deferred / unsupported" code; that requires aspec/cli-contract.md§ Exit codes amendment (codes 6–15 are reserved per spec). Not landing in this PR.Audit follow-up tail (low-priority items held back from the main commit —
patch-level)Tests + comments only; no behavioural or surface change. Folded into this changeset because it ships in the same release window and the reader benefits from one continuous narrative.
cli/commands/scan.ts+cli/util/scan-runner.ts— 6-line comments document thesm scan --globalgap. Spec § Global flags lists-g/--globalas universal but the per-verb § Scan table omits it, and "scan global" semantics (which dirs? which ignore filter?) are undefined.ScanCommandaccepts-g(inherited fromSmCommand) but the runner hardcodesscope: 'project'. Comments mark both sites so the wiring lands in one motion once spec defines the contract.test/conformance.test.ts— 2 new integration tests (audit finding 6.4) plant a hostile case JSON withfixture: '../../../../../../etc/passwd'and another withfixture: '/etc/passwd', invokerunConformanceCase(...)directly, and assert the runner refuses both before any I/O against the planted path. Reinforces the unit-level guard atconformance/index.ts:assertContainedend-to-end.test/dry-run-invariant.test.ts(new file, 7 tests — refactor 8.3) — cross-cutting gate for spec § Dry-run's "no observable side effects" contract. Snapshots the scope dir's file content viasha256(excluding SQLite WAL/SHM sidecars — those rewrite even on read-only opens) before / after a--dry-runinvocation and asserts byte-equality. Coversdb reset,db reset --hard,db restore <source>,db migrate,sm scan(over a fresh cwd with no.skill-map/), andsm init. Plus a negative control test that runsdb reset --hardfor real and asserts the file set DOES change — proves the snapshot machinery has teeth.Tests
749/749 pass (+24 vs prior 725; +9 vs the main follow-up commit's 740). Lint clean, build clean. No spec change;
spec/index.jsonnot regenerated.68c5e28: Step 14.1 —
sm serve+ Hono BFF skeletonAdds
src/server/Hono workspace with single-port wiring (/api/healthreal,/api/*404 stubs,/wsno-op upgrade,serveStatic+ SPA fallback). RealServeCommandextracted from stub atcli/commands/stubs.tsto dedicatedcli/commands/serve.tsextendingSmCommand. Loopback-only through v0.6.0(Decision #119). Boot resilient to missing DB —
/api/healthreportsdb: 'missing'. Speccli-contract.mdsm serverow updated to full flagset; new
### Serversubsection (skeleton — endpoints fill at 14.2).Files added (server)
src/server/index.ts—createServer(opts)factory returningServerHandle({ address, close }); resolves spec version, builds the Hono app, instantiates aWebSocketServer({ noServer: true }), hands both to@hono/node-server'sserve({ websocket: { server: wss } }). Closing the http server tears down the WSS automatically (node-server registers the'close'hook internally);close()callswss.close()defensively for forward-compatibility.src/server/app.ts— Hono app construction. Routes registered in single-port order:GET /api/health→ real,ALL /api/*→ structured 404,GET /wsvia the injectedattachWsregistrar, static handler + SPA fallback. Globalapp.onErrorformats every uncaught throw into the error envelope.src/server/options.ts—IServerOptions+validateServerOptions(input). Loopback-only check for--dev-cors; port range check[0, 65535]; scope validation.src/server/paths.ts—resolveDefaultUiDist(ctx)walks upwards from cwd looking forui/dist/browser/index.html;resolveExplicitUiDist(ctx, raw)honours absolute paths for--ui-dist.src/server/static.ts— wraps@hono/node-server'sserveStaticmiddleware with the SPA-fallback layer (serveStaticdoes not do SPA fallback — itnext()s on miss, which is exactly the seam we hook into). Absoluterootpaths work on POSIX in node-server@2.0.1 (verified runtime probe — implementation ispath.join(root, filename)); the.d.ts"Absolute paths are not supported" string is stale (upstream issue add support for absolute path to serveStatic root honojs/node-server#187 still open). When the bundle is missing (uiDist === null), a tiny placeholder middleware serves the boot-without-bundle hint at/.src/server/ws.ts—noopWebSocketRoute(app)registersGET /wsvia the officialupgradeWebSocketre-exported from@hono/node-server@2.x. The 14.1 handler closes the connection inonOpenwith code 1000 + reason'no broadcaster yet'. 14.4 swaps this registrar for the chokidar-fed broadcaster — one-line change inindex.ts,app.tsuntouched.src/server/health.ts—buildHealth(deps)synchronous;resolveSpecVersion()async, called once at boot.src/server/i18n/server.texts.ts—SERVER_TEXTScatalog.Files added (CLI)
src/cli/commands/serve.ts—ServeCommand extends SmCommand. Parses flags, validates, callscreateServer, registers SIGINT/SIGTERM handlers, awaits shutdown.protected emitElapsed = false(long-running daemon).src/cli/i18n/serve.texts.ts—SERVE_TEXTScatalog.Tests added (15)
src/test/server-boot.test.ts(7) — boot/listen/health JSON, custom port, db state present/missing, structured 404, /ws upgrade closes with code 1000 + reason 'no broadcaster yet' (uses realWebSocketclient fromws), shutdown < 1s + idempotent close, inline placeholder when uiDist null.src/test/server-flags.test.ts(6) — host non-loopback + dev-cors rejection, port out-of-range, port non-numeric, scope invalid, ui-dist missing, ui-dist with valid bundle.src/test/server-db-missing.test.ts(2) —--db <missing>exits 5, default boots cleanly with db:missing.Files edited
src/cli/commands/stubs.ts—ServeCommandremoved; replaced with a comment pointer.src/cli/entry.ts— registers the newServeCommand.src/package.json— addshono@4.12.16,@hono/node-server@2.0.1,ws@8.20.0(deps);@types/ws@8.18.1(dev). All exact-pinned per AGENTS.md.spec/cli-contract.md—sm serverow replaced with the full 14.1 flag set; new#### Serversubsection (stability: experimental).spec/CHANGELOG.md—[Unreleased]### Minorentry for the spec change.spec/index.json— regenerated (40 files hashed; previous head was 215 lines).Decisions during implementation (flag for orchestrator)
@hono/node-server@2.x's built-inupgradeWebSocketplus the canonicalws@8.20.0Node WebSocket library, per the official README pattern. The previously-published@hono/node-wsadapter was deprecated when node-server@2.0 absorbed WebSocket support natively (PR feat: first class support for websockets honojs/node-server#328). The 14.4 broadcaster will replacenoopWebSocketRoutewith its own one-line registrar — no API churn between 14.1 and 14.4./api/*catch-all is wired withapp.all('/api/*', ...)BEFORE the/wsregistrar and the static handler so neither aserveStaticfilesystem hit nor the SPA fallback can shadow API endpoints./wsis registered BEFORE the static handler so a literal/wspath on disk insideuiDistcannot accidentally shadow the upgrade route.serveStaticfrom@hono/node-server/serve-staticaccepts absolute root paths at runtime on POSIX (its implementation ispath.join(root, filename)); the.d.tsstring saying otherwise is documentation drift, not a runtime contract. Verified with a runtime probe and cross-referenced against the open upstream issue (add support for absolute path to serveStatic root honojs/node-server#187). Documented insrc/server/static.tsso future contributors don't re-investigate.Patch Changes