@starci/skills 1.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/INDEX.md +74 -0
- package/INDEX.vi.md +75 -0
- package/README.md +44 -0
- package/README.vi.md +43 -0
- package/SKILL.md +135 -0
- package/SKILL.vi.md +128 -0
- package/alias/INDEX.md +104 -0
- package/alias/INDEX.vi.md +104 -0
- package/alias/alias.json +297 -0
- package/bin/starci-skills.mjs +219 -0
- package/knowledge/INDEX.md +22 -0
- package/knowledge/INDEX.vi.md +22 -0
- package/knowledge/grammars/starci/DNA.md +146 -0
- package/knowledge/grammars/starci/DNA.vi.md +146 -0
- package/knowledge/grammars/starci/INDEX.md +25 -0
- package/knowledge/grammars/starci/INDEX.vi.md +25 -0
- package/knowledge/grammars/starci/family.md +50 -0
- package/knowledge/grammars/starci/family.vi.md +50 -0
- package/knowledge/grammars/starci/idioms.md +120 -0
- package/knowledge/grammars/starci/idioms.vi.md +121 -0
- package/knowledge/grammars/starci/playbook.md +36 -0
- package/knowledge/grammars/starci/playbook.vi.md +35 -0
- package/knowledge/patterns/be/INDEX.md +29 -0
- package/knowledge/patterns/be/INDEX.vi.md +29 -0
- package/knowledge/patterns/be/comment.md +80 -0
- package/knowledge/patterns/be/comment.vi.md +80 -0
- package/knowledge/patterns/be/error.md +86 -0
- package/knowledge/patterns/be/error.vi.md +86 -0
- package/knowledge/patterns/be/folder.md +87 -0
- package/knowledge/patterns/be/folder.vi.md +86 -0
- package/knowledge/patterns/be/function.md +80 -0
- package/knowledge/patterns/be/function.vi.md +80 -0
- package/knowledge/patterns/be/imports.md +79 -0
- package/knowledge/patterns/be/imports.vi.md +79 -0
- package/knowledge/patterns/be/naming.md +87 -0
- package/knowledge/patterns/be/naming.vi.md +87 -0
- package/knowledge/patterns/be/test.md +79 -0
- package/knowledge/patterns/be/test.vi.md +79 -0
- package/knowledge/patterns/be/typing.md +73 -0
- package/knowledge/patterns/be/typing.vi.md +73 -0
- package/knowledge/patterns/fe/INDEX.md +29 -0
- package/knowledge/patterns/fe/INDEX.vi.md +29 -0
- package/knowledge/patterns/fe/comment.md +70 -0
- package/knowledge/patterns/fe/comment.vi.md +70 -0
- package/knowledge/patterns/fe/error.md +61 -0
- package/knowledge/patterns/fe/error.vi.md +61 -0
- package/knowledge/patterns/fe/folder.md +98 -0
- package/knowledge/patterns/fe/folder.vi.md +95 -0
- package/knowledge/patterns/fe/function.md +70 -0
- package/knowledge/patterns/fe/function.vi.md +70 -0
- package/knowledge/patterns/fe/imports.md +87 -0
- package/knowledge/patterns/fe/imports.vi.md +87 -0
- package/knowledge/patterns/fe/naming.md +77 -0
- package/knowledge/patterns/fe/naming.vi.md +77 -0
- package/knowledge/patterns/fe/test.md +73 -0
- package/knowledge/patterns/fe/test.vi.md +73 -0
- package/knowledge/patterns/fe/typing.md +67 -0
- package/knowledge/patterns/fe/typing.vi.md +67 -0
- package/knowledge/ui/INDEX.md +101 -0
- package/knowledge/ui/INDEX.vi.md +101 -0
- package/knowledge/ui/composition/INDEX.md +60 -0
- package/knowledge/ui/composition/INDEX.vi.md +63 -0
- package/knowledge/ui/composition/accent.md +73 -0
- package/knowledge/ui/composition/accent.vi.md +74 -0
- package/knowledge/ui/composition/action.md +55 -0
- package/knowledge/ui/composition/action.vi.md +56 -0
- package/knowledge/ui/composition/coverage.md +37 -0
- package/knowledge/ui/composition/coverage.vi.md +37 -0
- package/knowledge/ui/composition/cta.md +79 -0
- package/knowledge/ui/composition/cta.vi.md +79 -0
- package/knowledge/ui/composition/feedback.md +55 -0
- package/knowledge/ui/composition/feedback.vi.md +56 -0
- package/knowledge/ui/composition/hierarchy.md +83 -0
- package/knowledge/ui/composition/hierarchy.vi.md +82 -0
- package/knowledge/ui/composition/layout.md +91 -0
- package/knowledge/ui/composition/layout.vi.md +93 -0
- package/knowledge/ui/composition/responsive.md +67 -0
- package/knowledge/ui/composition/responsive.vi.md +67 -0
- package/knowledge/ui/composition/state.md +105 -0
- package/knowledge/ui/composition/state.vi.md +106 -0
- package/knowledge/ui/presentation/INDEX.md +94 -0
- package/knowledge/ui/presentation/INDEX.vi.md +69 -0
- package/knowledge/ui/presentation/boundary.md +170 -0
- package/knowledge/ui/presentation/boundary.vi.md +169 -0
- package/knowledge/ui/presentation/font.md +155 -0
- package/knowledge/ui/presentation/font.vi.md +156 -0
- package/knowledge/ui/presentation/gap.md +181 -0
- package/knowledge/ui/presentation/gap.vi.md +181 -0
- package/knowledge/ui/presentation/margin.md +168 -0
- package/knowledge/ui/presentation/margin.vi.md +171 -0
- package/knowledge/ui/presentation/measure.md +174 -0
- package/knowledge/ui/presentation/measure.vi.md +178 -0
- package/knowledge/ui/presentation/overflow.md +142 -0
- package/knowledge/ui/presentation/overflow.vi.md +142 -0
- package/knowledge/ui/presentation/padding.md +293 -0
- package/knowledge/ui/presentation/padding.vi.md +292 -0
- package/knowledge/ui/presentation/surface.md +166 -0
- package/knowledge/ui/presentation/surface.vi.md +166 -0
- package/knowledge/ui/presentation/text-flow.md +123 -0
- package/knowledge/ui/presentation/text-flow.vi.md +123 -0
- package/knowledge/ui/presentation/tone.md +114 -0
- package/knowledge/ui/presentation/tone.vi.md +113 -0
- package/knowledge/ui/proof/INDEX.md +55 -0
- package/knowledge/ui/proof/INDEX.vi.md +55 -0
- package/knowledge/ui/proof/accessibility.md +67 -0
- package/knowledge/ui/proof/accessibility.vi.md +68 -0
- package/knowledge/ui/proof/contrast.md +58 -0
- package/knowledge/ui/proof/contrast.vi.md +57 -0
- package/knowledge/ui/proof/focus.md +76 -0
- package/knowledge/ui/proof/focus.vi.md +76 -0
- package/knowledge/ui/proof/motion.md +63 -0
- package/knowledge/ui/proof/motion.vi.md +64 -0
- package/knowledge/ui/proof/render-truth.md +63 -0
- package/knowledge/ui/proof/render-truth.vi.md +63 -0
- package/operators/INDEX.md +199 -0
- package/operators/INDEX.vi.md +199 -0
- package/operators/architecture-decide/errors.json +115 -0
- package/operators/architecture-decide/operator.json +20 -0
- package/operators/architecture-decide/operator.md +133 -0
- package/operators/architecture-decide/operator.vi.md +130 -0
- package/operators/architecture-decide/self-test.mjs +221 -0
- package/operators/architecture-decide/validate.mjs +112 -0
- package/operators/backend-source-apply/errors.json +66 -0
- package/operators/backend-source-apply/operator.json +20 -0
- package/operators/backend-source-apply/operator.md +189 -0
- package/operators/backend-source-apply/operator.vi.md +185 -0
- package/operators/backend-source-apply/self-test.mjs +257 -0
- package/operators/backend-source-apply/validate.mjs +240 -0
- package/operators/business-decide/errors.json +78 -0
- package/operators/business-decide/operator.json +20 -0
- package/operators/business-decide/operator.md +176 -0
- package/operators/business-decide/operator.vi.md +174 -0
- package/operators/business-decide/self-test.mjs +225 -0
- package/operators/business-decide/validate.mjs +277 -0
- package/operators/content-generate/errors.json +106 -0
- package/operators/content-generate/operator.json +21 -0
- package/operators/content-generate/operator.md +155 -0
- package/operators/content-generate/operator.vi.md +155 -0
- package/operators/content-generate/self-test.mjs +288 -0
- package/operators/content-generate/validate.mjs +196 -0
- package/operators/errors.json +178 -0
- package/operators/frontend-direction-decide/errors.json +135 -0
- package/operators/frontend-direction-decide/operator.json +21 -0
- package/operators/frontend-direction-decide/operator.md +167 -0
- package/operators/frontend-direction-decide/operator.vi.md +167 -0
- package/operators/frontend-direction-decide/self-test.mjs +226 -0
- package/operators/frontend-direction-decide/validate.mjs +146 -0
- package/operators/frontend-presentation-resolve/errors.json +42 -0
- package/operators/frontend-presentation-resolve/operator.json +19 -0
- package/operators/frontend-presentation-resolve/operator.md +142 -0
- package/operators/frontend-presentation-resolve/operator.vi.md +140 -0
- package/operators/frontend-presentation-resolve/self-test.mjs +163 -0
- package/operators/frontend-presentation-resolve/validate.mjs +143 -0
- package/operators/frontend-source-apply/errors.json +30 -0
- package/operators/frontend-source-apply/operator.json +20 -0
- package/operators/frontend-source-apply/operator.md +127 -0
- package/operators/frontend-source-apply/operator.vi.md +126 -0
- package/operators/frontend-source-apply/self-test.mjs +214 -0
- package/operators/frontend-source-apply/validate.mjs +133 -0
- package/operators/frontend-surface-audit/errors.json +5 -0
- package/operators/frontend-surface-audit/operator.json +22 -0
- package/operators/frontend-surface-audit/operator.md +121 -0
- package/operators/frontend-surface-audit/operator.vi.md +121 -0
- package/operators/frontend-surface-audit/self-test.mjs +185 -0
- package/operators/frontend-surface-audit/validate.mjs +127 -0
- package/operators/git-publish/errors.json +54 -0
- package/operators/git-publish/operator.json +20 -0
- package/operators/git-publish/operator.md +180 -0
- package/operators/git-publish/operator.vi.md +178 -0
- package/operators/git-publish/self-test.mjs +177 -0
- package/operators/git-publish/validate.mjs +106 -0
- package/operators/platform-operate/errors.json +90 -0
- package/operators/platform-operate/operator.json +22 -0
- package/operators/platform-operate/operator.md +162 -0
- package/operators/platform-operate/operator.vi.md +160 -0
- package/operators/platform-operate/self-test.mjs +202 -0
- package/operators/platform-operate/validate.mjs +193 -0
- package/operators/quality-verify/errors.json +54 -0
- package/operators/quality-verify/operator.json +20 -0
- package/operators/quality-verify/operator.md +185 -0
- package/operators/quality-verify/operator.vi.md +177 -0
- package/operators/quality-verify/self-test.mjs +210 -0
- package/operators/quality-verify/validate.mjs +197 -0
- package/operators/release-deploy/errors.json +158 -0
- package/operators/release-deploy/operator.json +23 -0
- package/operators/release-deploy/operator.md +183 -0
- package/operators/release-deploy/operator.vi.md +181 -0
- package/operators/release-deploy/self-test.mjs +235 -0
- package/operators/release-deploy/validate.mjs +129 -0
- package/operators/uat-verify/errors.json +78 -0
- package/operators/uat-verify/operator.json +25 -0
- package/operators/uat-verify/operator.md +162 -0
- package/operators/uat-verify/operator.vi.md +161 -0
- package/operators/uat-verify/self-test.mjs +270 -0
- package/operators/uat-verify/validate.mjs +202 -0
- package/operators/workspace-bind/errors.json +90 -0
- package/operators/workspace-bind/operator.json +21 -0
- package/operators/workspace-bind/operator.md +148 -0
- package/operators/workspace-bind/operator.vi.md +148 -0
- package/operators/workspace-bind/self-test.mjs +205 -0
- package/operators/workspace-bind/validate.mjs +152 -0
- package/package.json +50 -0
- package/readiness/initialization/workspaces/commit-policy.json +91 -0
- package/readiness/initialization/workspaces/config.schema.json +35 -0
- package/readiness/initialization/workspaces/device-state.schema.json +54 -0
- package/readiness/initialization/workspaces/local-route.schema.json +206 -0
- package/readiness/initialization/workspaces/portable-route.schema.json +200 -0
- package/resources/INDEX.md +96 -0
- package/resources/INDEX.vi.md +99 -0
- package/resources/agents/profiles/claude.json +131 -0
- package/resources/agents/profiles/openai.json +131 -0
- package/resources/orchestrator.json +71 -0
- package/resources/tools.json +85 -0
- package/routing.json +272 -0
- package/scripts/alias-registry.mjs +31 -0
- package/scripts/device-state.mjs +497 -0
- package/scripts/device-state.spec.mjs +18 -0
- package/scripts/errors-registry.mjs +68 -0
- package/scripts/generate-alias-doc.mjs +66 -0
- package/scripts/generate-grammar-dna.mjs +387 -0
- package/scripts/generate-operators-index.mjs +95 -0
- package/scripts/generate-presentation-owned.mjs +681 -0
- package/scripts/install-cli.spec.mjs +74 -0
- package/scripts/json-schema.mjs +94 -0
- package/scripts/operator-md.mjs +96 -0
- package/scripts/run-operator-self-tests.mjs +36 -0
- package/scripts/validate-alias.mjs +165 -0
- package/scripts/validate-defaults.mjs +72 -0
- package/scripts/validate-knowledge-citations.mjs +90 -0
- package/scripts/validate-operator.mjs +125 -0
- package/scripts/validate-request.mjs +80 -0
- package/scripts/validate-resources.mjs +117 -0
- package/scripts/validate-response.mjs +141 -0
- package/scripts/validate-routing.mjs +91 -0
- package/scripts/validate-step.mjs +50 -0
- package/scripts/validate-templates.mjs +226 -0
- package/scripts/validate-templates.spec.mjs +144 -0
- package/scripts/validate-workflows.mjs +106 -0
- package/scripts/workspace-portable.mjs +389 -0
- package/scripts/workspace-portable.spec.mjs +246 -0
- package/templates/README.md +47 -0
- package/templates/README.vi.md +45 -0
- package/templates/changes.example.md +27 -0
- package/templates/grammars.template.md +34 -0
- package/templates/kinds/architecture-decision.contract.json +14 -0
- package/templates/kinds/architecture-decision.skeleton.md +52 -0
- package/templates/kinds/backend-source-application.contract.json +10 -0
- package/templates/kinds/backend-source-application.skeleton.md +34 -0
- package/templates/kinds/business-promise-authority.contract.json +13 -0
- package/templates/kinds/business-promise-authority.skeleton.md +67 -0
- package/templates/kinds/capture.schema.json +33 -0
- package/templates/kinds/changes.contract.json +10 -0
- package/templates/kinds/changes.skeleton.md +26 -0
- package/templates/kinds/checks.schema.json +44 -0
- package/templates/kinds/claims.schema.json +165 -0
- package/templates/kinds/conformance.schema.json +15 -0
- package/templates/kinds/content-brief.contract.json +12 -0
- package/templates/kinds/content-brief.skeleton.md +45 -0
- package/templates/kinds/content-generation-receipt.contract.json +11 -0
- package/templates/kinds/content-generation-receipt.skeleton.md +40 -0
- package/templates/kinds/content-review.contract.json +11 -0
- package/templates/kinds/content-review.skeleton.md +45 -0
- package/templates/kinds/contract.schema.json +28 -0
- package/templates/kinds/coverage-matrix.schema.json +86 -0
- package/templates/kinds/coverage.schema.json +62 -0
- package/templates/kinds/current-state.schema.json +40 -0
- package/templates/kinds/delta.schema.json +95 -0
- package/templates/kinds/e2e.schema.json +63 -0
- package/templates/kinds/frontend-direction-decision.contract.json +93 -0
- package/templates/kinds/frontend-direction-decision.skeleton.md +68 -0
- package/templates/kinds/frontend-presentation-resolution.contract.json +11 -0
- package/templates/kinds/frontend-presentation-resolution.skeleton.md +32 -0
- package/templates/kinds/frontend-source-application.contract.json +10 -0
- package/templates/kinds/frontend-source-application.skeleton.md +30 -0
- package/templates/kinds/frontend-surface-audit.contract.json +52 -0
- package/templates/kinds/frontend-surface-audit.skeleton.md +32 -0
- package/templates/kinds/gate-result.schema.json +64 -0
- package/templates/kinds/git-publication.contract.json +82 -0
- package/templates/kinds/git-publication.skeleton.md +61 -0
- package/templates/kinds/independent-critique.contract.json +9 -0
- package/templates/kinds/independent-critique.skeleton.md +28 -0
- package/templates/kinds/inventory.schema.json +35 -0
- package/templates/kinds/model.schema.json +99 -0
- package/templates/kinds/mutations.schema.json +65 -0
- package/templates/kinds/platform-operation-receipt.contract.json +76 -0
- package/templates/kinds/platform-operation-receipt.skeleton.md +54 -0
- package/templates/kinds/probes.schema.json +130 -0
- package/templates/kinds/proof.schema.json +17 -0
- package/templates/kinds/quality-verification.contract.json +87 -0
- package/templates/kinds/quality-verification.skeleton.md +58 -0
- package/templates/kinds/release-deployment.contract.json +85 -0
- package/templates/kinds/release-deployment.skeleton.md +67 -0
- package/templates/kinds/route.schema.json +293 -0
- package/templates/kinds/stack-model.schema.json +90 -0
- package/templates/kinds/uat-capture.schema.json +35 -0
- package/templates/kinds/uat-flow-verification.contract.json +11 -0
- package/templates/kinds/uat-flow-verification.skeleton.md +47 -0
- package/templates/kinds/uat-snapshot.schema.json +96 -0
- package/templates/kinds/uat-verdicts.schema.json +41 -0
- package/templates/kinds/ui-coverage.schema.json +77 -0
- package/templates/kinds/verdicts.schema.json +39 -0
- package/templates/kinds/workspace-route-binding.contract.json +12 -0
- package/templates/kinds/workspace-route-binding.skeleton.md +60 -0
- package/templates/kinds/writes.schema.json +37 -0
- package/templates/operator.template.md +73 -0
- package/templates/patterns.template.md +31 -0
- package/templates/step/request.schema.json +42 -0
- package/templates/step/response.schema.json +144 -0
- package/templates/ui-composition.template.md +36 -0
- package/templates/ui-presentation.template.md +57 -0
- package/templates/ui-proof.template.md +34 -0
- package/workflows/README.md +37 -0
- package/workflows/README.vi.md +37 -0
- package/workflows/backend-feature.json +59 -0
- package/workflows/content-unit.json +19 -0
- package/workflows/frontend-new-surface.json +81 -0
- package/workflows/frontend-reconstruct.json +67 -0
- package/workflows/frontend-refine.json +67 -0
- package/workflows/frontend-with-uat.json +78 -0
- package/workflows/full-feature.json +104 -0
- package/workflows/release.json +29 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 8,
|
|
3
|
+
"note": "How operators become agents. One invocation of one operator is one agent, created fresh on the operator's own profile (operator.json → resources) with the aliases its Context table declares and nothing else. The orchestrator owns dispatch: it writes the branch's request/request.json, validates it (scripts/validate-request.mjs), starts the agent, validates the response (scripts/validate-response.mjs, then the operator's validate.mjs), and follows routing.json to the next operator, user, or external party. It never merges two operators into one agent and never lets an agent start another; a nested exchange (a step that pauses with status waiting, e.g. architecture.decide's critique) is served by a second fresh agent the orchestrator spawns, with its own request/ and response/ inside the branch.",
|
|
4
|
+
"agentPerOperator": true,
|
|
5
|
+
"maxConcurrentAgents": 3,
|
|
6
|
+
"dispatch": "routing.json",
|
|
7
|
+
"agent": {
|
|
8
|
+
"profile": "operator.json → resources.profile",
|
|
9
|
+
"grants": "operator.json → resources.tools: each @tools/<id> with one mode from resources/tools.json, and nothing the profile would otherwise permit",
|
|
10
|
+
"refs": "operator.md → Context table, resolved through alias/alias.json; an unlisted location is unreadable",
|
|
11
|
+
"requirements": "operator.md → Requirements table; the orchestrator fills defaults into request.json and asks a person only for fields whose Default is — or whose value a stop code names",
|
|
12
|
+
"prompt": "rendered at dispatch from operator.md plus request.json; never stored",
|
|
13
|
+
"isolation": "fresh, no inherited turns",
|
|
14
|
+
"writes": "only response/ of its own branch (step-N/parallel-M/response/); a nested-exchange agent writes only <exchange>/response/ of that branch; a source-writing operator also writes the session branch of its checkout under an exclusive lease (see sourceWrites)"
|
|
15
|
+
},
|
|
16
|
+
"concurrency": {
|
|
17
|
+
"rule": "at most maxConcurrentAgents agents at once; branches of one step run concurrently only when their Writes touch no common alias",
|
|
18
|
+
"sharedCheckout": "two agents may read one checkout; only one may hold it for writing (backend.source.apply, frontend.source.apply, git.publish are exclusive per checkout)",
|
|
19
|
+
"sharedRoot": "business.decide is exclusive per businesses root; platform.operate is exclusive per runtime owner"
|
|
20
|
+
},
|
|
21
|
+
"handoff": {
|
|
22
|
+
"carrier": "response.json fields: kind → path relative to the branch; the next branch's request.json inputs point at step-N/parallel-M/<path> from the session root, written explicitly by the orchestrator (nearest earlier producer guides the orchestrator, never the agent)",
|
|
23
|
+
"stop": "response.json status blocked with stop = code; errors/ says whether the code terminates or falls back, and routing.json says where a terminated step hands to",
|
|
24
|
+
"waiting": "response.json status waiting with awaiting { exchange, kind }: the orchestrator validates the fields written so far, creates <exchange>/request/request.json in the same branch, runs a fresh agent for it, and resumes the paused agent when <exchange>/response/response.json is done; other branches of the step keep running",
|
|
25
|
+
"resume": "a blocked branch re-enters the same operator as a new agent in step-(N+1)/parallel-1, with request.json.resume naming the blocked step and parallel; the blocked branch stays on disk as evidence"
|
|
26
|
+
},
|
|
27
|
+
"session": {
|
|
28
|
+
"root": "<Source>/.worktrees/sessions/<sessionId>/",
|
|
29
|
+
"id": "<yyyymmdd-HHMMss>-<project>-<first operator>, e.g. 20260903-142200-starci-academy-frontend.direction.decide",
|
|
30
|
+
"manifest": "state.json: id, project, startedAt, status (running | blocked | done), chain [[\"1/1\"], [\"2/1\", \"2/2\"], ...], steps { \"N/M\": operatorId }, current, leases { \"N/M\": { agent, holds } }, requestHashes { \"N/M\": sha256 of request/request.json }",
|
|
31
|
+
"branch": "step-<N>/parallel-<M>/ — N is the position in the chain, M the parallel branch; parallel-1 always exists",
|
|
32
|
+
"branchLayout": [
|
|
33
|
+
"request/request.json",
|
|
34
|
+
"response/response.json",
|
|
35
|
+
"response/response.md",
|
|
36
|
+
"response/<other>.md when the operator has one",
|
|
37
|
+
"response/data/",
|
|
38
|
+
"response/artifacts/",
|
|
39
|
+
"<exchange>/request/request.json and <exchange>/response/ for a nested exchange"
|
|
40
|
+
],
|
|
41
|
+
"paths": "inside request.json inputs: from the session root (step-1/parallel-1/response/response.md); inside response.json fields and operator.md Outputs: from the branch (response/response.md, critique/response/critique.md)",
|
|
42
|
+
"lifecycle": [
|
|
43
|
+
"create: the orchestrator writes state.json and takes the leases before the first agent starts",
|
|
44
|
+
"branch: each agent gets a fresh step-N/parallel-M/ with request/request.json already written and hashed into state.json, and writes only response/",
|
|
45
|
+
"advance: response.json status done and both validators green; the orchestrator writes the next branches' request.json from the Next table and routing.json",
|
|
46
|
+
"wait: status waiting runs the nested exchange, then resumes the same agent; the branch stays running in state.json",
|
|
47
|
+
"block: status blocked keeps the session on disk; the orchestrator asks the person for the field the stop names, then re-enters the operator in step-(N+1)/parallel-1 with resume set",
|
|
48
|
+
"done: when routing reaches user or external, or git.publish emits done, the orchestrator releases the leases and deletes the session folder; what survives is what the steps published (commits, business heads, UAT pairs, remote runs) and any audit record the owner copies out first"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"sourceWrites": {
|
|
52
|
+
"rule": "an operator that writes source (frontend.source.apply, backend.source.apply) writes only on the session branch session/<sessionId> of the routed checkout, in a git worktree the orchestrator prepared from the frozen head; it commits the declared write set once and records the sha in response.json.commits; the person's checked-out branch is never touched",
|
|
53
|
+
"track": "changes.md names every path with before/after hashes and the commit; the next requests pin @workspaces/<role> at that sha (contexts[].head) so quality.verify and frontend.surface.audit verify exactly what was written",
|
|
54
|
+
"publish": "git.publish merges the session branch into the target branch: fast-forward when the target has not moved; a merge commit only when there is no conflict and the gates are re-run on the merge result; a conflict is NON_FAST_FORWARD and a person resolves it; never rebase, never force",
|
|
55
|
+
"cleanup": "after a successful publish the worktree and the session branch are removed together with the session folder; a blocked session keeps both",
|
|
56
|
+
"policy": "the routed checkout must declare gitPolicy.worktreeBranches = session-only (readiness/initialization/workspaces); a route declaring forbidden binds read-only and no source-writing operator may run against it"
|
|
57
|
+
},
|
|
58
|
+
"profileEquivalents": {
|
|
59
|
+
"rule": "an operator binds one profile; when the processor runs on a runtime that lacks that profile, it runs the equivalent profile of its own runtime with exactly the grants the operator requires, and response.json records both (boundProfile, ranProfile) so an audit can tell a stand-in from the binding",
|
|
60
|
+
"pairs": {
|
|
61
|
+
"opus": "sol-fresh",
|
|
62
|
+
"sonnet": "luna",
|
|
63
|
+
"fable": "sol-reviewer",
|
|
64
|
+
"sol-fresh": "opus",
|
|
65
|
+
"luna": "sonnet",
|
|
66
|
+
"sol-reviewer": "fable"
|
|
67
|
+
},
|
|
68
|
+
"grants": "the equivalent runs with the tools the operator declares that its own profile permits and its runtime supports (resources/tools.json); a tool the runtime does not support is unavailable for that run: a judged imagegen step records that no artwork could be made and continues, any other unsupported tool blocks the branch with the operator's own code",
|
|
69
|
+
"imageVersusVisualize": "imageGeneration means artwork: a digital image produced by an image model (OpenAI profiles only). Rendering HTML (direction candidates, audit sheets, previews) is visualization, needs no grant, and every runtime does it."
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"note": "The closed registry of tools an operator may call, addressed as @tools/<id> in a Steps table. A tool is what an operator is allowed to do beyond reading aliases; an alias is what it may read. Each tool lists the modes an operator may declare in operator.json → resources.tools, and how each runtime provides it, so the same operator.md runs on Codex and on Claude without a second home for the rule. A runtime that does not support a tool cannot run an operator that declares it in a mode other than never; the processor then runs the profile equivalent on a runtime that does, or reports the gap. A tool absent from this file does not exist for an operator.",
|
|
4
|
+
"runtimes": {
|
|
5
|
+
"openai": "Codex (desktop app or CLI) running an OpenAI profile from resources/agents/profiles/openai.json",
|
|
6
|
+
"claude": "Claude Code (desktop app or CLI) running a Claude profile from resources/agents/profiles/claude.json"
|
|
7
|
+
},
|
|
8
|
+
"tools": {
|
|
9
|
+
"fileread": {
|
|
10
|
+
"purpose": "Read files and directories at the aliases the Context table names, at the frozen head.",
|
|
11
|
+
"modes": { "never": "the operator reads nothing on disk", "context-aliases": "only locations the Context table resolves to" },
|
|
12
|
+
"support": { "openai": { "supported": true, "via": "Codex file reads" }, "claude": { "supported": true, "via": "Claude Code Read, Glob and Grep" } }
|
|
13
|
+
},
|
|
14
|
+
"sourcewrite": {
|
|
15
|
+
"purpose": "Write files inside a routed checkout or an authority root.",
|
|
16
|
+
"modes": { "never": "the operator writes no file outside its own response/", "declared-write-set": "only the paths the request declared, only on the session branch or the authority root the alias names, only values the bound receipts already contain" },
|
|
17
|
+
"support": { "openai": { "supported": true, "via": "Codex file edits" }, "claude": { "supported": true, "via": "Claude Code Write and Edit" } }
|
|
18
|
+
},
|
|
19
|
+
"git": {
|
|
20
|
+
"purpose": "Read and change repository state: heads, branches, worktrees, commits, merges, pushes.",
|
|
21
|
+
"modes": { "never": "no git at all", "read": "rev-parse, status, log, diff, show; nothing that writes", "commit-session-branch": "create or reuse the session/<sessionId> worktree from the frozen head and commit the declared write set there exactly once; never the person's branch", "merge-and-push": "merge the session branch into the target (fast-forward, or a merge commit with the gates re-run), push without force, remove the session worktree and branch; never rebase, never force, never --no-verify" },
|
|
22
|
+
"support": { "openai": { "supported": true, "via": "git through the Codex shell" }, "claude": { "supported": true, "via": "git through the Claude Code Bash tool" } }
|
|
23
|
+
},
|
|
24
|
+
"shell": {
|
|
25
|
+
"purpose": "Run declared commands: gates, builds, proofs, hooks, deployment plans.",
|
|
26
|
+
"modes": { "never": "the operator runs no command", "declared-commands": "only the commands the route, the contract, or the manifest pins, with their output captured as evidence" },
|
|
27
|
+
"support": { "openai": { "supported": true, "via": "the Codex shell" }, "claude": { "supported": true, "via": "the Claude Code Bash tool" } }
|
|
28
|
+
},
|
|
29
|
+
"websearch": {
|
|
30
|
+
"purpose": "Read public web pages to close one named gap in the evidence; results are references with URLs, never authority.",
|
|
31
|
+
"modes": { "never": "the operator does not search", "bounded": "the operator searches only for the gap the step names and records every source it used with its URL" },
|
|
32
|
+
"support": { "openai": { "supported": true, "via": "Codex web search" }, "claude": { "supported": true, "via": "Claude Code WebSearch and WebFetch" } }
|
|
33
|
+
},
|
|
34
|
+
"imagegen": {
|
|
35
|
+
"purpose": "Produce artwork: a digital image from an image model, made to one stated claim. Rendering HTML is the visualize tool, not this one.",
|
|
36
|
+
"modes": { "never": "the operator produces no artwork", "judged": "the operator decides on its own, from the direction, whether a region reads empty enough to need artwork, records why, and never decorates", "required": "artwork is a step of the job" },
|
|
37
|
+
"support": { "openai": { "supported": true, "via": "the OpenAI image model available to the Codex session" }, "claude": { "supported": false, "via": "none; a judged step records that no artwork could be made and the branch continues; a required step blocks with the operator's own code" } }
|
|
38
|
+
},
|
|
39
|
+
"visualize": {
|
|
40
|
+
"purpose": "Render HTML for a person to look at: direction candidates, audit sheets, alternative comparisons, previews. No model grant is involved.",
|
|
41
|
+
"modes": { "never": "the operator renders nothing", "html": "the operator writes HTML under response/artifacts/ and links it from response.md" },
|
|
42
|
+
"support": { "openai": { "supported": true, "via": "files written by the Codex session" }, "claude": { "supported": true, "via": "files written by the Claude Code session" } }
|
|
43
|
+
},
|
|
44
|
+
"browsercontrol": {
|
|
45
|
+
"purpose": "Drive a real browser against a served route: navigate, act, capture screenshots and DOM measurements.",
|
|
46
|
+
"modes": { "never": "the operator opens no browser", "required": "the operator's evidence comes from a driven browser" },
|
|
47
|
+
"support": { "openai": { "supported": true, "via": "Codex computer use, which opens the person's own Chrome; every UAT or audit run must use a dedicated browser profile (the shared UAT identity), never the person's logged-in profile" }, "claude": { "supported": true, "via": "the in-app Browser pane, or Claude in Chrome when the task needs the person's sessions" } }
|
|
48
|
+
},
|
|
49
|
+
"http": {
|
|
50
|
+
"purpose": "Probe an endpoint: readiness, health, a served route, a GraphQL typename, a status page.",
|
|
51
|
+
"modes": { "never": "no probes", "probe": "GET or HEAD against the endpoints the runtime registry or the manifest names, with the observed status recorded" },
|
|
52
|
+
"support": { "openai": { "supported": true, "via": "curl through the Codex shell" }, "claude": { "supported": true, "via": "curl through Bash, or WebFetch for a public URL" } }
|
|
53
|
+
},
|
|
54
|
+
"registry": {
|
|
55
|
+
"purpose": "Read a package registry: the published Grammar, its version, its files.",
|
|
56
|
+
"modes": { "never": "no registry reads", "read": "npm view and the installed package in node_modules; publishing stays with a person" },
|
|
57
|
+
"support": { "openai": { "supported": true, "via": "npm through the Codex shell" }, "claude": { "supported": true, "via": "npm through Bash" } }
|
|
58
|
+
},
|
|
59
|
+
"container": {
|
|
60
|
+
"purpose": "Inspect or operate containers and images: compose services, GHCR images by digest.",
|
|
61
|
+
"modes": { "never": "no container operations", "read": "inspect, logs, digests", "operate": "start, stop, roll out, roll back the services the approved plan names" },
|
|
62
|
+
"support": { "openai": { "supported": true, "via": "docker and the GHCR API through the Codex shell" }, "claude": { "supported": true, "via": "docker and the GHCR API through Bash" } }
|
|
63
|
+
},
|
|
64
|
+
"ci": {
|
|
65
|
+
"purpose": "Observe or dispatch continuous-integration runs.",
|
|
66
|
+
"modes": { "never": "no CI access", "read": "list and read runs and their logs", "dispatch": "trigger the workflow the release manifest names" },
|
|
67
|
+
"support": { "openai": { "supported": true, "via": "gh through the Codex shell" }, "claude": { "supported": true, "via": "gh through Bash" } }
|
|
68
|
+
},
|
|
69
|
+
"objectstorage": {
|
|
70
|
+
"purpose": "Read or write objects in the content store (MinIO): curriculum, style references, published units.",
|
|
71
|
+
"modes": { "never": "no object store access", "read": "read the objects the unit names", "write": "publish the objects the unit produced, under a person's approval" },
|
|
72
|
+
"support": { "openai": { "supported": true, "via": "the MinIO client or its HTTP API through the Codex shell" }, "claude": { "supported": true, "via": "the MinIO client or its HTTP API through Bash" } }
|
|
73
|
+
},
|
|
74
|
+
"secrets": {
|
|
75
|
+
"purpose": "Resolve a sealed credential by name at the moment it is used; never read, print or store its value.",
|
|
76
|
+
"modes": { "never": "no credential is resolved", "resolve-by-name": "the name comes from device-state or a route; decryption happens in the tool that consumes it; a value never enters response/" },
|
|
77
|
+
"support": { "openai": { "supported": true, "via": "SOPS and age through the Codex shell" }, "claude": { "supported": true, "via": "SOPS and age through Bash" } }
|
|
78
|
+
},
|
|
79
|
+
"database": {
|
|
80
|
+
"purpose": "Read or write the product database for verification: seeds, fixtures, is_uat records.",
|
|
81
|
+
"modes": { "never": "no database access", "read": "select only", "namespaced-write": "insert and delete only rows carrying the run namespace and is_uat=true" },
|
|
82
|
+
"support": { "openai": { "supported": true, "via": "psql or the service's API through the Codex shell" }, "claude": { "supported": true, "via": "psql or the service's API through Bash" } }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
package/routing.json
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 9,
|
|
3
|
+
"note": "Closed routing map. A skill reads a validated operator output and routes on outcome, then on failure.owningDomain. It never reads prose to decide the next step.",
|
|
4
|
+
"kinds": {
|
|
5
|
+
"operator": "Invoke the named operator next.",
|
|
6
|
+
"resume": "Invoke the same operator again with the required delta from its resume token.",
|
|
7
|
+
"user": "Stop. A person owns this and must decide or publish before the mission continues.",
|
|
8
|
+
"external": "Stop. The blocker is outside the runtime and no operator can clear it."
|
|
9
|
+
},
|
|
10
|
+
"routes": {
|
|
11
|
+
"architecture.decide": {
|
|
12
|
+
"architecture": {
|
|
13
|
+
"kind": "resume"
|
|
14
|
+
},
|
|
15
|
+
"business": {
|
|
16
|
+
"kind": "operator",
|
|
17
|
+
"target": "business.decide"
|
|
18
|
+
},
|
|
19
|
+
"workspace": {
|
|
20
|
+
"kind": "operator",
|
|
21
|
+
"target": "workspace.bind"
|
|
22
|
+
},
|
|
23
|
+
"caller": {
|
|
24
|
+
"kind": "user"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"backend.source.apply": {
|
|
28
|
+
"backend": {
|
|
29
|
+
"kind": "resume"
|
|
30
|
+
},
|
|
31
|
+
"business": {
|
|
32
|
+
"kind": "operator",
|
|
33
|
+
"target": "business.decide"
|
|
34
|
+
},
|
|
35
|
+
"contract": {
|
|
36
|
+
"kind": "user"
|
|
37
|
+
},
|
|
38
|
+
"platform": {
|
|
39
|
+
"kind": "operator",
|
|
40
|
+
"target": "platform.operate"
|
|
41
|
+
},
|
|
42
|
+
"workspace": {
|
|
43
|
+
"kind": "operator",
|
|
44
|
+
"target": "workspace.bind"
|
|
45
|
+
},
|
|
46
|
+
"caller": {
|
|
47
|
+
"kind": "user"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"business.decide": {
|
|
51
|
+
"business": {
|
|
52
|
+
"kind": "resume"
|
|
53
|
+
},
|
|
54
|
+
"backend": {
|
|
55
|
+
"kind": "operator",
|
|
56
|
+
"target": "backend.source.apply"
|
|
57
|
+
},
|
|
58
|
+
"workspace": {
|
|
59
|
+
"kind": "operator",
|
|
60
|
+
"target": "workspace.bind"
|
|
61
|
+
},
|
|
62
|
+
"caller": {
|
|
63
|
+
"kind": "user"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"content.generate": {
|
|
67
|
+
"content": {
|
|
68
|
+
"kind": "resume"
|
|
69
|
+
},
|
|
70
|
+
"curriculum": {
|
|
71
|
+
"kind": "user"
|
|
72
|
+
},
|
|
73
|
+
"engineering": {
|
|
74
|
+
"kind": "user"
|
|
75
|
+
},
|
|
76
|
+
"workspace": {
|
|
77
|
+
"kind": "operator",
|
|
78
|
+
"target": "workspace.bind"
|
|
79
|
+
},
|
|
80
|
+
"caller": {
|
|
81
|
+
"kind": "user"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"frontend.direction.decide": {
|
|
85
|
+
"business": {
|
|
86
|
+
"kind": "operator",
|
|
87
|
+
"target": "business.decide"
|
|
88
|
+
},
|
|
89
|
+
"backend": {
|
|
90
|
+
"kind": "operator",
|
|
91
|
+
"target": "backend.source.apply"
|
|
92
|
+
},
|
|
93
|
+
"architecture": {
|
|
94
|
+
"kind": "operator",
|
|
95
|
+
"target": "architecture.decide"
|
|
96
|
+
},
|
|
97
|
+
"grammar": {
|
|
98
|
+
"kind": "user"
|
|
99
|
+
},
|
|
100
|
+
"workspace": {
|
|
101
|
+
"kind": "operator",
|
|
102
|
+
"target": "workspace.bind"
|
|
103
|
+
},
|
|
104
|
+
"caller": {
|
|
105
|
+
"kind": "user"
|
|
106
|
+
},
|
|
107
|
+
"frontend": {
|
|
108
|
+
"kind": "resume"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"frontend.presentation.resolve": {
|
|
112
|
+
"grammar": {
|
|
113
|
+
"kind": "user"
|
|
114
|
+
},
|
|
115
|
+
"knowledge": {
|
|
116
|
+
"kind": "user"
|
|
117
|
+
},
|
|
118
|
+
"workspace": {
|
|
119
|
+
"kind": "operator",
|
|
120
|
+
"target": "workspace.bind"
|
|
121
|
+
},
|
|
122
|
+
"caller": {
|
|
123
|
+
"kind": "user"
|
|
124
|
+
},
|
|
125
|
+
"frontend": {
|
|
126
|
+
"kind": "resume"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"frontend.source.apply": {
|
|
130
|
+
"resolution": {
|
|
131
|
+
"kind": "operator",
|
|
132
|
+
"target": "frontend.presentation.resolve"
|
|
133
|
+
},
|
|
134
|
+
"workspace": {
|
|
135
|
+
"kind": "operator",
|
|
136
|
+
"target": "workspace.bind"
|
|
137
|
+
},
|
|
138
|
+
"caller": {
|
|
139
|
+
"kind": "user"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"frontend.surface.audit": {
|
|
143
|
+
"workspace": {
|
|
144
|
+
"kind": "operator",
|
|
145
|
+
"target": "workspace.bind"
|
|
146
|
+
},
|
|
147
|
+
"caller": {
|
|
148
|
+
"kind": "user"
|
|
149
|
+
},
|
|
150
|
+
"platform": {
|
|
151
|
+
"kind": "operator",
|
|
152
|
+
"target": "platform.operate"
|
|
153
|
+
},
|
|
154
|
+
"frontend": {
|
|
155
|
+
"kind": "resume"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"git.publish": {
|
|
159
|
+
"workspace": {
|
|
160
|
+
"kind": "operator",
|
|
161
|
+
"target": "workspace.bind"
|
|
162
|
+
},
|
|
163
|
+
"source": {
|
|
164
|
+
"kind": "operator",
|
|
165
|
+
"target": "workspace.bind"
|
|
166
|
+
},
|
|
167
|
+
"remote": {
|
|
168
|
+
"kind": "external"
|
|
169
|
+
},
|
|
170
|
+
"caller": {
|
|
171
|
+
"kind": "user"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"platform.operate": {
|
|
175
|
+
"platform": {
|
|
176
|
+
"kind": "resume"
|
|
177
|
+
},
|
|
178
|
+
"provider": {
|
|
179
|
+
"kind": "external"
|
|
180
|
+
},
|
|
181
|
+
"product": {
|
|
182
|
+
"kind": "user"
|
|
183
|
+
},
|
|
184
|
+
"workspace": {
|
|
185
|
+
"kind": "operator",
|
|
186
|
+
"target": "workspace.bind"
|
|
187
|
+
},
|
|
188
|
+
"caller": {
|
|
189
|
+
"kind": "user"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"quality.verify": {
|
|
193
|
+
"platform": {
|
|
194
|
+
"kind": "operator",
|
|
195
|
+
"target": "platform.operate"
|
|
196
|
+
},
|
|
197
|
+
"workspace": {
|
|
198
|
+
"kind": "operator",
|
|
199
|
+
"target": "workspace.bind"
|
|
200
|
+
},
|
|
201
|
+
"caller": {
|
|
202
|
+
"kind": "user"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"release.deploy": {
|
|
206
|
+
"deployment": {
|
|
207
|
+
"kind": "resume"
|
|
208
|
+
},
|
|
209
|
+
"platform": {
|
|
210
|
+
"kind": "operator",
|
|
211
|
+
"target": "platform.operate"
|
|
212
|
+
},
|
|
213
|
+
"provider": {
|
|
214
|
+
"kind": "external"
|
|
215
|
+
},
|
|
216
|
+
"backend": {
|
|
217
|
+
"kind": "operator",
|
|
218
|
+
"target": "backend.source.apply"
|
|
219
|
+
},
|
|
220
|
+
"approval": {
|
|
221
|
+
"kind": "user"
|
|
222
|
+
},
|
|
223
|
+
"caller": {
|
|
224
|
+
"kind": "user"
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
"uat.verify": {
|
|
228
|
+
"control-panel": {
|
|
229
|
+
"kind": "external"
|
|
230
|
+
},
|
|
231
|
+
"runtime": {
|
|
232
|
+
"kind": "external"
|
|
233
|
+
},
|
|
234
|
+
"backend": {
|
|
235
|
+
"kind": "operator",
|
|
236
|
+
"target": "backend.source.apply"
|
|
237
|
+
},
|
|
238
|
+
"quality": {
|
|
239
|
+
"kind": "operator",
|
|
240
|
+
"target": "quality.verify"
|
|
241
|
+
},
|
|
242
|
+
"caller": {
|
|
243
|
+
"kind": "user"
|
|
244
|
+
},
|
|
245
|
+
"platform": {
|
|
246
|
+
"kind": "operator",
|
|
247
|
+
"target": "platform.operate"
|
|
248
|
+
},
|
|
249
|
+
"workspace": {
|
|
250
|
+
"kind": "operator",
|
|
251
|
+
"target": "workspace.bind"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"workspace.bind": {
|
|
255
|
+
"workspace": {
|
|
256
|
+
"kind": "resume"
|
|
257
|
+
},
|
|
258
|
+
"source": {
|
|
259
|
+
"kind": "resume"
|
|
260
|
+
},
|
|
261
|
+
"runtime": {
|
|
262
|
+
"kind": "external"
|
|
263
|
+
},
|
|
264
|
+
"identity": {
|
|
265
|
+
"kind": "external"
|
|
266
|
+
},
|
|
267
|
+
"caller": {
|
|
268
|
+
"kind": "user"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// alias/alias.json is a tree: one root per zone (@workspaces, @grammar, @knowledge, @worktrees,
|
|
2
|
+
// @remote, @dynamic), children by path segment, and a node is a definition when it carries
|
|
3
|
+
// `resolvesTo`. This module is the one place the tree is flattened to `@root/segment/...` keys, so
|
|
4
|
+
// the validator and the generator cannot disagree about what an alias is called.
|
|
5
|
+
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
|
|
8
|
+
export const DEF_KEYS = new Set(['params', 'kind', 'resolvesTo', 'scheme', 'bind', 'writers', 'purpose', 'note']);
|
|
9
|
+
|
|
10
|
+
export async function loadAliasRegistry(root) {
|
|
11
|
+
const raw = JSON.parse(await readFile(path.join(root, 'alias', 'alias.json'), 'utf8'));
|
|
12
|
+
const aliases = {};
|
|
13
|
+
const walk = (node, prefix, zone) => {
|
|
14
|
+
if (node.resolvesTo !== undefined) aliases[prefix] = { ...Object.fromEntries(Object.entries(node).filter(([k]) => DEF_KEYS.has(k))), zone };
|
|
15
|
+
for (const [key, child] of Object.entries(node)) {
|
|
16
|
+
if (DEF_KEYS.has(key) || typeof child !== 'object' || child === null || Array.isArray(child)) continue;
|
|
17
|
+
walk(child, `${prefix}/${key}`, zone);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
for (const [rootKey, node] of Object.entries(raw.tree ?? {})) walk(node, rootKey, rootKey.slice(1));
|
|
21
|
+
// @tools/<id> is what an operator may call, not read; it comes from resources/tools.json so a Steps cell can
|
|
22
|
+
// name a tool next to the aliases it reads and the same resolver answers both.
|
|
23
|
+
const toolsDoc = JSON.parse(await readFile(path.join(root, 'resources', 'tools.json'), 'utf8'));
|
|
24
|
+
const tools = {};
|
|
25
|
+
for (const [id, tool] of Object.entries(toolsDoc.tools ?? {})) {
|
|
26
|
+
tools[`@tools/${id}`] = { params: [], kind: 'tool', resolvesTo: `resources/tools.json#tools.${id}`, scheme: `tool://${id}`, bind: `mode declared in operator.json → resources.tools; modes: ${Object.keys(tool.modes).join(' | ')}`, writers: [], purpose: tool.purpose, zone: 'tools', support: tool.support };
|
|
27
|
+
}
|
|
28
|
+
return { schemaVersion: raw.schemaVersion, note: raw.note, zones: raw.zones ?? {}, segments: raw.segments ?? {}, aliases: { ...aliases, ...tools }, tree: raw.tree ?? {}, tools };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const baseOf = (aliases, alias) => Object.keys(aliases).filter((k) => alias === k || alias.startsWith(`${k}/`)).sort((a, b) => b.length - a.length)[0] ?? null;
|