mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-11 02:33:10 +08:00
feat: add dynamic workflow team orchestration surface
Adds dynamic workflow/team orchestration skills, the content pack, and control-pane work-item/Kanban state DB support. Includes reviewer hardening for state-db CLI validation, optional state DB failure handling, and mergeStateStatus projection.
This commit is contained in:
104
tests/ci/dynamic-workflow-team-surface.test.js
Normal file
104
tests/ci/dynamic-workflow-team-surface.test.js
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate the dynamic workflow and team-orchestration public surface.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
const SURFACES = [
|
||||
{
|
||||
path: 'skills/dynamic-workflow-mode/SKILL.md',
|
||||
required: [
|
||||
'dynamic workflow mode',
|
||||
'task-local harness',
|
||||
'shared skill',
|
||||
'eval',
|
||||
'control pane',
|
||||
'handoff'
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'skills/team-agent-orchestration/SKILL.md',
|
||||
required: [
|
||||
'team-based orchestration',
|
||||
'agent kanban',
|
||||
'work item',
|
||||
'ownership',
|
||||
'merge gate',
|
||||
'control pane'
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'docs/business/team-agent-orchestration-content-pack.md',
|
||||
required: [
|
||||
'Video Concepts',
|
||||
'Article Angles',
|
||||
'agent kanban',
|
||||
'team orchestration',
|
||||
'dynamic workflows',
|
||||
'distribution'
|
||||
],
|
||||
forbidden: [
|
||||
'https://x.com/',
|
||||
'http://x.com/',
|
||||
'twitter.com/'
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function readSurface(relativePath) {
|
||||
const absolutePath = path.join(REPO_ROOT, relativePath);
|
||||
assert.ok(fs.existsSync(absolutePath), `${relativePath} is missing`);
|
||||
return fs.readFileSync(absolutePath, 'utf8');
|
||||
}
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` PASS ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` FAIL ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
console.log('\n=== Testing dynamic workflow team surface ===\n');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const surface of SURFACES) {
|
||||
if (test(`${surface.path} exists and carries required concepts`, () => {
|
||||
const content = readSurface(surface.path);
|
||||
const normalized = content.toLowerCase();
|
||||
|
||||
for (const term of surface.required) {
|
||||
assert.ok(
|
||||
normalized.includes(term.toLowerCase()),
|
||||
`${surface.path} is missing required concept: ${term}`
|
||||
);
|
||||
}
|
||||
|
||||
for (const forbidden of surface.forbidden || []) {
|
||||
assert.ok(
|
||||
!normalized.includes(forbidden.toLowerCase()),
|
||||
`${surface.path} must not expose private bookmark source URLs: ${forbidden}`
|
||||
);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
}
|
||||
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -227,6 +227,96 @@ async function writeSampleEcc2Database(dbPath) {
|
||||
db.close();
|
||||
}
|
||||
|
||||
async function writeSampleWorkItemsDatabase(dbPath) {
|
||||
const SQL = await initSqlJs();
|
||||
const db = new SQL.Database();
|
||||
|
||||
db.run(`
|
||||
CREATE TABLE work_items (
|
||||
id TEXT PRIMARY KEY,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
title TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
priority TEXT,
|
||||
url TEXT,
|
||||
owner TEXT,
|
||||
repo_root TEXT,
|
||||
session_id TEXT,
|
||||
metadata TEXT NOT NULL CHECK (json_valid(metadata)),
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
const insertWorkItem = db.prepare(`
|
||||
INSERT INTO work_items (
|
||||
id, source, source_id, title, status, priority, url, owner,
|
||||
repo_root, session_id, metadata, created_at, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
insertWorkItem.run([
|
||||
'agent-card-001',
|
||||
'manual',
|
||||
'agent-card-001',
|
||||
'Build dynamic workflow skill',
|
||||
'running',
|
||||
'high',
|
||||
null,
|
||||
'codex',
|
||||
'/repo/ecc',
|
||||
'lead-hermes',
|
||||
JSON.stringify({
|
||||
branch: 'product/dynamic-workflow-team-orchestration',
|
||||
mergeGate: 'focused tests and catalog check pass',
|
||||
acceptance: ['skill exists', 'content pack exists'],
|
||||
}),
|
||||
'2026-06-04T09:00:00Z',
|
||||
'2026-06-04T09:05:00Z',
|
||||
]);
|
||||
insertWorkItem.run([
|
||||
'agent-card-002',
|
||||
'github-pr',
|
||||
'2131',
|
||||
'Merge ECC control pane',
|
||||
'done',
|
||||
'normal',
|
||||
'https://github.com/affaan-m/ECC/pull/2131',
|
||||
'affaan',
|
||||
'/repo/ecc',
|
||||
null,
|
||||
JSON.stringify({
|
||||
branch: 'product/ecc2-knowledge-control-pane',
|
||||
mergeStateStatus: 'CLEAN',
|
||||
}),
|
||||
'2026-06-03T13:00:00Z',
|
||||
'2026-06-03T13:55:00Z',
|
||||
]);
|
||||
insertWorkItem.run([
|
||||
'agent-card-003',
|
||||
'manual',
|
||||
'blocked-content',
|
||||
'Record content pipeline',
|
||||
'blocked',
|
||||
'high',
|
||||
null,
|
||||
'operator',
|
||||
'/repo/ecc',
|
||||
null,
|
||||
JSON.stringify({
|
||||
blocker: 'needs publish approval',
|
||||
mergeGate: 'approval packet accepted',
|
||||
}),
|
||||
'2026-06-04T09:10:00Z',
|
||||
'2026-06-04T09:12:00Z',
|
||||
]);
|
||||
insertWorkItem.free();
|
||||
|
||||
fs.writeFileSync(dbPath, Buffer.from(db.export()));
|
||||
db.close();
|
||||
}
|
||||
|
||||
async function mutateSqlDatabase(dbPath, mutator) {
|
||||
const SQL = await initSqlJs();
|
||||
const buffer = fs.readFileSync(dbPath);
|
||||
@@ -290,6 +380,64 @@ async function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('projects state-store work items into agent Kanban summary', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-work-items-'));
|
||||
const dbPath = path.join(tempDir, 'ecc2.db');
|
||||
const stateDbPath = path.join(tempDir, 'state.db');
|
||||
|
||||
try {
|
||||
await writeSampleEcc2Database(dbPath);
|
||||
await writeSampleWorkItemsDatabase(stateDbPath);
|
||||
|
||||
const snapshot = await buildControlPaneSnapshot({
|
||||
dbPath,
|
||||
stateDbPath,
|
||||
repoRoot: path.join(__dirname, '..', '..'),
|
||||
query: 'workflow',
|
||||
});
|
||||
|
||||
assert.strictEqual(snapshot.workItems.totalCount, 3);
|
||||
assert.strictEqual(snapshot.workItems.openCount, 2);
|
||||
assert.strictEqual(snapshot.workItems.blockedCount, 1);
|
||||
assert.strictEqual(snapshot.workItems.doneCount, 1);
|
||||
assert.strictEqual(snapshot.workItems.kanban.running, 1);
|
||||
assert.strictEqual(snapshot.workItems.kanban.blocked, 1);
|
||||
assert.strictEqual(snapshot.workItems.items[0].id, 'agent-card-003');
|
||||
assert.strictEqual(snapshot.workItems.items[0].mergeGate, 'approval packet accepted');
|
||||
assert.strictEqual(snapshot.workItems.items[1].branch, 'product/dynamic-workflow-team-orchestration');
|
||||
assert.strictEqual(
|
||||
snapshot.workItems.items.find(item => item.id === 'agent-card-002').mergeGate,
|
||||
'CLEAN'
|
||||
);
|
||||
} finally {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('treats an unreadable optional state-store database as empty work items', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-corrupt-work-items-'));
|
||||
const dbPath = path.join(tempDir, 'ecc2.db');
|
||||
const stateDbPath = path.join(tempDir, 'corrupt-state.db');
|
||||
|
||||
try {
|
||||
await writeSampleEcc2Database(dbPath);
|
||||
fs.writeFileSync(stateDbPath, 'not a sqlite database', 'utf8');
|
||||
|
||||
const snapshot = await buildControlPaneSnapshot({
|
||||
dbPath,
|
||||
stateDbPath,
|
||||
repoRoot: path.join(__dirname, '..', '..'),
|
||||
query: 'workflow',
|
||||
});
|
||||
|
||||
assert.strictEqual(snapshot.stateDatabase.exists, true);
|
||||
assert.strictEqual(snapshot.workItems.totalCount, 0);
|
||||
assert.strictEqual(snapshot.summary.totalSessions, 2);
|
||||
} finally {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('resolves config from explicit db path and TOML connector file', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-config-'));
|
||||
const dbPath = path.join(tempDir, 'state.db');
|
||||
|
||||
@@ -148,6 +148,8 @@ async function runTests() {
|
||||
'8788',
|
||||
'--db',
|
||||
'/tmp/ecc2.db',
|
||||
'--state-db',
|
||||
'/tmp/ecc-state.db',
|
||||
'--query',
|
||||
'Hermes memory',
|
||||
'--no-open',
|
||||
@@ -156,6 +158,7 @@ async function runTests() {
|
||||
assert.strictEqual(parsed.host, '127.0.0.1');
|
||||
assert.strictEqual(parsed.port, 8788);
|
||||
assert.strictEqual(parsed.dbPath, '/tmp/ecc2.db');
|
||||
assert.strictEqual(parsed.stateDbPath, '/tmp/ecc-state.db');
|
||||
assert.strictEqual(parsed.query, 'Hermes memory');
|
||||
assert.strictEqual(parsed.openBrowser, false);
|
||||
})) passed++; else failed++;
|
||||
@@ -171,6 +174,17 @@ async function runTests() {
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('rejects missing state database path values', async () => {
|
||||
assert.throws(
|
||||
() => parseArgs(['node', 'scripts/control-pane.js', '--state-db']),
|
||||
/Invalid --state-db value/
|
||||
);
|
||||
assert.throws(
|
||||
() => parseArgs(['node', 'scripts/control-pane.js', '--state-db', '--query', 'Hermes']),
|
||||
/Invalid --state-db value/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('serves HTML and snapshot JSON from a temp ECC2 database', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-server-'));
|
||||
const dbPath = path.join(tempDir, 'ecc2.db');
|
||||
@@ -191,12 +205,15 @@ async function runTests() {
|
||||
const html = await fetchLocal(`${app.url}/`).then(response => response.text());
|
||||
assert.ok(html.includes('ECC Control Pane'));
|
||||
assert.ok(html.includes('id="app"'));
|
||||
assert.ok(html.includes('id="work-items"'));
|
||||
assert.ok(html.includes('function renderWorkItems'));
|
||||
assert.ok(html.includes('function showError'));
|
||||
assert.ok(html.includes('response.ok'));
|
||||
|
||||
const snapshot = await fetchLocal(`${app.url}/api/snapshot?query=control`).then(response => response.json());
|
||||
assert.strictEqual(snapshot.schemaVersion, 'ecc.control-pane.snapshot.v1');
|
||||
assert.strictEqual(snapshot.summary.totalSessions, 1);
|
||||
assert.strictEqual(snapshot.workItems.totalCount, 0);
|
||||
assert.strictEqual(snapshot.sessions[0].id, 'session-a');
|
||||
} finally {
|
||||
await app.close();
|
||||
|
||||
Reference in New Issue
Block a user