@oisincoveney/pipeline 2.1.1 → 2.3.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.
Files changed (64) hide show
  1. package/.agents/skills/orchestrate/SKILL.md +80 -0
  2. package/defaults/pipeline.yaml +111 -0
  3. package/defaults/profiles.yaml +215 -0
  4. package/defaults/runners.yaml +24 -0
  5. package/dist/argo-graph.js +59 -27
  6. package/dist/argo-submit.d.ts +0 -1
  7. package/dist/argo-submit.js +11 -6
  8. package/dist/argo-workflow.d.ts +1 -2
  9. package/dist/argo-workflow.js +0 -2
  10. package/dist/claude-settings-config.js +44 -0
  11. package/dist/cli/program.js +12 -5
  12. package/dist/cli/submit-options.js +1 -2
  13. package/dist/cluster-doctor.js +0 -12
  14. package/dist/commands/pipeline-command.js +1 -1
  15. package/dist/config/defaults.js +7 -350
  16. package/dist/config/schemas.d.ts +9 -9
  17. package/dist/install-commands/claude-code.js +160 -0
  18. package/dist/install-commands/opencode.js +56 -39
  19. package/dist/install-commands/shared.js +32 -5
  20. package/dist/install-commands.js +26 -15
  21. package/dist/json-config-merge.js +47 -0
  22. package/dist/mcp/gateway.js +9 -1
  23. package/dist/moka-global-config.d.ts +0 -1
  24. package/dist/moka-global-config.js +0 -1
  25. package/dist/moka-submit.d.ts +8 -11
  26. package/dist/moka-submit.js +1 -4
  27. package/dist/opencode-project-config.js +2 -45
  28. package/dist/pipeline-runtime.d.ts +9 -0
  29. package/dist/pipeline-runtime.js +50 -8
  30. package/dist/planned-node.js +2 -5
  31. package/dist/{workflow-planner.d.ts → planning/compile.d.ts} +2 -2
  32. package/dist/{workflow-planner.js → planning/compile.js} +6 -83
  33. package/dist/{schedule/planner.d.ts → planning/generate.d.ts} +17 -3
  34. package/dist/{schedule/planner.js → planning/generate.js} +24 -56
  35. package/dist/planning/graph.js +138 -0
  36. package/dist/runner-command/lifecycle-context.js +2 -3
  37. package/dist/runner-command/run.js +2 -3
  38. package/dist/runner-command-contract.d.ts +2 -2
  39. package/dist/runner-event-schema.d.ts +349 -0
  40. package/dist/runner-event-schema.js +185 -0
  41. package/dist/runner-output.js +2 -2
  42. package/dist/runner.d.ts +29 -0
  43. package/dist/runtime/agent-node/agent-node.js +1 -0
  44. package/dist/runtime/context/context.js +1 -1
  45. package/dist/runtime/contracts/contracts.d.ts +18 -1
  46. package/dist/runtime/node-state-store.js +7 -0
  47. package/dist/runtime/opencode-adapter.js +28 -8
  48. package/dist/runtime/opencode-agent-name.js +18 -0
  49. package/dist/runtime/opencode-runtime.js +62 -0
  50. package/dist/runtime/opencode-server.js +67 -0
  51. package/dist/runtime/opencode-session-executor.js +206 -0
  52. package/dist/schedule/passes/coverage.js +7 -51
  53. package/dist/schedule/passes/ids.js +3 -23
  54. package/dist/schedule/scheduling-roles.js +19 -0
  55. package/dist/strings.js +30 -1
  56. package/docs/adr-opencode-first-goal-loop-runtime.md +1 -1
  57. package/docs/config-architecture.md +43 -6
  58. package/docs/mcp-gateway.md +4 -4
  59. package/docs/operator-guide.md +9 -8
  60. package/docs/pipeline-console-runner-contract.md +3 -4
  61. package/docs/slash-command-adapter-contract.md +1 -0
  62. package/package.json +10 -5
  63. package/dist/schedule-planner.d.ts +0 -2
  64. package/dist/schedule-planner.js +0 -2
