Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/scripts/discover.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ const CONTRACT_SCHEMA_VERSION = '1.0.0';
/* Three committed goals — a structured Spec-113 target + starting facts each.
No natural language: the target is an exact capability identity. */
const GOALS = [
{
id: 'docapproval',
label: 'Review a document for approval',
blurb: 'From the document text alone the planner chains doc-approval.analyze (extract type, parties, amounts, a confidence) into doc-approval.recommend (approve or route, with a rationale).',
kind: 'chain',
target: { capability_id: 'doc-approval.recommend', capability_version: '1.4.0' },
candidate_refs: [
{ namespace: 'doc-approval', id: 'doc-approval.analyze', versionRange: '1.4.0' },
{ namespace: 'doc-approval', id: 'doc-approval.recommend', versionRange: '1.4.0' },
],
starting_facts: {
document: 'INVOICE\nVendor: Acme Corp\nBill to: Globex Industries\nInvoice #: AC-20481\nTotal due: $4,200.00\nDue date: 2026-10-01\nTerms: Net 30',
},
},
{
id: 'price',
label: 'Price a quote',
Expand All @@ -38,20 +52,6 @@ const GOALS = [
},
},
},
{
id: 'docapproval',
label: 'Review a document for approval',
blurb: 'From the document text alone the planner chains doc-approval.analyze (extract type, parties, amounts, a confidence) into doc-approval.recommend (approve or route, with a rationale).',
kind: 'chain',
target: { capability_id: 'doc-approval.recommend', capability_version: '1.4.0' },
candidate_refs: [
{ namespace: 'doc-approval', id: 'doc-approval.analyze', versionRange: '1.4.0' },
{ namespace: 'doc-approval', id: 'doc-approval.recommend', versionRange: '1.4.0' },
],
starting_facts: {
document: 'INVOICE\nVendor: Acme Corp\nBill to: Globex Industries\nInvoice #: AC-20481\nTotal due: $4,200.00\nDue date: 2026-10-01\nTerms: Net 30',
},
},
{
id: 'luhn',
label: 'Check a card number',
Expand Down
29 changes: 20 additions & 9 deletions tests/e2e/discover.spec.mjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import { test, expect } from '@playwright/test';

test('goal 1 auto-plans on load, then review + execute for real against the live registry', async ({ page }) => {
test('goal 1 (doc-approval chain) auto-plans on load, then review + execute for real against the live registry', async ({ page }) => {
test.slow(); // fetches the live catalog + prepares artifacts

await page.goto('/discover.html');

// Auto-run to the review gate.
await expect(page.locator('#discover-badge')).toHaveText('Planned — review the mappings', { timeout: 45_000 });
await expect(page.locator('#discover-plan-target')).toHaveText('core.calculate-price@1.2.0');
await expect(page.locator('#discover-plan-target')).toHaveText('doc-approval.recommend@1.4.0');
await expect(page.locator('#discover-plan-mappings')).toContainText('unconfirmed');
await expect(page.locator('#discover-stats')).toContainText('namespaces');

// Explicit review gate → real composed execution.
// Explicit review gate → real composed execution of the two-node chain.
await page.locator('#discover-exec').click();
await expect(page.locator('#discover-badge')).toHaveText('Executed — real, offline, governed', { timeout: 45_000 });
await expect(page.locator('#discover-result')).toHaveAttribute('data-outcome', 'executed');
await expect(page.locator('#discover-trace')).toContainText('terminal: succeeded');
await expect(page.locator('#discover-trace')).toContainText('core.calculate-price@1.2.0');
await expect(page.locator('#discover-trace')).toContainText('doc-approval.analyze@1.4.0');
await expect(page.locator('#discover-trace')).toContainText('doc-approval.recommend@1.4.0');
await expect(page.locator('#discover-log')).toContainText('executed offline in your browser');
});

test('a single-capability goal (price a quote) plans and executes for real', async ({ page }) => {
test.slow();
await page.goto('/discover.html');
await expect(page.locator('#discover-badge')).toHaveText('Planned — review the mappings', { timeout: 45_000 });

await page.locator('.discover-goal[data-goal="price"]').click();
await expect(page.locator('#discover-plan-target')).toHaveText('core.calculate-price@1.2.0', { timeout: 45_000 });
await expect(page.locator('#discover-badge')).toHaveText('Planned — review the mappings');

await page.locator('#discover-exec').click();
await expect(page.locator('#discover-badge')).toHaveText('Executed — real, offline, governed', { timeout: 45_000 });
await expect(page.locator('#discover-trace')).toContainText('terminal: succeeded');
await expect(page.locator('#discover-trace')).toContainText('core.calculate-price@1.2.0');
});

test('a single-capability goal (card checksum) plans and executes for real', async ({ page }) => {
test.slow();
await page.goto('/discover.html');
Expand All @@ -34,8 +50,3 @@ test('a single-capability goal (card checksum) plans and executes for real', asy
await expect(page.locator('#discover-trace')).toContainText('terminal: succeeded');
await expect(page.locator('#discover-trace')).toContainText('validation.validate-luhn@1.2.0');
});

// The "Review a document for approval" goal (doc-approval.analyze -> doc-approval.recommend)
// plans today but only *executes* once doc-approval.analyze@1.4.0 / recommend@1.4.0 land
// on the live catalog with a pure_read risk class (traverse-framework/registry#424, #425).
// Add its plan+execute spec once those merge.
Loading