opensquid 0.5.441 → 0.5.447
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/README.md +1 -0
- package/dist/functions/arm_scope.d.ts +27 -0
- package/dist/functions/arm_scope.d.ts.map +1 -0
- package/dist/functions/arm_scope.js +52 -0
- package/dist/functions/arm_scope.js.map +1 -0
- package/dist/functions/index.d.ts +1 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +1 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts.map +1 -1
- package/dist/runtime/bootstrap.js +2 -0
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/handoff/render.d.ts +5 -4
- package/dist/runtime/handoff/render.d.ts.map +1 -1
- package/dist/runtime/handoff/render.js +7 -7
- package/dist/runtime/handoff/render.js.map +1 -1
- package/dist/runtime/hooks/active_task_mirror.js +0 -0
- package/dist/runtime/hooks/apply_patch.js +0 -0
- package/dist/runtime/hooks/dispatch.js +0 -0
- package/dist/runtime/hooks/hook_output.js +0 -0
- package/dist/runtime/hooks/memory_reconcile.js +0 -0
- package/dist/runtime/hooks/new_project_detect.js +0 -0
- package/dist/runtime/hooks/profession_resolver.js +0 -0
- package/dist/runtime/hooks/scope_intent.js +0 -0
- package/dist/runtime/hooks/session_id.js +0 -0
- package/dist/runtime/hooks/session_liveness.js +0 -0
- package/dist/runtime/hooks/stop_drive.js +0 -0
- package/dist/runtime/hooks/stop_stream.js +0 -0
- package/dist/runtime/hooks/subagent_guard.js +0 -0
- package/dist/runtime/hooks/transcript.js +0 -0
- package/dist/runtime/hooks/transcript_tasks.js +0 -0
- package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
- package/dist/runtime/ralph/orchestrator.js +2 -1
- package/dist/runtime/ralph/orchestrator.js.map +1 -1
- package/dist/setup/cli/limits_state.d.ts.map +1 -1
- package/dist/setup/cli/limits_state.js +6 -40
- package/dist/setup/cli/limits_state.js.map +1 -1
- package/dist/setup/cli/pack_walk.d.ts +32 -0
- package/dist/setup/cli/pack_walk.d.ts.map +1 -0
- package/dist/setup/cli/pack_walk.js +76 -0
- package/dist/setup/cli/pack_walk.js.map +1 -0
- package/dist/setup/cli/permissions_state.d.ts.map +1 -1
- package/dist/setup/cli/permissions_state.js +6 -37
- package/dist/setup/cli/permissions_state.js.map +1 -1
- package/dist/setup/cli/triggers_state.d.ts.map +1 -1
- package/dist/setup/cli/triggers_state.js +3 -29
- package/dist/setup/cli/triggers_state.js.map +1 -1
- package/dist/workgraph/events.d.ts.map +1 -1
- package/dist/workgraph/events.js +10 -0
- package/dist/workgraph/events.js.map +1 -1
- package/dist/workgraph/store.d.ts.map +1 -1
- package/dist/workgraph/store.js +5 -0
- package/dist/workgraph/store.js.map +1 -1
- package/dist/workgraph/types.d.ts +2 -1
- package/dist/workgraph/types.d.ts.map +1 -1
- package/docs/ARCHITECTURE.md +268 -0
- package/package.json +5 -3
- package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
- package/dist/anti-drift/evaluator.d.ts +0 -88
- package/dist/anti-drift/evaluator.d.ts.map +0 -1
- package/dist/anti-drift/evaluator.js +0 -417
- package/dist/anti-drift/evaluator.js.map +0 -1
- package/dist/anti-drift/evaluator.test.js +0 -78
- package/dist/anti-drift/rules.d.ts +0 -80
- package/dist/anti-drift/rules.d.ts.map +0 -1
- package/dist/anti-drift/rules.js +0 -368
- package/dist/anti-drift/rules.js.map +0 -1
- package/dist/anti-drift/rules.test.js +0 -213
- package/dist/anti-drift/state.d.ts +0 -107
- package/dist/anti-drift/state.d.ts.map +0 -1
- package/dist/anti-drift/state.js +0 -177
- package/dist/anti-drift/state.js.map +0 -1
- package/dist/anti-drift/state.test.js +0 -120
- package/dist/chat/adapters/discord.d.ts +0 -41
- package/dist/chat/adapters/discord.d.ts.map +0 -1
- package/dist/chat/adapters/discord.js +0 -176
- package/dist/chat/adapters/discord.js.map +0 -1
- package/dist/chat/adapters/discord.test.js +0 -25
- package/dist/chat/adapters/slack.d.ts +0 -43
- package/dist/chat/adapters/slack.d.ts.map +0 -1
- package/dist/chat/adapters/slack.js +0 -172
- package/dist/chat/adapters/slack.js.map +0 -1
- package/dist/chat/adapters/slack.test.js +0 -30
- package/dist/chat/adapters/telegram.d.ts +0 -148
- package/dist/chat/adapters/telegram.d.ts.map +0 -1
- package/dist/chat/adapters/telegram.js +0 -498
- package/dist/chat/adapters/telegram.js.map +0 -1
- package/dist/chat/adapters/telegram.test.js +0 -94
- package/dist/chat/config.d.ts +0 -98
- package/dist/chat/config.d.ts.map +0 -1
- package/dist/chat/config.js +0 -185
- package/dist/chat/config.js.map +0 -1
- package/dist/chat/daemon/active-project.d.ts +0 -17
- package/dist/chat/daemon/active-project.d.ts.map +0 -1
- package/dist/chat/daemon/active-project.js +0 -23
- package/dist/chat/daemon/active-project.js.map +0 -1
- package/dist/chat/daemon/autospawn.d.ts +0 -40
- package/dist/chat/daemon/autospawn.d.ts.map +0 -1
- package/dist/chat/daemon/autospawn.js +0 -129
- package/dist/chat/daemon/autospawn.js.map +0 -1
- package/dist/chat/daemon/autospawn.test.js +0 -112
- package/dist/chat/daemon/cli.d.ts +0 -18
- package/dist/chat/daemon/cli.d.ts.map +0 -1
- package/dist/chat/daemon/cli.js +0 -71
- package/dist/chat/daemon/cli.js.map +0 -1
- package/dist/chat/daemon/collisions.js +0 -384
- package/dist/chat/daemon/health-check.d.ts +0 -69
- package/dist/chat/daemon/health-check.d.ts.map +0 -1
- package/dist/chat/daemon/health-check.js +0 -112
- package/dist/chat/daemon/health-check.js.map +0 -1
- package/dist/chat/daemon/inbox-read.d.ts +0 -35
- package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
- package/dist/chat/daemon/inbox-read.js +0 -75
- package/dist/chat/daemon/inbox-read.js.map +0 -1
- package/dist/chat/daemon/inbox-read.test.js +0 -97
- package/dist/chat/daemon/inbox.d.ts +0 -63
- package/dist/chat/daemon/inbox.d.ts.map +0 -1
- package/dist/chat/daemon/inbox.js +0 -56
- package/dist/chat/daemon/inbox.js.map +0 -1
- package/dist/chat/daemon/inbox.test.js +0 -110
- package/dist/chat/daemon/lifecycle.d.ts +0 -71
- package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
- package/dist/chat/daemon/lifecycle.js +0 -221
- package/dist/chat/daemon/lifecycle.js.map +0 -1
- package/dist/chat/daemon/lifecycle.test.js +0 -163
- package/dist/chat/daemon/protocol.d.ts +0 -107
- package/dist/chat/daemon/protocol.d.ts.map +0 -1
- package/dist/chat/daemon/protocol.js +0 -54
- package/dist/chat/daemon/protocol.js.map +0 -1
- package/dist/chat/daemon/routing.d.ts +0 -140
- package/dist/chat/daemon/routing.d.ts.map +0 -1
- package/dist/chat/daemon/routing.js +0 -198
- package/dist/chat/daemon/routing.js.map +0 -1
- package/dist/chat/daemon/routing.test.js +0 -259
- package/dist/chat/daemon/rpc-client.d.ts +0 -45
- package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-client.js +0 -133
- package/dist/chat/daemon/rpc-client.js.map +0 -1
- package/dist/chat/daemon/rpc-server.d.ts +0 -39
- package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
- package/dist/chat/daemon/rpc-server.js +0 -385
- package/dist/chat/daemon/rpc-server.js.map +0 -1
- package/dist/chat/daemon/rpc.test.js +0 -177
- package/dist/chat/daemon/subscribers.js +0 -257
- package/dist/chat/daemon/worker.d.ts +0 -27
- package/dist/chat/daemon/worker.d.ts.map +0 -1
- package/dist/chat/daemon/worker.js +0 -313
- package/dist/chat/daemon/worker.js.map +0 -1
- package/dist/chat/daemon/workspace-topic.js +0 -324
- package/dist/chat/env-token.d.ts +0 -60
- package/dist/chat/env-token.d.ts.map +0 -1
- package/dist/chat/env-token.js +0 -137
- package/dist/chat/env-token.js.map +0 -1
- package/dist/chat/env-token.test.js +0 -160
- package/dist/chat/factory.d.ts +0 -30
- package/dist/chat/factory.d.ts.map +0 -1
- package/dist/chat/factory.js +0 -50
- package/dist/chat/factory.js.map +0 -1
- package/dist/chat/factory.test.js +0 -55
- package/dist/chat/gateway.d.ts +0 -176
- package/dist/chat/gateway.d.ts.map +0 -1
- package/dist/chat/gateway.js +0 -146
- package/dist/chat/gateway.js.map +0 -1
- package/dist/chat/gateway.test.js +0 -192
- package/dist/claude-md.d.ts +0 -39
- package/dist/claude-md.d.ts.map +0 -1
- package/dist/claude-md.js +0 -113
- package/dist/claude-md.js.map +0 -1
- package/dist/claude-md.test.js +0 -91
- package/dist/codex/activate.d.ts +0 -66
- package/dist/codex/activate.d.ts.map +0 -1
- package/dist/codex/activate.js +0 -329
- package/dist/codex/activate.js.map +0 -1
- package/dist/codex/activate.test.js +0 -229
- package/dist/codex/bundled-default/bundled-default.test.js +0 -161
- package/dist/codex/cli-publish.test.js +0 -133
- package/dist/codex/cli.d.ts +0 -35
- package/dist/codex/cli.d.ts.map +0 -1
- package/dist/codex/cli.js +0 -554
- package/dist/codex/cli.js.map +0 -1
- package/dist/codex/cli.test.js +0 -277
- package/dist/codex/import-skill-md.d.ts +0 -53
- package/dist/codex/import-skill-md.d.ts.map +0 -1
- package/dist/codex/import-skill-md.js +0 -236
- package/dist/codex/import-skill-md.js.map +0 -1
- package/dist/codex/import-skill-md.test.js +0 -225
- package/dist/codex/loader.d.ts +0 -27
- package/dist/codex/loader.d.ts.map +0 -1
- package/dist/codex/loader.js +0 -86
- package/dist/codex/loader.js.map +0 -1
- package/dist/codex/loader.test.js +0 -75
- package/dist/codex/parse.d.ts +0 -28
- package/dist/codex/parse.d.ts.map +0 -1
- package/dist/codex/parse.js +0 -309
- package/dist/codex/parse.js.map +0 -1
- package/dist/codex/parse.test.js +0 -241
- package/dist/codex/store.d.ts +0 -87
- package/dist/codex/store.d.ts.map +0 -1
- package/dist/codex/store.js +0 -205
- package/dist/codex/store.js.map +0 -1
- package/dist/codex/store.test.js +0 -242
- package/dist/codex/types.d.ts +0 -398
- package/dist/codex/types.d.ts.map +0 -1
- package/dist/codex/types.js +0 -21
- package/dist/codex/types.js.map +0 -1
- package/dist/config.d.ts +0 -53
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -202
- package/dist/config.js.map +0 -1
- package/dist/config.test.js +0 -117
- package/dist/engine/cli.d.ts +0 -14
- package/dist/engine/cli.d.ts.map +0 -1
- package/dist/engine/cli.js +0 -171
- package/dist/engine/cli.js.map +0 -1
- package/dist/engine/client.d.ts +0 -219
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js +0 -312
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/config.d.ts +0 -62
- package/dist/engine/config.d.ts.map +0 -1
- package/dist/engine/config.js +0 -223
- package/dist/engine/config.js.map +0 -1
- package/dist/engine/index.d.ts +0 -17
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js +0 -16
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/resolver.d.ts +0 -62
- package/dist/engine/resolver.d.ts.map +0 -1
- package/dist/engine/resolver.js +0 -103
- package/dist/engine/resolver.js.map +0 -1
- package/dist/engine/singleton.d.ts +0 -95
- package/dist/engine/singleton.d.ts.map +0 -1
- package/dist/engine/singleton.js +0 -325
- package/dist/engine/singleton.js.map +0 -1
- package/dist/engine/types.d.ts +0 -402
- package/dist/engine/types.d.ts.map +0 -1
- package/dist/engine/types.js +0 -22
- package/dist/engine/types.js.map +0 -1
- package/dist/engine-binary-resolver.js +0 -110
- package/dist/engine-binary-resolver.test.js +0 -61
- package/dist/engine-cli.js +0 -60
- package/dist/engine-client.js +0 -301
- package/dist/engine-client.test.js +0 -118
- package/dist/functions/chain_state.d.ts +0 -51
- package/dist/functions/chain_state.d.ts.map +0 -1
- package/dist/functions/chain_state.js +0 -59
- package/dist/functions/chain_state.js.map +0 -1
- package/dist/hooks/drift-catalog.d.ts +0 -68
- package/dist/hooks/drift-catalog.d.ts.map +0 -1
- package/dist/hooks/drift-catalog.js +0 -184
- package/dist/hooks/drift-catalog.js.map +0 -1
- package/dist/hooks/drift-catalog.test.js +0 -154
- package/dist/hooks/drift-patterns.d.ts +0 -110
- package/dist/hooks/drift-patterns.d.ts.map +0 -1
- package/dist/hooks/drift-patterns.js +0 -289
- package/dist/hooks/drift-patterns.js.map +0 -1
- package/dist/hooks/drift-patterns.test.js +0 -325
- package/dist/hooks/engine-vocab-gate.d.ts +0 -108
- package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
- package/dist/hooks/engine-vocab-gate.js +0 -225
- package/dist/hooks/engine-vocab-gate.js.map +0 -1
- package/dist/hooks/engine-vocab-gate.test.js +0 -170
- package/dist/hooks/heartbeat.d.ts +0 -107
- package/dist/hooks/heartbeat.d.ts.map +0 -1
- package/dist/hooks/heartbeat.js +0 -316
- package/dist/hooks/heartbeat.js.map +0 -1
- package/dist/hooks/heartbeat.test.js +0 -393
- package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
- package/dist/hooks/honesty-ledger.d.ts +0 -123
- package/dist/hooks/honesty-ledger.d.ts.map +0 -1
- package/dist/hooks/honesty-ledger.js +0 -226
- package/dist/hooks/honesty-ledger.js.map +0 -1
- package/dist/hooks/honesty-ledger.test.js +0 -466
- package/dist/hooks/inline-report-check.d.ts +0 -63
- package/dist/hooks/inline-report-check.d.ts.map +0 -1
- package/dist/hooks/inline-report-check.js +0 -88
- package/dist/hooks/inline-report-check.js.map +0 -1
- package/dist/hooks/inline-report-check.test.js +0 -96
- package/dist/hooks/pre-tool-use.d.ts +0 -62
- package/dist/hooks/pre-tool-use.d.ts.map +0 -1
- package/dist/hooks/pre-tool-use.js +0 -342
- package/dist/hooks/pre-tool-use.js.map +0 -1
- package/dist/hooks/pre-tool-use.test.js +0 -134
- package/dist/hooks/session-end.d.ts +0 -15
- package/dist/hooks/session-end.d.ts.map +0 -1
- package/dist/hooks/session-end.js +0 -60
- package/dist/hooks/session-end.js.map +0 -1
- package/dist/hooks/session-end.test.js +0 -52
- package/dist/hooks/stop.d.ts +0 -35
- package/dist/hooks/stop.d.ts.map +0 -1
- package/dist/hooks/stop.js +0 -136
- package/dist/hooks/stop.js.map +0 -1
- package/dist/hooks/transcript-active-task.test.js +0 -342
- package/dist/hooks/transcript.d.ts +0 -26
- package/dist/hooks/transcript.d.ts.map +0 -1
- package/dist/hooks/transcript.js +0 -266
- package/dist/hooks/transcript.js.map +0 -1
- package/dist/hooks/transcript.test.js +0 -103
- package/dist/hooks/user-prompt-submit.d.ts +0 -74
- package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
- package/dist/hooks/user-prompt-submit.js +0 -256
- package/dist/hooks/user-prompt-submit.js.map +0 -1
- package/dist/hooks/user-prompt-submit.test.js +0 -118
- package/dist/hooks/versioning-gate.d.ts +0 -101
- package/dist/hooks/versioning-gate.d.ts.map +0 -1
- package/dist/hooks/versioning-gate.js +0 -245
- package/dist/hooks/versioning-gate.js.map +0 -1
- package/dist/hooks/versioning-gate.test.js +0 -368
- package/dist/hooks/workflow-gate.d.ts +0 -64
- package/dist/hooks/workflow-gate.d.ts.map +0 -1
- package/dist/hooks/workflow-gate.js +0 -152
- package/dist/hooks/workflow-gate.js.map +0 -1
- package/dist/hooks/workflow-gate.test.js +0 -197
- package/dist/hooks-cli.d.ts +0 -25
- package/dist/hooks-cli.d.ts.map +0 -1
- package/dist/hooks-cli.js +0 -286
- package/dist/hooks-cli.js.map +0 -1
- package/dist/hooks-cli.test.js +0 -148
- package/dist/origin.d.ts +0 -16
- package/dist/origin.d.ts.map +0 -1
- package/dist/origin.js +0 -92
- package/dist/origin.js.map +0 -1
- package/dist/packs/seed_lessons_ingest.d.ts +0 -30
- package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
- package/dist/packs/seed_lessons_ingest.js +0 -107
- package/dist/packs/seed_lessons_ingest.js.map +0 -1
- package/dist/project-cli.d.ts +0 -7
- package/dist/project-cli.d.ts.map +0 -1
- package/dist/project-cli.js +0 -145
- package/dist/project-cli.js.map +0 -1
- package/dist/project.d.ts +0 -127
- package/dist/project.d.ts.map +0 -1
- package/dist/project.js +0 -281
- package/dist/project.js.map +0 -1
- package/dist/project.test.js +0 -287
- package/dist/rag/backends/loop_engine.d.ts +0 -61
- package/dist/rag/backends/loop_engine.d.ts.map +0 -1
- package/dist/rag/backends/loop_engine.js +0 -160
- package/dist/rag/backends/loop_engine.js.map +0 -1
- package/dist/recall.d.ts +0 -82
- package/dist/recall.d.ts.map +0 -1
- package/dist/recall.js +0 -81
- package/dist/recall.js.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
- package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
- package/dist/runtime/agent_bridge/autospawn.js +0 -251
- package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
- package/dist/runtime/chain_state.d.ts +0 -124
- package/dist/runtime/chain_state.d.ts.map +0 -1
- package/dist/runtime/chain_state.js +0 -189
- package/dist/runtime/chain_state.js.map +0 -1
- package/dist/runtime/hooks/permission_decision.d.ts +0 -34
- package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
- package/dist/runtime/hooks/permission_decision.js +0 -39
- package/dist/runtime/hooks/permission_decision.js.map +0 -1
- package/dist/runtime/workflow_fsm.d.ts +0 -21
- package/dist/runtime/workflow_fsm.d.ts.map +0 -1
- package/dist/runtime/workflow_fsm.js +0 -25
- package/dist/runtime/workflow_fsm.js.map +0 -1
- package/dist/runtime/workflow_map.d.ts +0 -26
- package/dist/runtime/workflow_map.d.ts.map +0 -1
- package/dist/runtime/workflow_map.js +0 -38
- package/dist/runtime/workflow_map.js.map +0 -1
- package/dist/scope.d.ts +0 -48
- package/dist/scope.d.ts.map +0 -1
- package/dist/scope.js +0 -111
- package/dist/scope.js.map +0 -1
- package/dist/setup/cli/topic_create_step.d.ts +0 -84
- package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
- package/dist/setup/cli/topic_create_step.js +0 -213
- package/dist/setup/cli/topic_create_step.js.map +0 -1
- package/dist/system-export.d.ts +0 -65
- package/dist/system-export.d.ts.map +0 -1
- package/dist/system-export.js +0 -194
- package/dist/system-export.js.map +0 -1
- package/dist/utterance/classifier.d.ts +0 -53
- package/dist/utterance/classifier.d.ts.map +0 -1
- package/dist/utterance/classifier.js +0 -184
- package/dist/utterance/classifier.js.map +0 -1
- package/dist/utterance/classifier.test.js +0 -147
package/dist/codex/cli.test.js
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import * as crypto from "node:crypto";
|
|
2
|
-
import { promises as fs } from "node:fs";
|
|
3
|
-
import * as os from "node:os";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
6
|
-
import { CodexCliError, runCodexCli } from "./cli.js";
|
|
7
|
-
import { codexDir, codexesDir, getCodex } from "./store.js";
|
|
8
|
-
import { isFocusedCodex } from "./types.js";
|
|
9
|
-
// ---------------------------------------------------------------------
|
|
10
|
-
// Isolation
|
|
11
|
-
// ---------------------------------------------------------------------
|
|
12
|
-
let tmpRoot;
|
|
13
|
-
let sourceRoot;
|
|
14
|
-
const origConsoleLog = console.log;
|
|
15
|
-
const origConsoleError = console.error;
|
|
16
|
-
beforeEach(async () => {
|
|
17
|
-
const uniq = crypto.randomUUID();
|
|
18
|
-
tmpRoot = path.join(os.tmpdir(), `opensquid-cli-test-${uniq}`);
|
|
19
|
-
sourceRoot = path.join(os.tmpdir(), `opensquid-cli-src-${uniq}`);
|
|
20
|
-
await fs.mkdir(tmpRoot, { recursive: true });
|
|
21
|
-
await fs.mkdir(sourceRoot, { recursive: true });
|
|
22
|
-
// Silence console during tests.
|
|
23
|
-
console.log = () => { };
|
|
24
|
-
console.error = () => { };
|
|
25
|
-
});
|
|
26
|
-
afterEach(async () => {
|
|
27
|
-
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
28
|
-
await fs.rm(sourceRoot, { recursive: true, force: true });
|
|
29
|
-
console.log = origConsoleLog;
|
|
30
|
-
console.error = origConsoleError;
|
|
31
|
-
});
|
|
32
|
-
// Fixture: write a minimal valid codex YAML + lesson body at sourceRoot.
|
|
33
|
-
async function makeSourceCodex(opts) {
|
|
34
|
-
const yaml = `
|
|
35
|
-
id: react-19
|
|
36
|
-
version: 1.0.0
|
|
37
|
-
foundation:
|
|
38
|
-
tools:
|
|
39
|
-
- { name: react, semver: ">=19,<20" }
|
|
40
|
-
domains: [software-engineering]
|
|
41
|
-
detected_by:
|
|
42
|
-
- { kind: file_exists, path: "package.json" }
|
|
43
|
-
seed_lessons:
|
|
44
|
-
- id: atomic-search
|
|
45
|
-
trigger: "before creating a component"
|
|
46
|
-
bank_strategy: full
|
|
47
|
-
body_path: "lessons/atomic-search/lesson.md"
|
|
48
|
-
`;
|
|
49
|
-
await fs.writeFile(path.join(sourceRoot, "codex.yaml"), yaml, "utf8");
|
|
50
|
-
if (opts?.withLessonBody) {
|
|
51
|
-
const lessonDir = path.join(sourceRoot, "lessons", "atomic-search");
|
|
52
|
-
await fs.mkdir(lessonDir, { recursive: true });
|
|
53
|
-
await fs.writeFile(path.join(lessonDir, "lesson.md"), "# Atomic search\n\nSearch atoms/molecules/organisms first.\n", "utf8");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
async function makeCompositeSource() {
|
|
57
|
-
const yaml = `
|
|
58
|
-
id: fullstack-bundle
|
|
59
|
-
kind: composite
|
|
60
|
-
version: 1.0.0
|
|
61
|
-
includes:
|
|
62
|
-
- { id: react, semver: ">=18" }
|
|
63
|
-
- { id: tdd, semver: ">=1" }
|
|
64
|
-
`;
|
|
65
|
-
await fs.writeFile(path.join(sourceRoot, "codex.yaml"), yaml, "utf8");
|
|
66
|
-
}
|
|
67
|
-
// ---------------------------------------------------------------------
|
|
68
|
-
// install
|
|
69
|
-
// ---------------------------------------------------------------------
|
|
70
|
-
describe("runCodexCli install", () => {
|
|
71
|
-
it("installs a focused codex from a local directory", async () => {
|
|
72
|
-
await makeSourceCodex({ withLessonBody: true });
|
|
73
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
74
|
-
const manifest = path.join(codexDir("react-19", tmpRoot), "codex.yaml");
|
|
75
|
-
expect((await fs.stat(manifest)).isFile()).toBe(true);
|
|
76
|
-
});
|
|
77
|
-
it("copies lesson bodies + companion files into canonical location", async () => {
|
|
78
|
-
await makeSourceCodex({ withLessonBody: true });
|
|
79
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
80
|
-
const lessonBody = path.join(codexDir("react-19", tmpRoot), "lessons", "atomic-search", "lesson.md");
|
|
81
|
-
expect((await fs.stat(lessonBody)).isFile()).toBe(true);
|
|
82
|
-
const content = await fs.readFile(lessonBody, "utf8");
|
|
83
|
-
expect(content).toContain("Atomic search");
|
|
84
|
-
});
|
|
85
|
-
it("installs a composite codex (no content copy)", async () => {
|
|
86
|
-
await makeCompositeSource();
|
|
87
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
88
|
-
const dir = codexDir("fullstack-bundle", tmpRoot);
|
|
89
|
-
const entries = await fs.readdir(dir);
|
|
90
|
-
expect(entries).toEqual(["codex.yaml"]);
|
|
91
|
-
});
|
|
92
|
-
it("accepts an explicit codex.yaml path (not just the dir)", async () => {
|
|
93
|
-
await makeSourceCodex();
|
|
94
|
-
const explicitFile = path.join(sourceRoot, "codex.yaml");
|
|
95
|
-
await runCodexCli("install", [explicitFile, "--root", tmpRoot, "--no-seed"]);
|
|
96
|
-
expect((await fs.stat(path.join(codexDir("react-19", tmpRoot), "codex.yaml"))).isFile()).toBe(true);
|
|
97
|
-
});
|
|
98
|
-
it("throws when source path doesn't exist", async () => {
|
|
99
|
-
await expect(runCodexCli("install", ["/nonexistent/path", "--root", tmpRoot])).rejects.toThrow(CodexCliError);
|
|
100
|
-
});
|
|
101
|
-
it("throws when codex.yaml is missing from source dir", async () => {
|
|
102
|
-
await expect(runCodexCli("install", [sourceRoot, "--root", tmpRoot])).rejects.toThrow(CodexCliError);
|
|
103
|
-
});
|
|
104
|
-
it("throws on malformed codex.yaml", async () => {
|
|
105
|
-
await fs.writeFile(path.join(sourceRoot, "codex.yaml"), "id: bad-id-uppercase\nNOT_A: VALID_FIELD\n", "utf8");
|
|
106
|
-
await expect(runCodexCli("install", [sourceRoot, "--root", tmpRoot])).rejects.toThrow(CodexCliError);
|
|
107
|
-
});
|
|
108
|
-
it("respects --force on re-install", async () => {
|
|
109
|
-
await makeSourceCodex();
|
|
110
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
111
|
-
// Second install without --force throws ALREADY_INSTALLED.
|
|
112
|
-
await expect(runCodexCli("install", [sourceRoot, "--root", tmpRoot])).rejects.toThrow();
|
|
113
|
-
// With --force succeeds.
|
|
114
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--force", "--no-seed"]);
|
|
115
|
-
});
|
|
116
|
-
it("rejects missing source arg", async () => {
|
|
117
|
-
await expect(runCodexCli("install", ["--root", tmpRoot])).rejects.toThrow(CodexCliError);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
// ---------------------------------------------------------------------
|
|
121
|
-
// list
|
|
122
|
-
// ---------------------------------------------------------------------
|
|
123
|
-
describe("runCodexCli list", () => {
|
|
124
|
-
it("succeeds on empty root", async () => {
|
|
125
|
-
await runCodexCli("list", ["--root", tmpRoot]);
|
|
126
|
-
});
|
|
127
|
-
it("succeeds when codexes are installed", async () => {
|
|
128
|
-
await makeSourceCodex();
|
|
129
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
130
|
-
await runCodexCli("list", ["--root", tmpRoot]);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
// ---------------------------------------------------------------------
|
|
134
|
-
// remove
|
|
135
|
-
// ---------------------------------------------------------------------
|
|
136
|
-
describe("runCodexCli remove", () => {
|
|
137
|
-
it("removes an installed codex", async () => {
|
|
138
|
-
await makeSourceCodex();
|
|
139
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
140
|
-
await runCodexCli("remove", ["react-19", "--root", tmpRoot]);
|
|
141
|
-
await expect(fs.access(codexDir("react-19", tmpRoot))).rejects.toThrow();
|
|
142
|
-
});
|
|
143
|
-
it("is idempotent on missing codex", async () => {
|
|
144
|
-
// No throw — just no-op.
|
|
145
|
-
await runCodexCli("remove", ["ghost", "--root", tmpRoot]);
|
|
146
|
-
});
|
|
147
|
-
it("rejects missing id arg", async () => {
|
|
148
|
-
await expect(runCodexCli("remove", ["--root", tmpRoot])).rejects.toThrow(CodexCliError);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
// ---------------------------------------------------------------------
|
|
152
|
-
// doctor
|
|
153
|
-
// ---------------------------------------------------------------------
|
|
154
|
-
describe("runCodexCli doctor", () => {
|
|
155
|
-
it("reports empty state", async () => {
|
|
156
|
-
await runCodexCli("doctor", ["--root", tmpRoot]);
|
|
157
|
-
});
|
|
158
|
-
it("reports per-codex detail when id is passed", async () => {
|
|
159
|
-
await makeSourceCodex();
|
|
160
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
161
|
-
await runCodexCli("doctor", ["react-19", "--root", tmpRoot]);
|
|
162
|
-
});
|
|
163
|
-
it("reports gracefully on missing codex when id is passed", async () => {
|
|
164
|
-
await runCodexCli("doctor", ["ghost", "--root", tmpRoot]);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
// ---------------------------------------------------------------------
|
|
168
|
-
// flag parsing
|
|
169
|
-
// ---------------------------------------------------------------------
|
|
170
|
-
describe("flag parsing", () => {
|
|
171
|
-
it("honors --root override", async () => {
|
|
172
|
-
await makeSourceCodex();
|
|
173
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
174
|
-
// Codex should be in tmpRoot, NOT in the user's actual ~/.opensquid.
|
|
175
|
-
expect((await fs.stat(codexesDir(tmpRoot))).isDirectory()).toBe(true);
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
// ---------------------------------------------------------------------
|
|
179
|
-
// v0.6d — SKILL.md foreign-format auto-detect + install
|
|
180
|
-
// ---------------------------------------------------------------------
|
|
181
|
-
const ANTHROPIC_SKILL_MD = `---
|
|
182
|
-
name: pdf
|
|
183
|
-
description: Use when extracting text or tables from PDF files.
|
|
184
|
-
license: Apache-2.0
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
# PDF Skill
|
|
188
|
-
|
|
189
|
-
Use pdfplumber for text, PyMuPDF for images.
|
|
190
|
-
`;
|
|
191
|
-
const HERMES_SKILL_MD = `---
|
|
192
|
-
name: google_meet
|
|
193
|
-
description: Schedule and join Google Meet calls.
|
|
194
|
-
version: 1.2.0
|
|
195
|
-
author: Hermes Team
|
|
196
|
-
license: MIT
|
|
197
|
-
platforms:
|
|
198
|
-
- hermes
|
|
199
|
-
metadata:
|
|
200
|
-
hermes:
|
|
201
|
-
tags: [calendar, meetings]
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
# google_meet
|
|
205
|
-
|
|
206
|
-
Hermes integration for Meet.
|
|
207
|
-
`;
|
|
208
|
-
describe("install — SKILL.md auto-detect", () => {
|
|
209
|
-
it("converts a directory containing SKILL.md and installs as native codex", async () => {
|
|
210
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), ANTHROPIC_SKILL_MD, "utf8");
|
|
211
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
212
|
-
const installed = await getCodex("pdf", { rootDir: tmpRoot });
|
|
213
|
-
expect(installed.id).toBe("pdf");
|
|
214
|
-
expect(installed.version).toBe("1.0.0");
|
|
215
|
-
expect(installed.license).toBe("Apache-2.0");
|
|
216
|
-
if (!isFocusedCodex(installed))
|
|
217
|
-
throw new Error("expected focused codex");
|
|
218
|
-
expect(installed.source?.kind).toBe("skill_md");
|
|
219
|
-
expect(installed.source?.original_variant).toBe("anthropic");
|
|
220
|
-
expect(installed.source?.original_name).toBe("pdf");
|
|
221
|
-
// Lesson body got materialized.
|
|
222
|
-
const lessonBody = await fs.readFile(path.join(codexDir("pdf", tmpRoot), "lessons", "pdf", "lesson.md"), "utf8");
|
|
223
|
-
expect(lessonBody).toContain("Use pdfplumber for text");
|
|
224
|
-
});
|
|
225
|
-
it("converts a SKILL.md file path directly (not a directory)", async () => {
|
|
226
|
-
const filePath = path.join(sourceRoot, "SKILL.md");
|
|
227
|
-
await fs.writeFile(filePath, ANTHROPIC_SKILL_MD, "utf8");
|
|
228
|
-
await runCodexCli("install", [filePath, "--root", tmpRoot, "--no-seed"]);
|
|
229
|
-
const installed = await getCodex("pdf", { rootDir: tmpRoot });
|
|
230
|
-
expect(installed.id).toBe("pdf");
|
|
231
|
-
});
|
|
232
|
-
it("rewrites underscore names to hyphens (google_meet → google-meet)", async () => {
|
|
233
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), HERMES_SKILL_MD, "utf8");
|
|
234
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
235
|
-
const installed = await getCodex("google-meet", { rootDir: tmpRoot });
|
|
236
|
-
expect(installed.id).toBe("google-meet");
|
|
237
|
-
expect(installed.version).toBe("1.2.0");
|
|
238
|
-
if (!isFocusedCodex(installed))
|
|
239
|
-
throw new Error("expected focused codex");
|
|
240
|
-
expect(installed.source?.original_variant).toBe("hermes");
|
|
241
|
-
expect(installed.source?.original_name).toBe("google_meet");
|
|
242
|
-
expect(installed.metadata?.platforms).toEqual(["hermes"]);
|
|
243
|
-
});
|
|
244
|
-
it("prefers codex.yaml over SKILL.md when both exist (auto-detect)", async () => {
|
|
245
|
-
// Native codex says id=react-19; SKILL.md says id=pdf. Auto-detect
|
|
246
|
-
// picks codex.yaml. --source skill_md would override.
|
|
247
|
-
await makeSourceCodex({ withLessonBody: true });
|
|
248
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), ANTHROPIC_SKILL_MD, "utf8");
|
|
249
|
-
await runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"]);
|
|
250
|
-
const installed = await getCodex("react-19", { rootDir: tmpRoot });
|
|
251
|
-
expect(installed.id).toBe("react-19");
|
|
252
|
-
// pdf should NOT be installed.
|
|
253
|
-
await expect(getCodex("pdf", { rootDir: tmpRoot })).rejects.toThrow();
|
|
254
|
-
});
|
|
255
|
-
it("--source skill_md forces SKILL.md branch when both files exist", async () => {
|
|
256
|
-
await makeSourceCodex({ withLessonBody: true });
|
|
257
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), ANTHROPIC_SKILL_MD, "utf8");
|
|
258
|
-
await runCodexCli("install", [
|
|
259
|
-
sourceRoot,
|
|
260
|
-
"--root",
|
|
261
|
-
tmpRoot,
|
|
262
|
-
"--no-seed",
|
|
263
|
-
"--source",
|
|
264
|
-
"skill_md",
|
|
265
|
-
]);
|
|
266
|
-
const installed = await getCodex("pdf", { rootDir: tmpRoot });
|
|
267
|
-
expect(installed.id).toBe("pdf");
|
|
268
|
-
});
|
|
269
|
-
it("rejects invalid --source value", async () => {
|
|
270
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), ANTHROPIC_SKILL_MD, "utf8");
|
|
271
|
-
await expect(runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed", "--source", "yaml"])).rejects.toThrow(CodexCliError);
|
|
272
|
-
});
|
|
273
|
-
it("reports a clear error for malformed SKILL.md (missing description)", async () => {
|
|
274
|
-
await fs.writeFile(path.join(sourceRoot, "SKILL.md"), "---\nname: broken\n---\nbody\n", "utf8");
|
|
275
|
-
await expect(runCodexCli("install", [sourceRoot, "--root", tmpRoot, "--no-seed"])).rejects.toThrow(/description/);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SKILL.md → opensquid native codex converter (v0.6d).
|
|
3
|
-
*
|
|
4
|
-
* Pure functions. No filesystem side effects. Takes a raw SKILL.md
|
|
5
|
-
* string + optional path metadata, returns a `{codex, lesson}` pair
|
|
6
|
-
* that the install pipeline materializes to disk before calling the
|
|
7
|
-
* existing `installCodex` + `copyCodexContent` path.
|
|
8
|
-
*
|
|
9
|
-
* Handles the union of:
|
|
10
|
-
* - Anthropic skills (https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) — `name`, `description`, optional `license`, optional experimental `allowed-tools` / `model` / `compatibility`
|
|
11
|
-
* - obra/superpowers — strict Anthropic subset (name + description, CSO description discipline)
|
|
12
|
-
* - everything-claude-code (ECC) — Anthropic + non-standard `origin: ECC`
|
|
13
|
-
* - Hermes Agent skills (~/projects/hermes-agent/skills/) — Anthropic + `version` + `author` + `platforms` + `metadata.hermes.{tags, related_skills}`
|
|
14
|
-
*
|
|
15
|
-
* 100% deterministic. No LLM call. Per [[find-simple-solutions]]:
|
|
16
|
-
* frontmatter → codex.yaml is structural mapping; body → one lesson is
|
|
17
|
-
* the trivial 1:1 case that every sampled SKILL.md follows. Sub-skill
|
|
18
|
-
* body-splitting is deferred until a real corpus demands it.
|
|
19
|
-
*/
|
|
20
|
-
import type { Codex, CodexSource } from "./types.js";
|
|
21
|
-
export type SkillMdVariant = NonNullable<CodexSource["original_variant"]>;
|
|
22
|
-
export interface SkillMdParseResult {
|
|
23
|
-
frontmatter: Record<string, unknown>;
|
|
24
|
-
body: string;
|
|
25
|
-
}
|
|
26
|
-
export interface ConvertOptions {
|
|
27
|
-
/** Absolute path to the source SKILL.md (or its containing dir). */
|
|
28
|
-
originalPath?: string;
|
|
29
|
-
/** Wall-clock at conversion time. Defaults to `new Date().toISOString()`. */
|
|
30
|
-
now?: string;
|
|
31
|
-
}
|
|
32
|
-
export interface ConvertedLesson {
|
|
33
|
-
/** Lesson id (slug). */
|
|
34
|
-
id: string;
|
|
35
|
-
/** Path relative to the codex root — written via `lessons/<id>/lesson.md`. */
|
|
36
|
-
bodyPath: string;
|
|
37
|
-
/** Raw markdown body to write at `bodyPath`. */
|
|
38
|
-
body: string;
|
|
39
|
-
}
|
|
40
|
-
export interface ConvertedCodex {
|
|
41
|
-
codex: Codex;
|
|
42
|
-
lessons: ConvertedLesson[];
|
|
43
|
-
variant: SkillMdVariant;
|
|
44
|
-
}
|
|
45
|
-
export declare class SkillMdImportError extends Error {
|
|
46
|
-
readonly hint?: string | undefined;
|
|
47
|
-
constructor(message: string, hint?: string | undefined);
|
|
48
|
-
}
|
|
49
|
-
export declare function parseSkillMd(source: string): SkillMdParseResult;
|
|
50
|
-
export declare function slugify(name: string): string;
|
|
51
|
-
export declare function detectVariant(frontmatter: Record<string, unknown>, originalPath?: string): SkillMdVariant;
|
|
52
|
-
export declare function convertSkillMdToCodex(source: string, options?: ConvertOptions): ConvertedCodex;
|
|
53
|
-
//# sourceMappingURL=import-skill-md.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-skill-md.d.ts","sourceRoot":"","sources":["../../src.legacy/codex/import-skill-md.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAmB,WAAW,EAA2B,MAAM,YAAY,CAAC;AAM/F,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,cAAc,CAAC;CACzB;AAMD,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,CAAC,EAAE,MAAM;gBAD7B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAQD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CA6C/D;AAQD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY5C;AAMD,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,YAAY,CAAC,EAAE,MAAM,GACpB,cAAc,CA6BhB;AAMD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,cAAc,CA8HhB"}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SKILL.md → opensquid native codex converter (v0.6d).
|
|
3
|
-
*
|
|
4
|
-
* Pure functions. No filesystem side effects. Takes a raw SKILL.md
|
|
5
|
-
* string + optional path metadata, returns a `{codex, lesson}` pair
|
|
6
|
-
* that the install pipeline materializes to disk before calling the
|
|
7
|
-
* existing `installCodex` + `copyCodexContent` path.
|
|
8
|
-
*
|
|
9
|
-
* Handles the union of:
|
|
10
|
-
* - Anthropic skills (https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) — `name`, `description`, optional `license`, optional experimental `allowed-tools` / `model` / `compatibility`
|
|
11
|
-
* - obra/superpowers — strict Anthropic subset (name + description, CSO description discipline)
|
|
12
|
-
* - everything-claude-code (ECC) — Anthropic + non-standard `origin: ECC`
|
|
13
|
-
* - Hermes Agent skills (~/projects/hermes-agent/skills/) — Anthropic + `version` + `author` + `platforms` + `metadata.hermes.{tags, related_skills}`
|
|
14
|
-
*
|
|
15
|
-
* 100% deterministic. No LLM call. Per [[find-simple-solutions]]:
|
|
16
|
-
* frontmatter → codex.yaml is structural mapping; body → one lesson is
|
|
17
|
-
* the trivial 1:1 case that every sampled SKILL.md follows. Sub-skill
|
|
18
|
-
* body-splitting is deferred until a real corpus demands it.
|
|
19
|
-
*/
|
|
20
|
-
import { parse as parseYaml } from "yaml";
|
|
21
|
-
// ---------------------------------------------------------------------
|
|
22
|
-
// Errors
|
|
23
|
-
// ---------------------------------------------------------------------
|
|
24
|
-
export class SkillMdImportError extends Error {
|
|
25
|
-
hint;
|
|
26
|
-
constructor(message, hint) {
|
|
27
|
-
super(message);
|
|
28
|
-
this.hint = hint;
|
|
29
|
-
this.name = "SkillMdImportError";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// ---------------------------------------------------------------------
|
|
33
|
-
// Parse SKILL.md frontmatter + body
|
|
34
|
-
// ---------------------------------------------------------------------
|
|
35
|
-
const FRONTMATTER_FENCE_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
36
|
-
export function parseSkillMd(source) {
|
|
37
|
-
if (!source || !source.trim()) {
|
|
38
|
-
throw new SkillMdImportError("SKILL.md is empty", "SKILL.md must have a YAML frontmatter block + body");
|
|
39
|
-
}
|
|
40
|
-
// v0.6d audit fix (L1): strip UTF-8 BOM if present. The fence regex
|
|
41
|
-
// requires `---` at the very start; a BOM-prefixed file (common from
|
|
42
|
-
// Windows editors) would silently fail the match.
|
|
43
|
-
const stripped = source.charCodeAt(0) === 0xfeff ? source.slice(1) : source;
|
|
44
|
-
const match = stripped.match(FRONTMATTER_FENCE_RE);
|
|
45
|
-
if (!match) {
|
|
46
|
-
throw new SkillMdImportError("SKILL.md missing YAML frontmatter (--- ... ---) at top", "wrap your frontmatter in triple-dash fences and ensure the closing fence is on its own line");
|
|
47
|
-
}
|
|
48
|
-
const [, yamlText, bodyText] = match;
|
|
49
|
-
let parsed;
|
|
50
|
-
try {
|
|
51
|
-
parsed = parseYaml(yamlText);
|
|
52
|
-
}
|
|
53
|
-
catch (e) {
|
|
54
|
-
throw new SkillMdImportError(`SKILL.md frontmatter is not valid YAML: ${e instanceof Error ? e.message : String(e)}`, "frontmatter must be parseable as YAML (key: value pairs)");
|
|
55
|
-
}
|
|
56
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
57
|
-
throw new SkillMdImportError("SKILL.md frontmatter must be a YAML mapping (key: value pairs)");
|
|
58
|
-
}
|
|
59
|
-
const frontmatter = parsed;
|
|
60
|
-
if (typeof frontmatter.name !== "string" || !frontmatter.name.trim()) {
|
|
61
|
-
throw new SkillMdImportError("SKILL.md frontmatter missing required `name` field", "per the Anthropic spec, `name` is required (max 64 chars, [a-z0-9-])");
|
|
62
|
-
}
|
|
63
|
-
if (typeof frontmatter.description !== "string" || !frontmatter.description.trim()) {
|
|
64
|
-
throw new SkillMdImportError("SKILL.md frontmatter missing required `description` field", "per the Anthropic spec, `description` is required (max 1024 chars)");
|
|
65
|
-
}
|
|
66
|
-
return { frontmatter, body: (bodyText ?? "").trim() };
|
|
67
|
-
}
|
|
68
|
-
// ---------------------------------------------------------------------
|
|
69
|
-
// Slugify (ASCII-safe — sampled SKILL.md names are all ASCII)
|
|
70
|
-
// ---------------------------------------------------------------------
|
|
71
|
-
const SLUG_MAX_LEN = 64;
|
|
72
|
-
export function slugify(name) {
|
|
73
|
-
const lower = name.toLowerCase();
|
|
74
|
-
// Replace any run of non-alphanumerics with a single dash. Trim
|
|
75
|
-
// leading/trailing dashes. Cap length per Anthropic spec.
|
|
76
|
-
const dashed = lower.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
77
|
-
if (!dashed) {
|
|
78
|
-
throw new SkillMdImportError(`cannot slugify name "${name}" (no alphanumeric characters)`, "skill names must include at least one ASCII letter or digit");
|
|
79
|
-
}
|
|
80
|
-
return dashed.slice(0, SLUG_MAX_LEN);
|
|
81
|
-
}
|
|
82
|
-
// ---------------------------------------------------------------------
|
|
83
|
-
// Variant detection
|
|
84
|
-
// ---------------------------------------------------------------------
|
|
85
|
-
export function detectVariant(frontmatter, originalPath) {
|
|
86
|
-
if (frontmatter.origin === "ECC")
|
|
87
|
-
return "ecc";
|
|
88
|
-
// Hermes: rich frontmatter (`platforms`, `metadata.hermes.*`)
|
|
89
|
-
if (Array.isArray(frontmatter.platforms))
|
|
90
|
-
return "hermes";
|
|
91
|
-
const meta = frontmatter.metadata;
|
|
92
|
-
if (meta && typeof meta === "object" && !Array.isArray(meta)) {
|
|
93
|
-
if (meta.hermes !== undefined)
|
|
94
|
-
return "hermes";
|
|
95
|
-
}
|
|
96
|
-
// superpowers: path-based detection only. The CSO "Use when..." phrasing
|
|
97
|
-
// is recommended by superpowers but Anthropic's own skill-creator also
|
|
98
|
-
// uses it, so description alone is too noisy to distinguish.
|
|
99
|
-
const path = (originalPath ?? "").toLowerCase();
|
|
100
|
-
if (path.includes("superpowers/skills/") || path.includes("/superpowers/")) {
|
|
101
|
-
return "superpowers";
|
|
102
|
-
}
|
|
103
|
-
// Pure Anthropic minimum: only name + description (+ optional license)
|
|
104
|
-
const keys = new Set(Object.keys(frontmatter));
|
|
105
|
-
const anthropicKnown = new Set([
|
|
106
|
-
"name",
|
|
107
|
-
"description",
|
|
108
|
-
"license",
|
|
109
|
-
"compatibility",
|
|
110
|
-
"metadata",
|
|
111
|
-
"allowed-tools",
|
|
112
|
-
"model",
|
|
113
|
-
]);
|
|
114
|
-
const allKnown = [...keys].every((k) => anthropicKnown.has(k));
|
|
115
|
-
if (allKnown)
|
|
116
|
-
return "anthropic";
|
|
117
|
-
return "unknown";
|
|
118
|
-
}
|
|
119
|
-
// ---------------------------------------------------------------------
|
|
120
|
-
// Main conversion
|
|
121
|
-
// ---------------------------------------------------------------------
|
|
122
|
-
export function convertSkillMdToCodex(source, options = {}) {
|
|
123
|
-
const { frontmatter, body } = parseSkillMd(source);
|
|
124
|
-
const rawName = frontmatter.name.trim();
|
|
125
|
-
const id = slugify(rawName);
|
|
126
|
-
const description = frontmatter.description.trim();
|
|
127
|
-
const variant = detectVariant(frontmatter, options.originalPath);
|
|
128
|
-
const now = options.now ?? new Date().toISOString();
|
|
129
|
-
// ----- version: Hermes provides one; default to "1.0.0" otherwise -----
|
|
130
|
-
let version = "1.0.0";
|
|
131
|
-
let versionSynthesized = true;
|
|
132
|
-
if (typeof frontmatter.version === "string" && frontmatter.version.trim()) {
|
|
133
|
-
version = frontmatter.version.trim();
|
|
134
|
-
versionSynthesized = false;
|
|
135
|
-
}
|
|
136
|
-
// ----- author: Hermes "author" is a flat string; opensquid wants {name, contact?} -----
|
|
137
|
-
let author;
|
|
138
|
-
const rawAuthor = frontmatter.author;
|
|
139
|
-
if (typeof rawAuthor === "string" && rawAuthor.trim()) {
|
|
140
|
-
author = { name: rawAuthor.trim() };
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
author = { name: "Imported from SKILL.md" };
|
|
144
|
-
}
|
|
145
|
-
// ----- license: pass through if present -----
|
|
146
|
-
const license = typeof frontmatter.license === "string" && frontmatter.license.trim()
|
|
147
|
-
? frontmatter.license.trim()
|
|
148
|
-
: undefined;
|
|
149
|
-
// ----- foundation.tools from Anthropic experimental `allowed-tools` -----
|
|
150
|
-
let tools;
|
|
151
|
-
const allowedTools = frontmatter["allowed-tools"];
|
|
152
|
-
if (Array.isArray(allowedTools) && allowedTools.length > 0) {
|
|
153
|
-
tools = [];
|
|
154
|
-
for (const t of allowedTools) {
|
|
155
|
-
if (typeof t === "string" && t.trim()) {
|
|
156
|
-
tools.push({ name: t.trim() });
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (tools.length === 0)
|
|
160
|
-
tools = undefined;
|
|
161
|
-
}
|
|
162
|
-
// ----- preserved non-standard frontmatter → metadata extensibility bucket -----
|
|
163
|
-
const metadata = { imported_from: "skill_md" };
|
|
164
|
-
if (versionSynthesized) {
|
|
165
|
-
// mark for downstream auditing
|
|
166
|
-
metadata.imported = { synthesized_version: true };
|
|
167
|
-
}
|
|
168
|
-
// Preserve every frontmatter key we don't have a first-class slot for.
|
|
169
|
-
for (const [k, v] of Object.entries(frontmatter)) {
|
|
170
|
-
if (k === "name" ||
|
|
171
|
-
k === "description" ||
|
|
172
|
-
k === "version" ||
|
|
173
|
-
k === "author" ||
|
|
174
|
-
k === "license" ||
|
|
175
|
-
k === "allowed-tools") {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
// Anthropic optional `model` → metadata.model. Hermes `platforms` →
|
|
179
|
-
// metadata.platforms. ECC `origin` → metadata.origin. Hermes
|
|
180
|
-
// `metadata.hermes.*` is already a nested object; preserve it under
|
|
181
|
-
// metadata.hermes (don't flatten).
|
|
182
|
-
if (k === "metadata" && v && typeof v === "object" && !Array.isArray(v)) {
|
|
183
|
-
// Merge into our metadata bucket without overwriting our own keys.
|
|
184
|
-
for (const [mk, mv] of Object.entries(v)) {
|
|
185
|
-
if (!(mk in metadata)) {
|
|
186
|
-
metadata[mk] = mv;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
metadata[k] = v;
|
|
192
|
-
}
|
|
193
|
-
// ----- source provenance -----
|
|
194
|
-
const sourceBlock = {
|
|
195
|
-
kind: "skill_md",
|
|
196
|
-
original_variant: variant,
|
|
197
|
-
original_name: rawName,
|
|
198
|
-
original_path: options.originalPath,
|
|
199
|
-
imported_at: now,
|
|
200
|
-
};
|
|
201
|
-
// ----- seed lesson (one cohesive lesson per SKILL.md) -----
|
|
202
|
-
// The lesson trigger is the description verbatim — lossy in tone but
|
|
203
|
-
// functionally correct. Future LLM-mediated trigger synthesis (deferred)
|
|
204
|
-
// could rewrite into the imperative voice opensquid prefers.
|
|
205
|
-
const seedLesson = {
|
|
206
|
-
id,
|
|
207
|
-
trigger: description,
|
|
208
|
-
priority: "medium",
|
|
209
|
-
bank_strategy: "full",
|
|
210
|
-
body_path: `lessons/${id}/lesson.md`,
|
|
211
|
-
};
|
|
212
|
-
// Lesson body = the SKILL.md body verbatim. If empty (extremely rare —
|
|
213
|
-
// would mean a frontmatter-only file), synthesize a stub.
|
|
214
|
-
const lessonBody = body.length > 0
|
|
215
|
-
? body
|
|
216
|
-
: `# ${rawName}\n\n${description}\n\n*(Imported from SKILL.md with no body content.)*\n`;
|
|
217
|
-
const codex = {
|
|
218
|
-
id,
|
|
219
|
-
version,
|
|
220
|
-
description,
|
|
221
|
-
author,
|
|
222
|
-
license,
|
|
223
|
-
source: sourceBlock,
|
|
224
|
-
metadata,
|
|
225
|
-
kind: "focused",
|
|
226
|
-
foundation: tools ? { tools } : undefined,
|
|
227
|
-
seed_lessons: [seedLesson],
|
|
228
|
-
evolves: true,
|
|
229
|
-
};
|
|
230
|
-
return {
|
|
231
|
-
codex,
|
|
232
|
-
lessons: [{ id, bodyPath: seedLesson.body_path, body: lessonBody }],
|
|
233
|
-
variant,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
//# sourceMappingURL=import-skill-md.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"import-skill-md.js","sourceRoot":"","sources":["../../src.legacy/codex/import-skill-md.ts"],"names":[],"mappings":"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"}
|