@@ -0,0 +1,44 @@
1
+ import { applyJsonEdit, ensureTrailingNewline, formatJson, isRecord, parseJsonRecord, setIfMissing } from "./json-config-merge.js";
2
+ //#region src/claude-settings-config.ts
3
+ function mergeClaudeSettings(currentText, projection) {
4
+ if (currentText === void 0) return {
5
+ content: formatJson(projection),
6
+ ok: true
7
+ };
8
+ const parsed = parseJsonRecord(currentText);
9
+ if (!parsed.ok) return parsed;
10
+ return {
11
+ content: ensureTrailingNewline(applyClaudeProjection(currentText, parsed.value, projection)),
12
+ ok: true
13
+ };
14
+ }
15
+ function applyClaudeProjection(currentText, parsed, projection) {
16
+ return applyPermissionsAllow(applyMcpServersProjection(currentText, parsed, projection), parsed, projection);
17
+ }
18
+ function applyMcpServersProjection(content, parsed, projection) {
19
+ return Object.entries(projection.mcpServers ?? {}).reduce((nextContent, [name, server]) => setIfMissing(nextContent, parsed, ["mcpServers", name], server), content);
20
+ }
21
+ function applyPermissionsAllow(content, parsed, projection) {
22
+ const existing = permissionAllowList(parsed);
23
+ const merged = unionPreservingOrder(existing, projectedAllowList(projection));
24
+ return sameOrderedList(existing, merged) ? content : applyJsonEdit(content, ["permissions", "allow"], merged);
25
+ }
26
+ function projectedAllowList(projection) {
27
+ return projection.permissions?.allow ?? [];
28
+ }
29
+ function unionPreservingOrder(existing, extra) {
30
+ const merged = [...existing];
31
+ for (const entry of extra) if (!merged.includes(entry)) merged.push(entry);
32
+ return merged;
33
+ }
34
+ function sameOrderedList(a, b) {
35
+ return a.length === b.length && a.every((value, index) => value === b[index]);
36
+ }
37
+ function permissionAllowList(parsed) {
38
+ const permissions = parsed.permissions;
39
+ if (!isRecord(permissions)) return [];
40
+ const allow = permissions.allow;
41
+ return Array.isArray(allow) ? allow.filter((entry) => typeof entry === "string") : [];
42
+ }
43
+ //#endregion
44
+ export { mergeClaudeSettings };
@@ -2,9 +2,8 @@ import { PipelineConfigError } from "../config/schemas.js";
2
2
  import { loadPipelineConfig } from "../config/load.js";
3
3
  import "../config.js";
4
4
  import { createOrchestratorLaunchPlan, createRunnerLaunchPlan } from "../runner.js";
5
- import { compileWorkflowPlan } from "../workflow-planner.js";
6
- import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "../schedule/planner.js";
7
- import "../schedule-planner.js";
5
+ import { compileWorkflowPlan } from "../planning/compile.js";
6
+ import { compileScheduleArtifact, generateScheduleArtifact, parseScheduleArtifact } from "../planning/generate.js";
8
7
  import { loadMokaGlobalConfig } from "../moka-global-config.js";
9
8
  import { defaultClusterDoctorNamespace, runClusterDoctor } from "../cluster-doctor.js";
10
9
  import { formatCodexAuthSyncResult, syncLocalCodexAuth } from "../codex-auth-sync.js";
@@ -150,7 +149,7 @@ function createCliProgram() {
150
149
  const config = loadPipelineConfig(process.env.PIPELINE_TARGET_PATH ?? process.cwd(), { allowMissingLintFileReferences: true });
151
150
  console.log(renderGatewayConfig(config));
152
151
  });
