reflectt-node 0.1.8 → 0.1.12
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/defaults/TEAM-ROLES.yaml +317 -5
- package/dist/agent-config.d.ts +51 -0
- package/dist/agent-config.d.ts.map +1 -0
- package/dist/agent-config.js +129 -0
- package/dist/agent-config.js.map +1 -0
- package/dist/agent-config.test.d.ts +2 -0
- package/dist/agent-config.test.d.ts.map +1 -0
- package/dist/agent-config.test.js +91 -0
- package/dist/agent-config.test.js.map +1 -0
- package/dist/agent-memories.d.ts +58 -0
- package/dist/agent-memories.d.ts.map +1 -0
- package/dist/agent-memories.js +168 -0
- package/dist/agent-memories.js.map +1 -0
- package/dist/agent-memories.test.d.ts +2 -0
- package/dist/agent-memories.test.d.ts.map +1 -0
- package/dist/agent-memories.test.js +327 -0
- package/dist/agent-memories.test.js.map +1 -0
- package/dist/agent-messaging.d.ts +50 -0
- package/dist/agent-messaging.d.ts.map +1 -0
- package/dist/agent-messaging.js +103 -0
- package/dist/agent-messaging.js.map +1 -0
- package/dist/agent-messaging.test.d.ts +2 -0
- package/dist/agent-messaging.test.d.ts.map +1 -0
- package/dist/agent-messaging.test.js +105 -0
- package/dist/agent-messaging.test.js.map +1 -0
- package/dist/agent-runs.d.ts +158 -0
- package/dist/agent-runs.d.ts.map +1 -0
- package/dist/agent-runs.js +514 -0
- package/dist/agent-runs.js.map +1 -0
- package/dist/agent-runs.test.d.ts +2 -0
- package/dist/agent-runs.test.d.ts.map +1 -0
- package/dist/agent-runs.test.js +386 -0
- package/dist/agent-runs.test.js.map +1 -0
- package/dist/approval-queue.test.d.ts +2 -0
- package/dist/approval-queue.test.d.ts.map +1 -0
- package/dist/approval-queue.test.js +118 -0
- package/dist/approval-queue.test.js.map +1 -0
- package/dist/artifact-store.d.ts +55 -0
- package/dist/artifact-store.d.ts.map +1 -0
- package/dist/artifact-store.js +128 -0
- package/dist/artifact-store.js.map +1 -0
- package/dist/artifact-store.test.d.ts +2 -0
- package/dist/artifact-store.test.d.ts.map +1 -0
- package/dist/artifact-store.test.js +119 -0
- package/dist/artifact-store.test.js.map +1 -0
- package/dist/boardHealthWorker.d.ts +28 -0
- package/dist/boardHealthWorker.d.ts.map +1 -1
- package/dist/boardHealthWorker.js +33 -1
- package/dist/boardHealthWorker.js.map +1 -1
- package/dist/canvas-input.test.d.ts +2 -0
- package/dist/canvas-input.test.d.ts.map +1 -0
- package/dist/canvas-input.test.js +96 -0
- package/dist/canvas-input.test.js.map +1 -0
- package/dist/canvas-render.test.d.ts +2 -0
- package/dist/canvas-render.test.d.ts.map +1 -0
- package/dist/canvas-render.test.js +95 -0
- package/dist/canvas-render.test.js.map +1 -0
- package/dist/capabilities/browser.d.ts +75 -0
- package/dist/capabilities/browser.d.ts.map +1 -0
- package/dist/capabilities/browser.js +172 -0
- package/dist/capabilities/browser.js.map +1 -0
- package/dist/channels.d.ts +1 -1
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/cloud.d.ts +2 -0
- package/dist/cloud.d.ts.map +1 -1
- package/dist/cloud.js +135 -3
- package/dist/cloud.js.map +1 -1
- package/dist/cost-enforcement.d.ts +38 -0
- package/dist/cost-enforcement.d.ts.map +1 -0
- package/dist/cost-enforcement.js +84 -0
- package/dist/cost-enforcement.js.map +1 -0
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +8 -0
- package/dist/dashboard.js.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +131 -0
- package/dist/db.js.map +1 -1
- package/dist/e2e-loop-proof.test.d.ts +2 -0
- package/dist/e2e-loop-proof.test.d.ts.map +1 -0
- package/dist/e2e-loop-proof.test.js +104 -0
- package/dist/e2e-loop-proof.test.js.map +1 -0
- package/dist/email-sms-send.test.d.ts +2 -0
- package/dist/email-sms-send.test.d.ts.map +1 -0
- package/dist/email-sms-send.test.js +96 -0
- package/dist/email-sms-send.test.js.map +1 -0
- package/dist/events.d.ts +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -1
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +5 -10
- package/dist/fingerprint.js.map +1 -1
- package/dist/github-webhook-chat.d.ts +75 -0
- package/dist/github-webhook-chat.d.ts.map +1 -0
- package/dist/github-webhook-chat.js +108 -0
- package/dist/github-webhook-chat.js.map +1 -0
- package/dist/handoff-state.test.d.ts +2 -0
- package/dist/handoff-state.test.d.ts.map +1 -0
- package/dist/handoff-state.test.js +102 -0
- package/dist/handoff-state.test.js.map +1 -0
- package/dist/health.d.ts +9 -0
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +18 -0
- package/dist/health.js.map +1 -1
- package/dist/host-error-correlation.d.ts +65 -0
- package/dist/host-error-correlation.d.ts.map +1 -0
- package/dist/host-error-correlation.js +123 -0
- package/dist/host-error-correlation.js.map +1 -0
- package/dist/index.js +39 -10
- package/dist/index.js.map +1 -1
- package/dist/notificationDedupeGuard.d.ts +4 -0
- package/dist/notificationDedupeGuard.d.ts.map +1 -1
- package/dist/notificationDedupeGuard.js +8 -4
- package/dist/notificationDedupeGuard.js.map +1 -1
- package/dist/presence.d.ts +37 -5
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +127 -16
- package/dist/presence.js.map +1 -1
- package/dist/review-sla.d.ts +9 -0
- package/dist/review-sla.d.ts.map +1 -0
- package/dist/review-sla.js +51 -0
- package/dist/review-sla.js.map +1 -0
- package/dist/routing-enforcement.test.d.ts +2 -0
- package/dist/routing-enforcement.test.d.ts.map +1 -0
- package/dist/routing-enforcement.test.js +86 -0
- package/dist/routing-enforcement.test.js.map +1 -0
- package/dist/run-retention.test.d.ts +2 -0
- package/dist/run-retention.test.d.ts.map +1 -0
- package/dist/run-retention.test.js +57 -0
- package/dist/run-retention.test.js.map +1 -0
- package/dist/run-stream.test.d.ts +2 -0
- package/dist/run-stream.test.d.ts.map +1 -0
- package/dist/run-stream.test.js +70 -0
- package/dist/run-stream.test.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1301 -75
- package/dist/server.js.map +1 -1
- package/dist/tasks.d.ts.map +1 -1
- package/dist/tasks.js +45 -0
- package/dist/tasks.js.map +1 -1
- package/dist/todoHoardingGuard.d.ts +17 -0
- package/dist/todoHoardingGuard.d.ts.map +1 -1
- package/dist/todoHoardingGuard.js +25 -2
- package/dist/todoHoardingGuard.js.map +1 -1
- package/dist/webhook-storage.d.ts +50 -0
- package/dist/webhook-storage.d.ts.map +1 -0
- package/dist/webhook-storage.js +102 -0
- package/dist/webhook-storage.js.map +1 -0
- package/dist/webhook-storage.test.d.ts +2 -0
- package/dist/webhook-storage.test.d.ts.map +1 -0
- package/dist/webhook-storage.test.js +86 -0
- package/dist/webhook-storage.test.js.map +1 -0
- package/dist/workflow-templates.d.ts +44 -0
- package/dist/workflow-templates.d.ts.map +1 -0
- package/dist/workflow-templates.js +154 -0
- package/dist/workflow-templates.js.map +1 -0
- package/dist/workflow-templates.test.d.ts +2 -0
- package/dist/workflow-templates.test.d.ts.map +1 -0
- package/dist/workflow-templates.test.js +76 -0
- package/dist/workflow-templates.test.js.map +1 -0
- package/package.json +3 -1
- package/public/dashboard.js +76 -1
- package/public/design-tokens-platform.md +118 -0
- package/public/design-tokens.css +195 -0
- package/public/docs.md +131 -2
- package/public/presence-loop-demo.html +473 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-storage.test.d.ts","sourceRoot":"","sources":["../src/webhook-storage.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { describe, it, beforeEach } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
class InMemoryWebhookStore {
|
|
5
|
+
payloads = [];
|
|
6
|
+
counter = 0;
|
|
7
|
+
ingest(source, eventType, body, agentId) {
|
|
8
|
+
const p = { id: `whk-${++this.counter}`, source, eventType, agentId: agentId ?? null, body, processed: false };
|
|
9
|
+
this.payloads.push(p);
|
|
10
|
+
return p;
|
|
11
|
+
}
|
|
12
|
+
get(id) { return this.payloads.find(p => p.id === id) ?? null; }
|
|
13
|
+
list(opts) {
|
|
14
|
+
return this.payloads.filter(p => {
|
|
15
|
+
if (opts?.source && p.source !== opts.source)
|
|
16
|
+
return false;
|
|
17
|
+
if (opts?.agentId && p.agentId !== opts.agentId)
|
|
18
|
+
return false;
|
|
19
|
+
if (opts?.unprocessedOnly && p.processed)
|
|
20
|
+
return false;
|
|
21
|
+
return true;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
markProcessed(id) {
|
|
25
|
+
const p = this.get(id);
|
|
26
|
+
if (!p || p.processed)
|
|
27
|
+
return false;
|
|
28
|
+
p.processed = true;
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
unprocessedCount(opts) {
|
|
32
|
+
return this.list({ source: opts?.source, unprocessedOnly: true }).length;
|
|
33
|
+
}
|
|
34
|
+
clear() { this.payloads = []; this.counter = 0; }
|
|
35
|
+
}
|
|
36
|
+
describe('webhook storage', () => {
|
|
37
|
+
let store;
|
|
38
|
+
beforeEach(() => { store = new InMemoryWebhookStore(); });
|
|
39
|
+
it('ingests a payload', () => {
|
|
40
|
+
const p = store.ingest('resend', 'email.received', { from: 'user@example.com', subject: 'Test' });
|
|
41
|
+
assert.ok(p.id.startsWith('whk-'));
|
|
42
|
+
assert.equal(p.source, 'resend');
|
|
43
|
+
assert.equal(p.eventType, 'email.received');
|
|
44
|
+
assert.equal(p.processed, false);
|
|
45
|
+
});
|
|
46
|
+
it('retrieves by id', () => {
|
|
47
|
+
const p = store.ingest('resend', 'email.received', { subject: 'Hello' });
|
|
48
|
+
assert.deepEqual(store.get(p.id)?.body, { subject: 'Hello' });
|
|
49
|
+
});
|
|
50
|
+
it('returns null for missing id', () => {
|
|
51
|
+
assert.equal(store.get('nonexistent'), null);
|
|
52
|
+
});
|
|
53
|
+
it('lists by source', () => {
|
|
54
|
+
store.ingest('resend', 'email.received', { a: 1 });
|
|
55
|
+
store.ingest('twilio', 'sms.received', { b: 2 });
|
|
56
|
+
store.ingest('resend', 'email.bounced', { c: 3 });
|
|
57
|
+
assert.equal(store.list({ source: 'resend' }).length, 2);
|
|
58
|
+
assert.equal(store.list({ source: 'twilio' }).length, 1);
|
|
59
|
+
});
|
|
60
|
+
it('lists by agent', () => {
|
|
61
|
+
store.ingest('resend', 'email.received', {}, 'link');
|
|
62
|
+
store.ingest('resend', 'email.received', {}, 'kai');
|
|
63
|
+
assert.equal(store.list({ agentId: 'link' }).length, 1);
|
|
64
|
+
});
|
|
65
|
+
it('marks as processed', () => {
|
|
66
|
+
const p = store.ingest('resend', 'email.received', {});
|
|
67
|
+
assert.equal(store.markProcessed(p.id), true);
|
|
68
|
+
assert.equal(store.get(p.id)?.processed, true);
|
|
69
|
+
// Double-process returns false
|
|
70
|
+
assert.equal(store.markProcessed(p.id), false);
|
|
71
|
+
});
|
|
72
|
+
it('filters unprocessed only', () => {
|
|
73
|
+
const p1 = store.ingest('resend', 'email.received', {});
|
|
74
|
+
store.ingest('resend', 'email.received', {});
|
|
75
|
+
store.markProcessed(p1.id);
|
|
76
|
+
assert.equal(store.list({ unprocessedOnly: true }).length, 1);
|
|
77
|
+
});
|
|
78
|
+
it('tracks unprocessed count', () => {
|
|
79
|
+
store.ingest('resend', 'email.received', {});
|
|
80
|
+
store.ingest('resend', 'email.received', {});
|
|
81
|
+
store.ingest('twilio', 'sms.received', {});
|
|
82
|
+
assert.equal(store.unprocessedCount(), 3);
|
|
83
|
+
assert.equal(store.unprocessedCount({ source: 'resend' }), 2);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=webhook-storage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-storage.test.js","sourceRoot":"","sources":["../src/webhook-storage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface WorkflowStep {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
action: (ctx: WorkflowContext) => Promise<StepResult> | StepResult;
|
|
5
|
+
}
|
|
6
|
+
export interface WorkflowContext {
|
|
7
|
+
runId: string;
|
|
8
|
+
agentId: string;
|
|
9
|
+
teamId: string;
|
|
10
|
+
params: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface StepResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
data?: Record<string, unknown>;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface WorkflowTemplate {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
steps: WorkflowStep[];
|
|
22
|
+
}
|
|
23
|
+
export interface WorkflowResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
runId: string;
|
|
26
|
+
steps: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
success: boolean;
|
|
29
|
+
data?: Record<string, unknown>;
|
|
30
|
+
error?: string;
|
|
31
|
+
durationMs: number;
|
|
32
|
+
}>;
|
|
33
|
+
totalDurationMs: number;
|
|
34
|
+
}
|
|
35
|
+
export declare const prReviewWorkflow: WorkflowTemplate;
|
|
36
|
+
export declare function runWorkflow(template: WorkflowTemplate, agentId: string, teamId: string, params?: Record<string, unknown>): Promise<WorkflowResult>;
|
|
37
|
+
export declare function getWorkflowTemplate(id: string): WorkflowTemplate | undefined;
|
|
38
|
+
export declare function listWorkflowTemplates(): Array<{
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
description: string;
|
|
42
|
+
stepCount: number;
|
|
43
|
+
}>;
|
|
44
|
+
//# sourceMappingURL=workflow-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-templates.d.ts","sourceRoot":"","sources":["../src/workflow-templates.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAA;CACnE;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpH,eAAe,EAAE,MAAM,CAAA;CACxB;AAID,eAAO,MAAM,gBAAgB,EAAE,gBAoG9B,CAAA;AAID,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,OAAO,CAAC,cAAc,CAAC,CA+BzB;AAQD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5E;AAED,wBAAgB,qBAAqB,IAAI,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAOnH"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Canonical workflow templates — reusable, runnable, regression-testable
|
|
3
|
+
// Packages the proven PR review → approve → handoff → completion loop
|
|
4
|
+
import { createAgentRun, updateAgentRun, appendAgentEvent } from './agent-runs.js';
|
|
5
|
+
// ── PR Review Workflow ──────────────────────────────────────────────────
|
|
6
|
+
export const prReviewWorkflow = {
|
|
7
|
+
id: 'pr-review',
|
|
8
|
+
name: 'PR Review → Approve → Handoff → Complete',
|
|
9
|
+
description: 'The canonical agent workflow: create run, attach task, request review, approve, handoff, complete.',
|
|
10
|
+
steps: [
|
|
11
|
+
{
|
|
12
|
+
name: 'create_run',
|
|
13
|
+
description: 'Create an agent run with objective',
|
|
14
|
+
action: (ctx) => {
|
|
15
|
+
const run = createAgentRun(ctx.agentId, ctx.teamId, ctx.params.objective ?? 'PR review workflow', {
|
|
16
|
+
taskId: ctx.params.taskId,
|
|
17
|
+
});
|
|
18
|
+
ctx.runId = run.id;
|
|
19
|
+
return { success: true, data: { runId: run.id } };
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'start_work',
|
|
24
|
+
description: 'Move run to working status',
|
|
25
|
+
action: (ctx) => {
|
|
26
|
+
updateAgentRun(ctx.runId, { status: 'working' });
|
|
27
|
+
appendAgentEvent({
|
|
28
|
+
agentId: ctx.agentId,
|
|
29
|
+
runId: ctx.runId,
|
|
30
|
+
eventType: 'work_started',
|
|
31
|
+
payload: { message: 'Agent began working on objective' },
|
|
32
|
+
});
|
|
33
|
+
return { success: true };
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'request_review',
|
|
38
|
+
description: 'Submit work for review',
|
|
39
|
+
action: (ctx) => {
|
|
40
|
+
updateAgentRun(ctx.runId, { status: 'waiting_review' });
|
|
41
|
+
const event = appendAgentEvent({
|
|
42
|
+
agentId: ctx.agentId,
|
|
43
|
+
runId: ctx.runId,
|
|
44
|
+
eventType: 'review_requested',
|
|
45
|
+
payload: {
|
|
46
|
+
action_required: 'Review and approve the submitted work',
|
|
47
|
+
urgency: ctx.params.urgency ?? 'normal',
|
|
48
|
+
owner: ctx.params.reviewer ?? 'kai',
|
|
49
|
+
pr_url: ctx.params.prUrl,
|
|
50
|
+
title: ctx.params.title ?? 'Review requested',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return { success: true, data: { eventId: event.id } };
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'approve',
|
|
58
|
+
description: 'Approve the review (simulates reviewer action)',
|
|
59
|
+
action: (ctx) => {
|
|
60
|
+
updateAgentRun(ctx.runId, { status: 'working' });
|
|
61
|
+
appendAgentEvent({
|
|
62
|
+
agentId: ctx.agentId,
|
|
63
|
+
runId: ctx.runId,
|
|
64
|
+
eventType: 'review_approved',
|
|
65
|
+
payload: {
|
|
66
|
+
reviewer: ctx.params.reviewer ?? 'kai',
|
|
67
|
+
comment: 'LGTM',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
return { success: true };
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'handoff',
|
|
75
|
+
description: 'Hand off to next owner or complete',
|
|
76
|
+
action: (ctx) => {
|
|
77
|
+
appendAgentEvent({
|
|
78
|
+
agentId: ctx.agentId,
|
|
79
|
+
runId: ctx.runId,
|
|
80
|
+
eventType: 'handoff',
|
|
81
|
+
payload: {
|
|
82
|
+
action_required: 'Deploy or merge the approved work',
|
|
83
|
+
urgency: 'normal',
|
|
84
|
+
owner: ctx.params.nextOwner ?? ctx.agentId,
|
|
85
|
+
summary: ctx.params.summary ?? 'Work reviewed and approved',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
return { success: true };
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'complete',
|
|
93
|
+
description: 'Mark run as completed',
|
|
94
|
+
action: (ctx) => {
|
|
95
|
+
updateAgentRun(ctx.runId, { status: 'completed', completedAt: Date.now() });
|
|
96
|
+
appendAgentEvent({
|
|
97
|
+
agentId: ctx.agentId,
|
|
98
|
+
runId: ctx.runId,
|
|
99
|
+
eventType: 'run_completed',
|
|
100
|
+
payload: { message: 'Workflow completed successfully' },
|
|
101
|
+
});
|
|
102
|
+
return { success: true };
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
};
|
|
107
|
+
// ── Workflow runner ──────────────────────────────────────────────────────
|
|
108
|
+
export async function runWorkflow(template, agentId, teamId, params = {}) {
|
|
109
|
+
const start = Date.now();
|
|
110
|
+
const ctx = { runId: '', agentId, teamId, params };
|
|
111
|
+
const stepResults = [];
|
|
112
|
+
for (const step of template.steps) {
|
|
113
|
+
const stepStart = Date.now();
|
|
114
|
+
try {
|
|
115
|
+
const result = await step.action(ctx);
|
|
116
|
+
stepResults.push({
|
|
117
|
+
name: step.name,
|
|
118
|
+
success: result.success,
|
|
119
|
+
data: result.data,
|
|
120
|
+
error: result.error,
|
|
121
|
+
durationMs: Date.now() - stepStart,
|
|
122
|
+
});
|
|
123
|
+
if (!result.success) {
|
|
124
|
+
return { success: false, runId: ctx.runId, steps: stepResults, totalDurationMs: Date.now() - start };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
stepResults.push({
|
|
129
|
+
name: step.name,
|
|
130
|
+
success: false,
|
|
131
|
+
error: err.message,
|
|
132
|
+
durationMs: Date.now() - stepStart,
|
|
133
|
+
});
|
|
134
|
+
return { success: false, runId: ctx.runId, steps: stepResults, totalDurationMs: Date.now() - start };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { success: true, runId: ctx.runId, steps: stepResults, totalDurationMs: Date.now() - start };
|
|
138
|
+
}
|
|
139
|
+
// ── Template registry ───────────────────────────────────────────────────
|
|
140
|
+
const TEMPLATES = new Map([
|
|
141
|
+
['pr-review', prReviewWorkflow],
|
|
142
|
+
]);
|
|
143
|
+
export function getWorkflowTemplate(id) {
|
|
144
|
+
return TEMPLATES.get(id);
|
|
145
|
+
}
|
|
146
|
+
export function listWorkflowTemplates() {
|
|
147
|
+
return [...TEMPLATES.values()].map(t => ({
|
|
148
|
+
id: t.id,
|
|
149
|
+
name: t.name,
|
|
150
|
+
description: t.description,
|
|
151
|
+
stepCount: t.steps.length,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=workflow-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-templates.js","sourceRoot":"","sources":["../src/workflow-templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-templates.test.d.ts","sourceRoot":"","sources":["../src/workflow-templates.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
async function runSteps(steps) {
|
|
5
|
+
const completed = [];
|
|
6
|
+
for (const step of steps) {
|
|
7
|
+
const result = step.action();
|
|
8
|
+
if (!result.success)
|
|
9
|
+
return { success: false, completed, failed: step.name };
|
|
10
|
+
completed.push(step.name);
|
|
11
|
+
}
|
|
12
|
+
return { success: true, completed };
|
|
13
|
+
}
|
|
14
|
+
describe('workflow templates', () => {
|
|
15
|
+
it('runs all steps in order on success', async () => {
|
|
16
|
+
const steps = [
|
|
17
|
+
{ name: 'create', action: () => ({ success: true }) },
|
|
18
|
+
{ name: 'work', action: () => ({ success: true }) },
|
|
19
|
+
{ name: 'review', action: () => ({ success: true }) },
|
|
20
|
+
{ name: 'approve', action: () => ({ success: true }) },
|
|
21
|
+
{ name: 'handoff', action: () => ({ success: true }) },
|
|
22
|
+
{ name: 'complete', action: () => ({ success: true }) },
|
|
23
|
+
];
|
|
24
|
+
const result = await runSteps(steps);
|
|
25
|
+
assert.equal(result.success, true);
|
|
26
|
+
assert.equal(result.completed.length, 6);
|
|
27
|
+
assert.deepEqual(result.completed, ['create', 'work', 'review', 'approve', 'handoff', 'complete']);
|
|
28
|
+
});
|
|
29
|
+
it('stops on first failure', async () => {
|
|
30
|
+
const steps = [
|
|
31
|
+
{ name: 'create', action: () => ({ success: true }) },
|
|
32
|
+
{ name: 'work', action: () => ({ success: true }) },
|
|
33
|
+
{ name: 'review', action: () => ({ success: false, error: 'Reviewer rejected' }) },
|
|
34
|
+
{ name: 'approve', action: () => ({ success: true }) },
|
|
35
|
+
];
|
|
36
|
+
const result = await runSteps(steps);
|
|
37
|
+
assert.equal(result.success, false);
|
|
38
|
+
assert.equal(result.failed, 'review');
|
|
39
|
+
assert.equal(result.completed.length, 2);
|
|
40
|
+
});
|
|
41
|
+
it('handles empty workflow', async () => {
|
|
42
|
+
const result = await runSteps([]);
|
|
43
|
+
assert.equal(result.success, true);
|
|
44
|
+
assert.equal(result.completed.length, 0);
|
|
45
|
+
});
|
|
46
|
+
it('pr-review template has 6 steps', () => {
|
|
47
|
+
const prReviewSteps = ['create_run', 'start_work', 'request_review', 'approve', 'handoff', 'complete'];
|
|
48
|
+
assert.equal(prReviewSteps.length, 6);
|
|
49
|
+
});
|
|
50
|
+
it('step order matches the canonical flow', () => {
|
|
51
|
+
const expected = ['create_run', 'start_work', 'request_review', 'approve', 'handoff', 'complete'];
|
|
52
|
+
// This is the order that was proven in the demo run
|
|
53
|
+
assert.equal(expected[0], 'create_run');
|
|
54
|
+
assert.equal(expected[1], 'start_work');
|
|
55
|
+
assert.equal(expected[2], 'request_review');
|
|
56
|
+
assert.equal(expected[3], 'approve');
|
|
57
|
+
assert.equal(expected[4], 'handoff');
|
|
58
|
+
assert.equal(expected[5], 'complete');
|
|
59
|
+
});
|
|
60
|
+
it('failure at create prevents all subsequent steps', async () => {
|
|
61
|
+
const steps = [
|
|
62
|
+
{ name: 'create', action: () => ({ success: false, error: 'DB error' }) },
|
|
63
|
+
{ name: 'work', action: () => ({ success: true }) },
|
|
64
|
+
];
|
|
65
|
+
const result = await runSteps(steps);
|
|
66
|
+
assert.equal(result.success, false);
|
|
67
|
+
assert.equal(result.completed.length, 0);
|
|
68
|
+
assert.equal(result.failed, 'create');
|
|
69
|
+
});
|
|
70
|
+
it('single step workflow succeeds', async () => {
|
|
71
|
+
const result = await runSteps([{ name: 'only', action: () => ({ success: true }) }]);
|
|
72
|
+
assert.equal(result.success, true);
|
|
73
|
+
assert.equal(result.completed.length, 1);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=workflow-templates.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-templates.test.js","sourceRoot":"","sources":["../src/workflow-templates.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reflectt-node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Coordinate your AI agent team. Shared tasks, memory, reflections, and presence. Self-host for free.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"author": "Team Reflectt",
|
|
45
45
|
"license": "Apache-2.0",
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@browserbasehq/stagehand": "^3.1.0",
|
|
47
48
|
"@fastify/cors": "^10.0.1",
|
|
48
49
|
"@fastify/multipart": "^9.4.0",
|
|
49
50
|
"@fastify/websocket": "^11.0.1",
|
|
@@ -87,6 +88,7 @@
|
|
|
87
88
|
"README.md"
|
|
88
89
|
],
|
|
89
90
|
"optionalDependencies": {
|
|
91
|
+
"@browserbasehq/stagehand": "^3.1.0",
|
|
90
92
|
"@xenova/transformers": "^2.17.2"
|
|
91
93
|
},
|
|
92
94
|
"overrides": {
|
package/public/dashboard.js
CHANGED
|
@@ -1457,6 +1457,7 @@ async function loadHealth() {
|
|
|
1457
1457
|
const team = health.team || { blockers: [], overlaps: [], compliance: null, agents: [] };
|
|
1458
1458
|
const agentsSummary = health.agentsSummary || { agents: [] };
|
|
1459
1459
|
const idleNudgeDebug = health.idleNudgeDebug || null;
|
|
1460
|
+
const scope = team.scope || null;
|
|
1460
1461
|
|
|
1461
1462
|
healthAgentMap = new Map((team.agents || []).map(a => [String(a.agent || '').toLowerCase(), a]));
|
|
1462
1463
|
const workflow = health.workflow || { agents: [] };
|
|
@@ -1525,6 +1526,16 @@ async function loadHealth() {
|
|
|
1525
1526
|
const body = document.getElementById('health-body');
|
|
1526
1527
|
let html = '';
|
|
1527
1528
|
|
|
1529
|
+
if (scope) {
|
|
1530
|
+
const orgHealthLink = scope.orgHealthUrl
|
|
1531
|
+
? ` <a href="${esc(scope.orgHealthUrl)}" target="_blank" rel="noopener">Open org-health</a>`
|
|
1532
|
+
: '';
|
|
1533
|
+
html += `<div class="blocker-item" style="border-left:4px solid var(--yellow);margin-bottom:12px">
|
|
1534
|
+
<div class="blocker-agent">${esc(scope.label || 'Host-local health')}</div>
|
|
1535
|
+
<div class="blocker-text">${esc(scope.message || '')}${orgHealthLink}</div>
|
|
1536
|
+
</div>`;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1528
1539
|
// Agent Health Grid
|
|
1529
1540
|
if (displayAgents.length > 0) {
|
|
1530
1541
|
html += '<div class="health-section"><div class="health-section-title">Agent Status</div><div class="health-grid">';
|
|
@@ -2208,6 +2219,70 @@ async function batchApproveHighConfidence() {
|
|
|
2208
2219
|
} catch (e) { console.error('Batch approve failed:', e); }
|
|
2209
2220
|
}
|
|
2210
2221
|
|
|
2222
|
+
// ---- Agent Action Approval Queue (review_requested events from agent runs) ----
|
|
2223
|
+
let agentApprovalData = null;
|
|
2224
|
+
|
|
2225
|
+
async function loadAgentApprovals() {
|
|
2226
|
+
try {
|
|
2227
|
+
const res = await fetch(BASE + '/approval-queue?category=review');
|
|
2228
|
+
agentApprovalData = await res.json();
|
|
2229
|
+
renderAgentApprovals();
|
|
2230
|
+
} catch (e) {
|
|
2231
|
+
const body = document.getElementById('agent-approval-body');
|
|
2232
|
+
if (body) body.innerHTML = '<div class="empty">Failed to load agent approvals</div>';
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
function renderAgentApprovals() {
|
|
2237
|
+
const body = document.getElementById('agent-approval-body');
|
|
2238
|
+
const count = document.getElementById('agent-approval-count');
|
|
2239
|
+
if (!body) return;
|
|
2240
|
+
|
|
2241
|
+
const items = (agentApprovalData && agentApprovalData.items) ? agentApprovalData.items : [];
|
|
2242
|
+
if (count) count.textContent = items.length > 0 ? items.length + ' pending' : '';
|
|
2243
|
+
|
|
2244
|
+
if (items.length === 0) {
|
|
2245
|
+
body.innerHTML = '<div class="empty" style="text-align:center;padding:20px;color:var(--text-dim)">✓ No pending agent approvals.</div>';
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
let html = '';
|
|
2250
|
+
items.forEach(function(item) {
|
|
2251
|
+
const urgencyColor = item.urgency === 'critical' ? '#ef4444' : item.urgency === 'high' ? '#f59e0b' : 'var(--text-dim)';
|
|
2252
|
+
const title = (item.title || item.event && item.event.payload && item.event.payload.action_required || 'Agent action pending').substring(0, 80);
|
|
2253
|
+
const desc = item.description || (item.event && item.event.payload && item.event.payload.description) || '';
|
|
2254
|
+
const agentId = item.agentId || '?';
|
|
2255
|
+
const runId = item.runId || '';
|
|
2256
|
+
html += '<div class="approval-card" style="border-left:3px solid ' + urgencyColor + '">';
|
|
2257
|
+
html += '<div class="approval-header">';
|
|
2258
|
+
html += '<span style="color:' + urgencyColor + '">⚡</span> ';
|
|
2259
|
+
html += '<span class="approval-title">' + esc(title) + '</span>';
|
|
2260
|
+
html += '<span class="assignee-tag" style="margin-left:8px">@' + esc(agentId) + '</span>';
|
|
2261
|
+
if (item.urgency) html += '<span style="font-size:10px;color:' + urgencyColor + ';margin-left:6px">' + esc(item.urgency) + '</span>';
|
|
2262
|
+
html += '</div>';
|
|
2263
|
+
if (desc) html += '<div class="approval-meta" style="font-size:12px;margin-top:4px">' + esc(desc.substring(0, 120)) + '</div>';
|
|
2264
|
+
if (runId) html += '<div class="approval-meta" style="font-size:10px;color:var(--text-dim)">Run: ' + esc(runId) + '</div>';
|
|
2265
|
+
html += '<div class="approval-actions">';
|
|
2266
|
+
html += '<button class="btn-reject" onclick="decideAgentApproval(\'' + esc(item.id) + '\',\'reject\')">✗ Reject</button>';
|
|
2267
|
+
html += '<button class="btn-approve" onclick="decideAgentApproval(\'' + esc(item.id) + '\',\'approve\')">✓ Approve</button>';
|
|
2268
|
+
html += '</div>';
|
|
2269
|
+
html += '</div>';
|
|
2270
|
+
});
|
|
2271
|
+
|
|
2272
|
+
body.innerHTML = html;
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
async function decideAgentApproval(eventId, decision) {
|
|
2276
|
+
try {
|
|
2277
|
+
await fetch(BASE + '/approval-queue/' + encodeURIComponent(eventId) + '/decide', {
|
|
2278
|
+
method: 'POST',
|
|
2279
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2280
|
+
body: JSON.stringify({ decision: decision, actor: 'dashboard' })
|
|
2281
|
+
});
|
|
2282
|
+
await loadAgentApprovals();
|
|
2283
|
+
} catch (e) { console.error('Agent approval decision failed:', e); }
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2211
2286
|
// ---- Routing Policy Editor ----
|
|
2212
2287
|
function toggleRoutingPolicy() {
|
|
2213
2288
|
routingPolicyVisible = !routingPolicyVisible;
|
|
@@ -2383,7 +2458,7 @@ async function refresh() {
|
|
|
2383
2458
|
if (refreshCount === 1 || forceFull) await refreshAgentRegistry();
|
|
2384
2459
|
await loadTasks(forceFull);
|
|
2385
2460
|
renderReviewQueue();
|
|
2386
|
-
await Promise.all([loadPresence(), loadChat(forceFull), loadActivity(forceFull), loadResearch(), loadSharedArtifacts(), loadHealth(), loadReleaseStatus(forceFull), loadBuildInfo(), loadRuntimeTruthCard(), loadApprovalQueue(), loadFeedback(), loadPauseStatus(), loadIntensityControl(), loadPolls()]);
|
|
2461
|
+
await Promise.all([loadPresence(), loadChat(forceFull), loadActivity(forceFull), loadResearch(), loadSharedArtifacts(), loadHealth(), loadReleaseStatus(forceFull), loadBuildInfo(), loadRuntimeTruthCard(), loadApprovalQueue(), loadAgentApprovals(), loadFeedback(), loadPauseStatus(), loadIntensityControl(), loadPolls()]);
|
|
2387
2462
|
await renderPromotionSSOT();
|
|
2388
2463
|
}
|
|
2389
2464
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Design Tokens — Platform Mapping
|
|
2
|
+
|
|
3
|
+
Source of truth: `/public/design-tokens.css`
|
|
4
|
+
|
|
5
|
+
## iOS (Swift)
|
|
6
|
+
|
|
7
|
+
```swift
|
|
8
|
+
// Colors.swift — auto-generate from design-tokens.css
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
extension Color {
|
|
12
|
+
static let brandPrimary = Color(hex: "#7C3AED")
|
|
13
|
+
static let brandPrimaryLight = Color(hex: "#A78BFA")
|
|
14
|
+
static let brandPrimaryDark = Color(hex: "#5B21B6")
|
|
15
|
+
|
|
16
|
+
// Canvas states
|
|
17
|
+
static let stateFloor = Color(hex: "#1F2937")
|
|
18
|
+
static let stateListening = Color(hex: "#7C3AED")
|
|
19
|
+
static let stateThinking = Color(hex: "#6366F1")
|
|
20
|
+
static let stateRendering = Color(hex: "#8B5CF6")
|
|
21
|
+
static let stateAmbient = Color(hex: "#374151")
|
|
22
|
+
static let stateDecision = Color(hex: "#F59E0B")
|
|
23
|
+
static let stateUrgent = Color(hex: "#EF4444")
|
|
24
|
+
static let stateHandoff = Color(hex: "#10B981")
|
|
25
|
+
|
|
26
|
+
// Trust
|
|
27
|
+
static let trustActive = Color(hex: "#F87171") // Red 400 — visible without alarming
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Dimensions.swift
|
|
31
|
+
enum Dimension {
|
|
32
|
+
static let tapTargetMin: CGFloat = 44
|
|
33
|
+
static let tapTargetUrgent: CGFloat = 52
|
|
34
|
+
static let orbSizeIdle: CGFloat = 64
|
|
35
|
+
static let orbSizeTranscript: CGFloat = 44
|
|
36
|
+
static let trustIndicatorSize: CGFloat = 10
|
|
37
|
+
static let overrideBarHeight: CGFloat = 52
|
|
38
|
+
static let presenceDotSize: CGFloat = 8
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Animation.swift
|
|
42
|
+
enum Timing {
|
|
43
|
+
static let fast: Double = 0.15
|
|
44
|
+
static let base: Double = 0.25
|
|
45
|
+
static let slow: Double = 0.35
|
|
46
|
+
static let canvas: Double = 0.5
|
|
47
|
+
static let orbGlow: Double = 1.8
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Android (Kotlin)
|
|
52
|
+
|
|
53
|
+
```xml
|
|
54
|
+
<!-- colors.xml -->
|
|
55
|
+
<color name="brand_primary">#FF7C3AED</color>
|
|
56
|
+
<color name="brand_primary_light">#FFA78BFA</color>
|
|
57
|
+
<color name="brand_primary_dark">#FF5B21B6</color>
|
|
58
|
+
|
|
59
|
+
<color name="state_floor">#FF1F2937</color>
|
|
60
|
+
<color name="state_listening">#FF7C3AED</color>
|
|
61
|
+
<color name="state_thinking">#FF6366F1</color>
|
|
62
|
+
<color name="state_rendering">#FF8B5CF6</color>
|
|
63
|
+
<color name="state_ambient">#FF374151</color>
|
|
64
|
+
<color name="state_decision">#FFF59E0B</color>
|
|
65
|
+
<color name="state_urgent">#FFEF4444</color>
|
|
66
|
+
<color name="state_handoff">#FF10B981</color>
|
|
67
|
+
|
|
68
|
+
<color name="trust_active">#FFF87171</color> <!-- Red 400 -->
|
|
69
|
+
|
|
70
|
+
<!-- dimens.xml -->
|
|
71
|
+
<dimen name="tap_target_min">44dp</dimen>
|
|
72
|
+
<dimen name="tap_target_urgent">52dp</dimen>
|
|
73
|
+
<dimen name="orb_size_idle">64dp</dimen>
|
|
74
|
+
<dimen name="orb_size_transcript">44dp</dimen>
|
|
75
|
+
<dimen name="trust_indicator_size">10dp</dimen>
|
|
76
|
+
<dimen name="override_bar_height">52dp</dimen>
|
|
77
|
+
<dimen name="presence_dot_size">8dp</dimen>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```kotlin
|
|
81
|
+
// Timing.kt
|
|
82
|
+
object Timing {
|
|
83
|
+
const val FAST = 150L
|
|
84
|
+
const val BASE = 250L
|
|
85
|
+
const val SLOW = 350L
|
|
86
|
+
const val CANVAS = 500L
|
|
87
|
+
const val ORB_GLOW = 1800L
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Important Notes
|
|
92
|
+
|
|
93
|
+
**Canvas state colors are tint references, not solid fills.** The spec uses these as radial gradient tints. Platform implementations should apply them as gradient bases, not flat backgrounds. For v0 surfaces using solid fills, these values are acceptable approximations.
|
|
94
|
+
|
|
95
|
+
**Trust indicator uses red-400 (#F87171)** — deliberately lighter than error red. Present and visible without being alarming. Both-sensors escalates to red-500 (#EF4444).
|
|
96
|
+
|
|
97
|
+
## Token Categories
|
|
98
|
+
|
|
99
|
+
| Category | Count | Notes |
|
|
100
|
+
|----------|-------|-------|
|
|
101
|
+
| Brand colors | 4 | Purple family |
|
|
102
|
+
| Semantic colors | 8 | Success/warning/error/info + backgrounds |
|
|
103
|
+
| Canvas states | 8 | Maps to state machine spec |
|
|
104
|
+
| Trust | 4 | Mic/camera indicators |
|
|
105
|
+
| Surface/bg | 6 | Light + dark mode |
|
|
106
|
+
| Text | 6 | Primary through inverse |
|
|
107
|
+
| Borders | 4 | Default/hover/focus/error |
|
|
108
|
+
| Typography | 14 | Font family, size, weight, line-height |
|
|
109
|
+
| Spacing | 12 | 0–64px scale |
|
|
110
|
+
| Radius | 6 | 4px–full |
|
|
111
|
+
| Shadows | 6 | sm through glow |
|
|
112
|
+
| Transitions | 9 | Duration + easing |
|
|
113
|
+
| Z-index | 8 | Layering scale |
|
|
114
|
+
| Interactive | 3 | Tap targets + focus ring |
|
|
115
|
+
| Canvas/orb | 5 | Orb dimensions + glow |
|
|
116
|
+
| Override bar | 3 | Height/bg/blur |
|
|
117
|
+
| Presence | 3 | Dot states |
|
|
118
|
+
| **Total** | **~105** | |
|