@volter/supercode-orchestrator 0.4.134 → 0.4.136

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/board/ci.mjs CHANGED
@@ -78,22 +78,43 @@ export function observeCompletionEvidence(board, id, entry, payload = {}) {
78
78
  }
79
79
  const configured = entry.params.completion_ci.workflows?.[repo] ?? entry.params.completion_ci.workflows?.['*'];
80
80
  if (!Array.isArray(configured) || !configured.length) throw new Error(`No deployment workflow is declared for ${repo} in completion_ci.workflows.`);
81
- const matchedRules = (entry.params.completion_ci.path_workflows?.[repo] ?? []).filter(rule =>
82
- records.some(([, , names]) => names.split('\n').some(path => rule.paths.some(prefix => path.startsWith(prefix)))));
83
- const deploymentWorkflows = matchedRules.length ? configured.filter(name => matchedRules.every(rule => rule.workflows.includes(name))) : configured;
81
+ const matchedRules = (entry.params.completion_ci.path_workflows?.[repo] ?? []).map(rule => ({ ...rule,
82
+ changed_at: records.find(([, , names]) => names.split('\n').some(path => rule.paths.some(prefix => path.startsWith(prefix))))?.[1]
83
+ })).filter(rule => rule.changed_at);
84
84
  const requestedRun = payload.ci_run ?? payload['ci-run'] ?? payload.metadata?.ci_run ?? (old?.commit === commit ? old?.run_id : null);
85
85
  let receipt;
86
86
  if (requestedRun) {
87
87
  receipt = JSON.parse(run('gh', ['run', 'view', String(requestedRun), '--repo', repo, '--json', 'databaseId,workflowName,headSha,status,conclusion,url'], path));
88
88
  } else {
89
89
  const runs = JSON.parse(run('gh', ['run', 'list', '--repo', repo, '--commit', commit, '--limit', '100', '--json', 'databaseId,workflowName,headSha,status,conclusion,url'], path));
90
- receipt = runs.find(row => deploymentWorkflows.includes(row.workflowName));
90
+ receipt = runs.find(row => configured.includes(row.workflowName));
91
91
  }
92
92
  if (!receipt) throw new Error(`No deployment CI run exists for ${repo}@${commit}.`);
93
93
  Object.assign(state, { run_id: receipt.databaseId, workflow: receipt.workflowName, status: receipt.status, conclusion: receipt.conclusion, url: receipt.url });
94
94
  if (receipt.headSha !== commit) throw new Error(`CI run ${receipt.databaseId} is for ${receipt.headSha}, not ${commit}.`);
95
- if (!deploymentWorkflows.includes(receipt.workflowName)) throw new Error(`${receipt.workflowName} is not a declared deployment workflow for ${repo}.`);
95
+ if (!configured.includes(receipt.workflowName)) throw new Error(`${receipt.workflowName} is not a declared deployment workflow for ${repo}.`);
96
96
  if (receipt.status !== 'completed' || receipt.conclusion !== 'success') throw new Error(`Deployment CI ${receipt.databaseId} is ${receipt.status}/${receipt.conclusion || 'pending'}.`);
97
+ // A later SDK publication need not rebuild unchanged native code. It does
98
+ // need a successful native deployment containing this task's native changes.
99
+ // Retain each artifact's actual SHA, rather than calling the SDK run a native release.
100
+ state.coverage = [];
101
+ let successful;
102
+ for (const rule of matchedRules) {
103
+ if (rule.workflows.includes(receipt.workflowName)) continue;
104
+ successful ??= JSON.parse(run('gh', ['run', 'list', '--repo', repo, '--status', 'success', '--limit', '100', '--json', 'databaseId,workflowName,headSha,status,conclusion,url'], path));
105
+ const covering = successful.find(row => {
106
+ if (!rule.workflows.includes(row.workflowName) || !configured.includes(row.workflowName)) return false;
107
+ try {
108
+ run('git', ['merge-base', '--is-ancestor', rule.changed_at, row.headSha], path);
109
+ run('git', ['merge-base', '--is-ancestor', row.headSha, commit], path);
110
+ // Any later change in these paths requires another native deployment,
111
+ // even when a different task authored that change.
112
+ return run('git', ['diff', '--name-only', row.headSha, commit], path).split('\n').every(name => !rule.paths.some(prefix => name.startsWith(prefix)));
113
+ } catch { return false; }
114
+ });
115
+ if (!covering) throw new Error(`No successful ${rule.workflows.join('/')} deployment covers ${rule.paths.join(', ')} through ${commit}.`);
116
+ state.coverage.push({ paths: rule.paths, commit: covering.headSha, workflow: covering.workflowName, run_id: covering.databaseId, conclusion: covering.conclusion, url: covering.url });
117
+ }
97
118
  state.deployed_sha = commit;
98
119
  state.ready = true;
99
120
  state.reason = null;
package/board/wake.mjs CHANGED
@@ -74,7 +74,12 @@ export function watchBoard({ root, binary, env, log = () => {} }) {
74
74
  const mail = join(config, 'mail');
75
75
  directory(mail, 'mailbox-registry', name => name.startsWith('board-'));
76
76
  if (existsSync(mail)) for (const name of readdirSync(mail)) {
77
- if (name.startsWith('board-')) directory(join(mail, name, 'new'), 'board-mail', name => name.endsWith('.json'));
77
+ if (name.startsWith('board-')) {
78
+ const inbox = join(mail, name, 'new');
79
+ // Reading mail moves it out of new/. That removal is not new work and
80
+ // must not make the dispatcher schedule another tick for its own read.
81
+ directory(inbox, 'board-mail', file => file.endsWith('.json') && existsSync(join(inbox, file)));
82
+ }
78
83
  }
79
84
  };
80
85
  // The retained Teams catalogue includes local and remote session changes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-orchestrator",
3
- "version": "0.4.134",
3
+ "version": "0.4.136",
4
4
  "type": "module",
5
5
  "description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
6
6
  "exports": {