153
- gatewayCommand.command("configure-host").description("Rewrite host MCP config to the singleton pipeline gateway").addOption(new Option("--host <host>", "host config to update").choices(["all", "opencode"]).default("all").argParser(parseCommandHost)).addOption(new Option("--scope <scope>", "config scope to update").choices(["project", "global"]).default("project").argParser(parseGatewayHostScope)).action((flags) => {
152
+ gatewayCommand.command("configure-host").description("Rewrite host MCP config to the singleton pipeline gateway").addOption(new Option("--host <host>", "host config to update").choices(["all", "opencode"]).default("all").argParser(parseGatewayHost)).addOption(new Option("--scope <scope>", "config scope to update").choices(["project", "global"]).default("project").argParser(parseGatewayHostScope)).action((flags) => {
154
153
  const cwd = process.env.PIPELINE_TARGET_PATH ?? process.cwd();
155
154
  const result = configureGatewayHosts(loadPipelineConfig(cwd, { allowMissingLintFileReferences: true }), {
156
155
  cwd,
@@ -182,7 +181,11 @@ function createCliProgram() {
182
181
  const result = await initPipelineProject({ cwd: process.env.PIPELINE_TARGET_PATH ?? process.cwd() });
183
182
  console.log(formatPipelineInitResult(result));
184
183
  });
185
- program.command("install-commands").description("Install generated slash-command adapters into this repository").addOption(new Option("--host <host>", "host command set to install").choices(["all", "opencode"]).default("all").argParser(parseCommandHost)).option("--dry-run", "show planned changes without writing files").option("--check", "fail if generated command files are missing or stale").option("--force", "overwrite manually edited command files").action(async (flags) => {
184
+ program.command("install-commands").description("Install generated slash-command adapters into this repository").addOption(new Option("--host <host>", "host command set to install").choices([
185
+ "all",
186
+ "opencode",
187
+ "claude-code"
188
+ ]).default("all").argParser(parseCommandHost)).option("--dry-run", "show planned changes without writing files").option("--check", "fail if generated command files are missing or stale").option("--force", "overwrite manually edited command files").action(async (flags) => {
186
189
  const result = await installCommands({
187
190
  ...flags,
188
191
  cwd: process.env.PIPELINE_TARGET_PATH ?? process.cwd()
@@ -232,6 +235,10 @@ function parseGatewayHostScope(value) {
232
235
  if (value === "project" || value === "global") return value;
233
236
  throw new Error("scope must be project or global");
234
237
  }
238
+ function parseGatewayHost(value) {
239
+ if (value === "all" || value === "opencode") return value;
240
+ throw new Error("host must be all or opencode");
241
+ }
235
242
  async function runCli(argv) {
236
243
  await createCliProgram().parseAsync(argv, { from: "node" });
237
244
  }
@@ -48,7 +48,6 @@ function mokaCommonSubmitOptions(input) {
48
48
  name: input.flags.name,
49
49
  namespace: input.flags.namespace ?? momokaya?.kubernetes.namespace,
50
50
  opencodeAuthSecretName: momokaya?.submit.opencodeAuthSecretName,
51
- queueName: input.flags.queueName ?? momokaya?.submit.queueName,
52
51
  serviceAccountName: input.flags.serviceAccount ?? momokaya?.submit.serviceAccountName,
53
52
  worktreePath: input.cwd
54
53
  };
@@ -77,7 +76,7 @@ function submitMokaGraphInput(input, flags, commonOptions) {
77
76
  function addRunnerArgoOptions(command, options = {}) {
78
77
  command.option("--name <name>", "Workflow metadata.name").option("--generate-name <prefix>", "Workflow metadata.generateName").option("--namespace <namespace>", "Workflow namespace");
79
78
  if (options.kubeconfig) command.option("--kubeconfig <path>", "kubeconfig path");
80
- return command.option("--queue-name <name>", "Kueue LocalQueue label for Workflow pods").option("--service-account <name>", "Workflow service account").option("--image <image>", "runner image").addOption(new Option("--image-pull-policy <policy>", "runner image pull policy").choices([
79
+ return command.option("--service-account <name>", "Workflow service account").option("--image <image>", "runner image").addOption(new Option("--image-pull-policy <policy>", "runner image pull policy").choices([
81
80
  "Always",
82
81
  "IfNotPresent",
83
82
  "Never"
@@ -10,7 +10,6 @@ const DEFAULT_RESOURCES = {
10
10
  githubAuthSecretName: "oisin-bot-github-auth",
11
11
  imagePullSecretName: "ghcr-pull-secret",
12
12
  opencodeAuthSecretName: "opencode-auth-1",
13
- queueName: "pipeline-runner",
14
13
  serviceAccountName: "pipeline-runner"
15
14
  };
16
15
  const FORBIDDEN_RE = /forbidden/i;
@@ -32,7 +31,6 @@ async function runClusterDoctor(options = {}) {
32
31
  verb: "create",
33
32
  ...kubectlOptions
34
33
  }),
35
- checkLocalQueue(namespace, resources.queueName, kubectlOptions),
36
34
  checkClusterResource("argo-workflow-crd", [
37
35
  "get",
38
36
  "crd",
@@ -63,7 +61,6 @@ function clusterResources() {
63
61
  githubAuthSecretName: configured.githubAuthSecretName,
64
62
  imagePullSecretName: configured.imagePullSecretName,
65
63
  opencodeAuthSecretName: configured.opencodeAuthSecretName,
66
- queueName: configured.queueName,
67
64
  serviceAccountName: configured.serviceAccountName
68
65
  } : DEFAULT_RESOURCES;
69
66
  }
@@ -169,15 +166,6 @@ async function checkWorkflowSubmitPermission(namespace, options) {
169
166
  passed: false
170
167
  };
171
168
  }
172
- function checkLocalQueue(namespace, queueName, kubectlOptions) {
173
- return checkNamespacedResource(`localqueue/${queueName}`, [
174
- "get",
175
- "localqueue",
176
- queueName,
177
- "-n",
178
- namespace
179
- ], `Kueue LocalQueue ${queueName} missing in ${namespace}; runner Workflow pods cannot be admitted to the expected queue.`, kubectlOptions);
180
- }
181
169
  async function checkClusterResource(name, args, kubectlOptions) {
182
170
  const result = await kubectl(args, kubectlOptions);
183
171
  return result.ok ? {
@@ -17,7 +17,7 @@ function registerConfiguredEntrypointCommands(program, config, runEntrypoint) {
17
17
  for (const [id, entrypoint] of Object.entries(config.entrypoints)) {
18
18
  if (reservedCommands.has(id)) continue;
19
19
  const command = program.command(id).description(entrypoint.description ?? `Run the ${id} workflow`).argument("<description...>", "task description");
20
- if ("schedule" in entrypoint) command.option("--namespace <namespace>", "Workflow namespace").option("--schedule <path>", "approved schedule YAML to submit").option("--kubeconfig <path>", "kubeconfig path").option("--queue-name <name>", "Kueue LocalQueue label for Workflow pods").option("--service-account <name>", "Workflow service account").option("--image <image>", "runner image").option("--image-pull-policy <policy>", "runner image pull policy").option("--image-pull-secret <name>", "imagePullSecret name").option("--event-url <url>", "runner event sink URL");
20
+ if ("schedule" in entrypoint) command.option("--namespace <namespace>", "Workflow namespace").option("--schedule <path>", "approved schedule YAML to submit").option("--kubeconfig <path>", "kubeconfig path").option("--service-account <name>", "Workflow service account").option("--image <image>", "runner image").option("--image-pull-policy <policy>", "runner image pull policy").option("--image-pull-secret <name>", "imagePullSecret name").option("--event-url <url>", "runner event sink URL");
21
21
  command.action(async (descriptionParts, flags) => {
22
22
  await runEntrypoint(id, descriptionParts.join(" "), flags);
23
23
  });
@@ -7,356 +7,13 @@ const PIPELINE_CONFIG_PATH = ".pipeline/pipeline.yaml";
7
7
  const RUNNERS_CONFIG_PATH = ".pipeline/runners.yaml";
8
8
  const PROFILES_CONFIG_PATH = ".pipeline/profiles.yaml";
9
9
  const OPENCODE_ECOSYSTEM_MANIFEST_PATH = "defaults/opencode-ecosystem.yaml";
10
- const PACKAGE_DEFAULT_RUNNERS_YAML = `version: 1
11
- runners:
12
- opencode:
13
- type: opencode
14
- capabilities:
15
- native_subagents: true
16
- rules: true
17
- skills: true
18
- mcp_servers: true
19
- tools: [read, list, grep, glob, bash, edit, write]
20
- filesystem: [read-only, workspace-write]
21
- network: [inherit, disabled]
22
- output_formats: [text, json, jsonl, json_schema]
23
- command:
24
- type: command
25
- capabilities:
26
- native_subagents: false
27
- rules: false
28
- skills: false
29
- mcp_servers: false
30
- tools: [bash]
31
- filesystem: [read-only, workspace-write]
32
- network: [inherit, disabled]
33
- output_formats: [text, json]
34
- `;
35
- const PACKAGE_DEFAULT_PROFILES_YAML = `version: 1
36
- mcp_gateway:
37
- provider: toolhive
38
- mode: local
39
- url: https://pipeline-mcp.momokaya.ee/mcp/
40
- url_env: PIPELINE_MCP_GATEWAY_URL
41
- authorization_env: PIPELINE_MCP_GATEWAY_AUTHORIZATION
42
- default_profile: default
43
- backends:
44
- context7:
45
- locality: shared-remote
46
- tool_prefixes: [context7]
47
- uidotsh:
48
- locality: shared-remote
49
- tool_prefixes: [uidotsh]
50
- qdrant:
51
- locality: repo-scoped-remote
52
- tool_prefixes: [qdrant]
53
- fallow:
54
- locality: repo-local
55
- workspace_path_source: PIPELINE_TARGET_PATH
56
- required: false
57
- tool_prefixes: [fallow]
58
- serena:
59
- locality: repo-local
60
- workspace_path_source: PIPELINE_TARGET_PATH
61
- tool_prefixes: [serena]
62
- backlog:
63
- locality: repo-local
64
- workspace_path_source: PIPELINE_TARGET_PATH
65
- tool_prefixes: [backlog]
66
- skills:
67
- execute:
68
- path: .agents/skills/execute/SKILL.md
69
- source_root: package
70
- inspect:
71
- path: .agents/skills/inspect/SKILL.md
72
- source_root: package
73
- quick:
74
- path: .agents/skills/quick/SKILL.md
75
- source_root: package
76
- critique:
77
- path: .agents/skills/critique/SKILL.md
78
- source_root: package
79
- doubt:
80
- path: .agents/skills/doubt/SKILL.md
81
- source_root: package
82
- fix:
83
- path: .agents/skills/fix/SKILL.md
84
- source_root: package
85
- library-first-development:
86
- path: .agents/skills/library-first-development/SKILL.md
87
- source_root: package
88
- migrate:
89
- path: .agents/skills/migrate/SKILL.md
90
- source_root: package
91
- optimize:
92
- path: .agents/skills/optimize/SKILL.md
93
- source_root: package
94
- research:
95
- path: .agents/skills/research/SKILL.md
96
- source_root: package
97
- schedule-graph-shaping:
98
- path: .agents/skills/schedule-graph-shaping/SKILL.md
99
- source_root: package
100
- scope:
101
- path: .agents/skills/scope/SKILL.md
102
- source_root: package
103
- secure:
104
- path: .agents/skills/secure/SKILL.md
105
- source_root: package
106
- spec:
107
- path: .agents/skills/spec/SKILL.md
108
- source_root: package
109
- test:
110
- path: .agents/skills/test/SKILL.md
111
- source_root: package
112
- trace:
113
- path: .agents/skills/trace/SKILL.md
114
- source_root: package
115
- verify:
116
- path: .agents/skills/verify/SKILL.md
117
- source_root: package
118
- profiles:
119
- moka-orchestrator:
120
- runner: opencode
121
- description: Orchestrate the configured pipeline and enforce gates.
122
- instructions: { inline: "Orchestrate the configured pipeline through package-defined entrypoints, native agents, and gates. Do not bypass configured runner subprocesses or package-configured gates." }
123
- skills: [execute, quick, inspect]
124
- mcp_servers: [pipeline-gateway]
125
- tools: [read, list, grep, glob, bash]
126
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
127
- network: { mode: inherit }
128
- moka-researcher:
129
- runner: opencode
130
- description: Research the requested task and produce structured findings.
131
- instructions: { inline: "Inspect first-party source, tests, docs, and task context for the current task only. Produce concise findings with file references and stop; do not perform open-ended repository exploration." }
132
- timeout_ms: 900000
133
- skills: [research, spec, scope]
134
- mcp_servers: [pipeline-gateway]
135
- tools: [read, list, grep, glob, bash]
136
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
137
- network: { mode: inherit }
138
- output:
139
- format: json_schema
140
- schema_path: .pipeline/schemas/research.schema.json
141
- repair: { enabled: true, max_attempts: 1 }
142
- moka-inspector:
143
- runner: opencode
144
- model: openai/gpt-5.5-low
145
- description: Inspect the repository without modifying files.
146
- instructions: { inline: "Inspect the repository without modifying files." }
147
- skills: [research]
148
- mcp_servers: [pipeline-gateway]
149
- tools: [read, list, grep, glob, bash]
150
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
151
- network: { mode: inherit }
152
- moka-schedule-planner:
153
- runner: opencode
154
- model: openai/gpt-5.5-xhigh
155
- description: Refine a baseline schedule into a specialized approved-plan artifact.
156
- instructions: { inline: "Generate exactly one workflow named root as an explicit schedule graph. Return YAML only." }
157
- timeout_ms: 300000
158
- skills: [schedule-graph-shaping]
159
- mcp_servers: [pipeline-gateway]
160
- tools: [read, list, grep, glob, bash]
161
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
162
- network: { mode: inherit }
163
- moka-test-writer:
164
- runner: opencode
165
- scheduling_roles: [implementation]
166
- description: Add focused failing tests for the requested behavior.
167
- instructions: { inline: "Add focused failing tests for the requested behavior only. Do not change production code. Only edit files matching test paths such as **/*.test.*, **/*.spec.*, **/*_test.*, **/__tests__/**, test/**, or tests/**. Return only valid JSON with top-level changes and verification. Every changes entry must include summary, why, and files. Include risks, followups, and lessons when present. Do not use Markdown fences or prose outside the JSON object." }
168
- skills: [test]
169
- mcp_servers: [pipeline-gateway]
170
- tools: [read, list, grep, glob, bash, edit, write]
171
- filesystem: { mode: workspace-write, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
172
- network: { mode: inherit }
173
- output:
174
- format: json_schema
175
- schema_path: .pipeline/schemas/implementation.schema.json
176
- repair: { enabled: true, max_attempts: 1 }
177
- moka-code-writer:
178
- runner: opencode
179
- scheduling_roles: [implementation]
180
- description: Implement production code until the failing tests pass.
181
- instructions: { inline: "Implement the smallest production change that satisfies the failing tests. Return only valid JSON with top-level changes and verification. Every changes entry must include summary, why, and files. Include risks, followups, and lessons when present. Do not use Markdown fences or prose outside the JSON object." }
182
- skills: [trace, test, fix, library-first-development]
183
- mcp_servers: [pipeline-gateway]
184
- tools: [read, list, grep, glob, bash, edit, write]
185
- filesystem: { mode: workspace-write, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
186
- network: { mode: inherit }
187
- output:
188
- format: json_schema
189
- schema_path: .pipeline/schemas/implementation.schema.json
190
- repair: { enabled: true, max_attempts: 1 }
191
- moka-acceptance-reviewer:
192
- runner: opencode
193
- scheduling_roles: [coverage]
194
- description: Audit the finished change against every acceptance criterion.
195
- instructions: { inline: 'Audit the completed change against each canonical acceptance criterion independently. Return only valid JSON with top-level "verdict", "evidence", "acceptance", and optional "violations". Each "acceptance" entry must include "id", "verdict", and non-empty "evidence". Do not use Markdown fences or prose outside the JSON object.' }
196
- skills: [critique, doubt]
197
- mcp_servers: [pipeline-gateway]
198
- tools: [read, list, grep, glob, bash]
199
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
200
- network: { mode: inherit }
201
- output:
202
- format: json_schema
203
- schema_path: .pipeline/schemas/acceptance.schema.json
204
- repair: { enabled: true, max_attempts: 1 }
205
- moka-thermo-nuclear-reviewer:
206
- runner: opencode
207
- scheduling_roles: [coverage]
208
- description: Perform the final thermo-nuclear code quality review of the integration branch.
209
- instructions: { inline: "Perform the final code quality review of the integration branch." }
210
- skills: [critique]
211
- mcp_servers: [pipeline-gateway]
212
- tools: [read, list, grep, glob, bash]
213
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
214
- network: { mode: inherit }
215
- output:
216
- format: json_schema
217
- schema_path: .pipeline/schemas/review.schema.json
218
- repair: { enabled: true, max_attempts: 1 }
219
- moka-verifier:
220
- runner: opencode
221
- scheduling_roles: [coverage]
222
- description: Verify checks, implementation fit, and final evidence.
223
- instructions: { inline: 'Verify checks, implementation fit, and final evidence. Return only valid JSON with top-level "verdict", "evidence", and optional "violations". Do not use Markdown fences or prose outside the JSON object.' }
224
- skills: [verify, critique, secure, optimize]
225
- mcp_servers: [pipeline-gateway]
226
- tools: [read, list, grep, glob, bash]
227
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
228
- network: { mode: inherit }
229
- output:
230
- format: json_schema
231
- schema_path: .pipeline/schemas/verify.schema.json
232
- repair: { enabled: true, max_attempts: 1 }
233
- moka-learner:
234
- runner: opencode
235
- model: openai/gpt-5.5-low
236
- description: Store durable lessons from the completed run.
237
- instructions: { inline: "Store durable lessons from the completed run when useful." }
238
- skills: [migrate]
239
- mcp_servers: [pipeline-gateway]
240
- tools: [read, list, grep, glob, bash]
241
- filesystem: { mode: read-only, allow: ["**/*"], deny: ["node_modules/**", "dist/**", ".git/**"] }
242
- network: { mode: inherit }
243
- output:
244
- format: json_schema
245
- schema_path: .pipeline/schemas/learn.schema.json
246
- repair: { enabled: true, max_attempts: 1 }
247
- `;
248
- const PACKAGE_DEFAULT_PIPELINE_YAML = `version: 1
249
- default_workflow: inspect
250
- orchestrator:
251
- profile: moka-orchestrator
252
- entrypoints:
253
- quick:
254
- schedule: quick-schedule
255
- description: Compact planner-generated pipeline for small work
256
- execute:
257
- schedule: execute-schedule
258
- description: Full planner-generated pipeline for repository work
259
- inspect:
260
- workflow: inspect
261
- description: Read-only repository inspection
262
- hooks:
263
- functions:
264
- generated-defaults-audit:
265
- kind: command
266
- command: [node, -e, "const fs=require('node:fs'); fs.writeFileSync(process.env.PIPELINE_HOOK_RESULT, JSON.stringify({status:'pass',summary:'Generated defaults audit passed'}));"]
267
- trusted: true
268
- timeout_ms: 5000
269
- output_limit_bytes: 4096
270
- on:
271
- workflow.start:
272
- - id: generated-defaults-audit
273
- function: generated-defaults-audit
274
- failure: fail
275
- runner_command:
276
- environment:
277
- setup:
278
- - command: bun
279
- args: [install, --frozen-lockfile]
280
- scheduler:
281
- commands:
282
- quick:
283
- schedule: quick-schedule
284
- catalog: quick
285
- execute:
286
- schedule: execute-schedule
287
- catalog: execute
288
- node_catalogs:
289
- quick:
290
- required_categories: [intake, red, green, mechanical, verification]
291
- nodes:
292
- backlog-intake:
293
- category: intake
294
- profile: moka-researcher
295
- models: [openai/gpt-5.5-medium]
296
- red-tests:
297
- category: red
298
- profile: moka-test-writer
299
- models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
300
- green-implementation:
301
- category: green
302
- profile: moka-code-writer
303
- models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
304
- verification:
305
- category: verification
306
- profile: moka-verifier
307
- models: [openai/gpt-5.5-medium]
308
- execute:
309
- required_categories: [intake, research, red, green, mechanical, acceptance, verification, learn]
310
- nodes:
311
- backlog-intake:
312
- category: intake
313
- profile: moka-researcher
314
- models: [openai/gpt-5.5-medium]
315
- research:
316
- category: research
317
- profile: moka-researcher
318
- models: [openai/gpt-5.5-medium, kimi-for-coding/k2p6]
319
- red-tests:
320
- category: red
321
- profile: moka-test-writer
322
- models: [openai/gpt-5.5-high, kimi-for-coding/kimi-k2-thinking]
323
- green-backend:
324
- category: green
325
- profile: moka-code-writer
326
- models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
327
- green-frontend:
328
- category: green
329
- profile: moka-code-writer
330
- models: [openai/gpt-5.5-high, kimi-for-coding/k2p6, opencode-go/qwen3.7-max]
331
- acceptance-review:
332
- category: acceptance
333
- profile: moka-acceptance-reviewer
334
- models: [openai/gpt-5.5-medium]
335
- verification:
336
- category: verification
337
- profile: moka-verifier
338
- models: [openai/gpt-5.5-medium]
339
- learn:
340
- category: learn
341
- profile: moka-learner
342
- models: [openai/gpt-5.5-low]
343
- schedules:
344
- quick-schedule:
345
- baseline: quick
346
- planner_profile: moka-schedule-planner
347
- node_catalog: quick
348
- execute-schedule:
349
- baseline: execute
350
- planner_profile: moka-schedule-planner
351
- node_catalog: execute
352
- workflows:
353
- inspect:
354
- description: Read-only repository inspection workflow.
355
- nodes:
356
- - id: inspect
357
- kind: agent
358
- profile: moka-inspector
359
- `;
10
+ const DEFAULT_PACKAGE_DEFAULTS_ROOT = new URL("../../defaults/", import.meta.url);
11
+ function loadDefaultYaml(filename) {
12
+ return readFileSync(new URL(filename, DEFAULT_PACKAGE_DEFAULTS_ROOT), "utf8");
13
+ }
14
+ const PACKAGE_DEFAULT_RUNNERS_YAML = loadDefaultYaml("runners.yaml");
15
+ const PACKAGE_DEFAULT_PROFILES_YAML = loadDefaultYaml("profiles.yaml");
16
+ const PACKAGE_DEFAULT_PIPELINE_YAML = loadDefaultYaml("pipeline.yaml");
360
17
  const DEFAULT_OPENCODE_ECOSYSTEM_MANIFEST_URL = new URL(`../../${OPENCODE_ECOSYSTEM_MANIFEST_PATH}`, import.meta.url);
361
18
  const ecosystemStringArraySchema = z.array(z.string().min(1));
362
19
  const ecosystemRuntimeSchema = z.object({
@@ -220,8 +220,8 @@ declare const configSchema: z.ZodObject<{
220
220
  policy: z.ZodOptional<z.ZodObject<{
221
221
  commands: z.ZodOptional<z.ZodEnum<{
222
222
  allow: "allow";
223
- "trusted-only": "trusted-only";
224
223
  deny: "deny";
224
+ "trusted-only": "trusted-only";
225
225
  }>>;
226
226
  modules: z.ZodOptional<z.ZodEnum<{
227
227
  allow: "allow";
@@ -245,8 +245,8 @@ declare const configSchema: z.ZodObject<{
245
245
  }, z.core.$strict>>>;
246
246
  default_profile: z.ZodOptional<z.ZodString>;
247
247
  mode: z.ZodEnum<{
248
- hosted: "hosted";
249
248
  local: "local";
249
+ hosted: "hosted";
250
250
  }>;
251
251
  provider: z.ZodLiteral<"toolhive">;
252
252
  authorization_env: z.ZodDefault<z.ZodString>;
@@ -289,10 +289,10 @@ declare const configSchema: z.ZodObject<{
289
289
  }, z.core.$strict>>;
290
290
  output: z.ZodOptional<z.ZodObject<{
291
291
  format: z.ZodEnum<{
292
+ json_schema: "json_schema";
292
293
  text: "text";
293
294
  json: "json";
294
295
  jsonl: "jsonl";
295
- json_schema: "json_schema";
296
296
  }>;
297
297
  repair: z.ZodOptional<z.ZodObject<{
298
298
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -310,6 +310,7 @@ declare const configSchema: z.ZodObject<{
310
310
  skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
311
311
  timeout_ms: z.ZodOptional<z.ZodNumber>;
312
312
  tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
313
+ task: "task";
313
314
  read: "read";
314
315
  list: "list";
315
316
  grep: "grep";
@@ -317,7 +318,6 @@ declare const configSchema: z.ZodObject<{
317
318
  bash: "bash";
318
319
  edit: "edit";
319
320
  write: "write";
320
- task: "task";
321
321
  }>>>;
322
322
  }, z.core.$strict>>>;
323
323
  runner_command: z.ZodDefault<z.ZodObject<{
@@ -343,8 +343,8 @@ declare const configSchema: z.ZodObject<{
343
343
  rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
344
344
  path: z.ZodString;
345
345
  source_root: z.ZodDefault<z.ZodEnum<{
346
- package: "package";
347
346
  project: "project";
347
+ package: "package";
348
348
  }>>;
349
349
  }, z.core.$strict>>>;
350
350
  runners: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -361,14 +361,15 @@ declare const configSchema: z.ZodObject<{
361
361
  disabled: "disabled";
362
362
  }>>>;
363
363
  output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
364
+ json_schema: "json_schema";
364
365
  text: "text";
365
366
  json: "json";
366
367
  jsonl: "jsonl";
367
- json_schema: "json_schema";
368
368
  }>>>;
369
369
  rules: z.ZodOptional<z.ZodBoolean>;
370
370
  skills: z.ZodOptional<z.ZodBoolean>;
371
371
  tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
372
+ task: "task";
372
373
  read: "read";
373
374
  list: "list";
374
375
  grep: "grep";
@@ -376,7 +377,6 @@ declare const configSchema: z.ZodObject<{
376
377
  bash: "bash";
377
378
  edit: "edit";
378
379
  write: "write";
379
- task: "task";
380
380
  }>>>;
381
381
  }, z.core.$strict>;
382
382
  command: z.ZodOptional<z.ZodString>;
@@ -471,8 +471,8 @@ declare const configSchema: z.ZodObject<{
471
471
  schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
472
472
  description: z.ZodOptional<z.ZodString>;
473
473
  baseline: z.ZodEnum<{
474
- execute: "execute";
475
474
  quick: "quick";
475
+ execute: "execute";
476
476
  }>;
477
477
  max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
478
478
  node_catalog: z.ZodOptional<z.ZodString>;
@@ -484,8 +484,8 @@ declare const configSchema: z.ZodObject<{
484
484
  skills: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
485
485
  path: z.ZodString;
486
486
  source_root: z.ZodDefault<z.ZodEnum<{
487
- package: "package";
488
487
  project: "project";
488
+ package: "package";
489
489
  }>>;
490
490
  }, z.core.$strict>>>;
491
491
  task_context: z.ZodOptional<z.ZodObject<{