From 9c806c4b09892703f0d7e6477dfc00b2afee1fc3 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN Date: Thu, 1 Oct 2026 03:32:49 -0400 Subject: [PATCH] TASK-console-attention-actions: respect live role and authority evidence --- ...e-attention-integrity-report-2026-10-01.md | 5 +++ site/attention-projection.js | 44 +++++++++---------- site/console.js | 4 +- test/fleet/console-attention.test.mjs | 33 ++++++++++++-- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/reports/test-audit/console-attention-integrity-report-2026-10-01.md b/reports/test-audit/console-attention-integrity-report-2026-10-01.md index 390e0f5..7c6c4d8 100644 --- a/reports/test-audit/console-attention-integrity-report-2026-10-01.md +++ b/reports/test-audit/console-attention-integrity-report-2026-10-01.md @@ -24,12 +24,17 @@ test_integrity_note: given: "Approval evidence is unavailable and no queue or doctor finding is observed" when: "Attention items are projected" then: "No synthetic owner decision or operational issue is created" + - id: SCN-console-attention-authority + given: "Integration records may name a manager as authorizer while other runtime records lack an arbiter grant" + when: "Attention ownership is projected from the live roster" + then: "Roster titles supply display names, integration remains Fleet handling, and no arbiter-only authority is inferred" observable_outcomes: - "Attention groups distinguish owner decisions, Fleet work, and arbiter work" - "Approval action ownership follows the named approver" - "Repeated message queue evidence produces one item" - "Worktree progress and unsafe Git state have distinct descriptions" - "Unknown evidence stays explicit rather than gaining an invented owner" + - "Manager-authorized integration is not mislabeled as an owner or arbiter decision" determinism_controls: - "Tests pass fixed in-memory snapshots; no clock, network, or filesystem is consulted" anti_cheat_rationale: diff --git a/site/attention-projection.js b/site/attention-projection.js index 77618f6..54c27e1 100644 --- a/site/attention-projection.js +++ b/site/attention-projection.js @@ -1,12 +1,5 @@ (function (global) { const shortCommit = (value) => value ? String(value).slice(0, 9) : '—'; -const ownerDomainNames = { - 'release-self-host': 'Release and Self-host', - 'work-integration': 'Work and Integration', - 'project-kernel': 'Project Kernel', - 'session-manager': 'Session Manager', -}; - function worktreeProblemLabel(problem) { if (problem === 'worktree-dirty') return 'Uncommitted changes are present'; if (problem === 'worktree-missing') return 'The managed worktree is missing'; @@ -19,7 +12,7 @@ function worktreeProblemLabel(problem) { function attentionGroups(snapshot) { const groups = { owner: [], fleet: [], arbiter: [] }; const agents = new Map((snapshot.agents ?? []).map((agent) => [agent.areaId, agent])); - const agentName = (id) => ownerDomainNames[id] ?? agents.get(id)?.title ?? id ?? 'Owner not recorded'; + const agentName = (id) => agents.get(id)?.title ?? id ?? 'Owner not recorded'; const add = (group, item) => groups[group].push(item); const approvals = (snapshot.approvalRequests?.items ?? []).filter((approval) => approval.status === 'pending'); @@ -31,6 +24,7 @@ function attentionGroups(snapshot) { owner: isOwner ? 'Project owner' : agentName(approval.approver), detail: `${agentName(approval.requester)} is waiting on ${isOwner ? 'your decision' : agentName(approval.approver)}. ${approval.summary || 'Request consequence and options are not recorded.'}`, evidence: [approval.task, approval.evidence].filter(Boolean).join(' · ') || 'Request evidence not recorded', + waitSince: approval.createdAt ?? null, href: `#approval-${encodeURIComponent(approval.id)}`, action: isOwner ? 'Review request and evidence' : 'Open approval details', }); @@ -73,7 +67,7 @@ function attentionGroups(snapshot) { tone: !hasUnsafeProblem ? 'info' : item.problems.some((problem) => problem.startsWith('git-operation:') || problem === 'worktree-missing') ? 'urgent' : 'review', title: !hasUnsafeProblem ? `${identity} has work ahead of main` : `${identity} worktree needs review`, owner: identity, - detail: `${labels.join('; ')}.${hasAhead ? ' Ahead commits are retained work progress, not a broken repository.' : ''} ${hasUnsafeProblem ? 'Review the exact worktree before deciding on recovery.' : 'Ask the owner to review a safe convergence plan.'}`, + detail: `${labels.join('; ')}.${hasAhead ? ' Ahead commits are retained work progress, not a broken repository.' : ''} ${hasUnsafeProblem ? 'Review the exact worktree before deciding on recovery.' : 'Ask the owning specialist or manager to review a safe convergence plan.'}`, evidence: [worktree?.branch, worktree?.path ?? item.path, worktree?.ahead != null ? `${worktree.ahead} ahead / ${worktree.behind ?? 0} behind` : null].filter(Boolean).join(' · ') || 'Branch and path not recorded', href: `#worktree-${encodeURIComponent(item.area)}`, action: 'Inspect this worktree', requestOwner: item.area !== 'unknown-owner' ? item.area : null, @@ -88,7 +82,7 @@ function attentionGroups(snapshot) { : finding.code.replaceAll('_', ' ').toLowerCase().replace(/^./, (letter) => letter.toUpperCase()); add('fleet', { tone: finding.severity === 'error' ? 'urgent' : 'review', title: humanTitle, - owner: recoveryGap ? 'Release and Self-host' : finding.area ? agentName(finding.area) : 'Responsible domain not recorded', + owner: finding.area ? agentName(finding.area) : 'Responsible domain not recorded', detail: recoveryGap ? `${finding.recommendation ?? 'Configure and synchronize an off-machine canonical Git boundary.'} A single disk failure could remove the only recorded recovery copy.` : finding.message ?? finding.recommendation ?? 'Review this condition with the responsible domain; its consequence is not recorded.', @@ -105,25 +99,31 @@ function attentionGroups(snapshot) { }); const waitingIntegration = (snapshot.integration ?? []).filter((item) => !['landed', 'rejected', 'superseded'].includes(item.state)); - for (const item of waitingIntegration) add('arbiter', { - tone: 'review', title: `Integration ${item.state}`, owner: 'Session Manager / integration authority', - detail: 'Landing is serialized. The arbiter must check the exact candidate and required receipts before proceeding.', - evidence: `${item.sourceArea} · ${shortCommit(item.sourceCommit)} · ${item.reason ?? 'reason not recorded'}`, + for (const item of waitingIntegration) add('fleet', { + tone: 'review', title: `Integration ${item.state}`, owner: item.authorizedBy ? agentName(item.authorizedBy) : 'Integration authority not recorded', + detail: 'Review the exact candidate and required receipts under the current named landing authority. Queue state does not establish that a separate owner decision is required.', + evidence: [item.sourceArea, shortCommit(item.sourceCommit), item.authorizedBy ? `authorized by ${agentName(item.authorizedBy)}` : null, item.reason ?? 'reason not recorded'].filter(Boolean).join(' · '), href: '#delivery', action: 'Inspect integration queue', }); const unknownWakes = snapshot.managerWakes?.blockingCount ?? 0; - if (unknownWakes) add('arbiter', { - tone: 'urgent', title: `${unknownWakes} manager launch${unknownWakes === 1 ? '' : 'es'} need inspection`, - owner: 'Session Manager', detail: 'An unknown launch blocks another scheduled wake. Inspect recorded runtime evidence; no automatic restart is available.', - evidence: 'A reserved launch does not prove the provider is still running.', - href: '#manager-wakes', action: 'Inspect manager launches', - }); + if (unknownWakes) { + const reservations = (snapshot.managerWakes?.reservations ?? []).filter((item) => item.blocksManagerWake); + const wakeOwners = [...new Set(reservations.map((item) => agentName(item.managerId)))]; + add('fleet', { + tone: 'urgent', title: `${unknownWakes} scheduled manager wake${unknownWakes === 1 ? '' : 's'} need inspection`, + owner: wakeOwners.join(', ') || 'Scheduled wake owner not recorded', + detail: 'A recorded reservation blocks another wake. Inspect current runtime evidence before acting; this record does not prove a provider is still running or establish who may restart it.', + evidence: reservations.map((item) => [item.scheduleId, item.reservedAt, item.outcome].filter(Boolean).join(' · ')).join('; ') || 'Reservation detail unavailable', + href: '#manager-wakes', action: 'Inspect manager launches', + }); + } const unresolvedDelivery = (snapshot.deliveryOperations ?? []).filter((operation) => ['running', 'unknown', 'succeeded'].includes(operation.state)); - if (unresolvedDelivery.length) add('arbiter', { + if (unresolvedDelivery.length) add('fleet', { tone: 'urgent', title: `${unresolvedDelivery.length} delivery operation${unresolvedDelivery.length === 1 ? '' : 's'} need review`, - owner: 'Release and Self-host', detail: 'Inspect recorded attempts and external state before considering recovery. Do not repeat effects automatically.', + owner: [...new Set(unresolvedDelivery.map((operation) => operation.actor ? agentName(operation.actor) : 'Operation owner not recorded'))].join(', '), + detail: 'Inspect recorded attempts and external state before considering recovery. Do not repeat effects automatically.', evidence: unresolvedDelivery.map((operation) => `${operation.operation} · ${operation.state} · ${shortCommit(operation.commit)}`).join('; '), href: '#operation-outcomes', action: 'Inspect operation outcomes', }); diff --git a/site/console.js b/site/console.js index baf16e9..d502b4c 100644 --- a/site/console.js +++ b/site/console.js @@ -732,7 +732,7 @@ function renderAttention(groups) { const definitions = [ ['owner', 'Waiting on you', 'Only requests that name the project owner as decision-maker.'], ['fleet', 'Fleet handling', 'A named domain owns the next step; unknown ownership stays explicit.'], - ['arbiter', 'Arbiter handling', 'Serialized execution and installation decisions stay with the arbiter.'], + ['arbiter', 'Arbiter handling', 'No observed item has structured evidence assigning its next step exclusively to an arbiter.'], ]; const total = Object.values(groups).reduce((sum, items) => sum + items.length, 0); setText('#attention-count', `${total} ${total === 1 ? 'item' : 'items'}`); @@ -743,7 +743,7 @@ function renderAttention(groups) { ${items.length ? items.map((item) => `
${escapeHtml(item.title)}

${escapeHtml(item.detail)}

- Severity: ${escapeHtml(({ urgent: 'Urgent', review: 'Review', decision: 'Decision required', info: 'Progress' })[item.tone] ?? 'Unknown')} · Owner: ${escapeHtml(item.owner)} · ${escapeHtml(item.evidence)} + Severity: ${escapeHtml(({ urgent: 'Urgent', review: 'Review', decision: 'Decision required', info: 'Progress' })[item.tone] ?? 'Unknown')} · Owner: ${escapeHtml(item.owner)}${item.waitSince ? ` · Waiting ${escapeHtml(ageLabel(item.waitSince))}` : ''} · ${escapeHtml(item.evidence)} ${escapeHtml(item.action)} ${item.requestOwner ? `Request review from ${escapeHtml(item.owner)}` : ''}
`).join('') : `

${escapeHtml(description)}

`} diff --git a/test/fleet/console-attention.test.mjs b/test/fleet/console-attention.test.mjs index 3f3e266..0355af4 100644 --- a/test/fleet/console-attention.test.mjs +++ b/test/fleet/console-attention.test.mjs @@ -12,7 +12,7 @@ test('SCN-console-attention-ownership: only owner-addressed pending decisions en ], approvalRequests: { items: [ { id: 'owner-review', status: 'pending', approver: 'owner', requester: 'provider-runtime', - title: 'Review executor boundary', task: 'TASK-RUNTIME', evidence: 'receipt:17', summary: 'Confirm the bounded scope.' }, + title: 'Review executor boundary', task: 'TASK-RUNTIME', evidence: 'receipt:17', createdAt: '2026-10-01T06:00:00Z', summary: 'Confirm the bounded scope.' }, { id: 'qa-review', status: 'pending', approver: 'qa', requester: 'owner-console', title: 'Confirm scenario path', summary: 'Review the owned test path.' }, ] }, @@ -21,6 +21,7 @@ test('SCN-console-attention-ownership: only owner-addressed pending decisions en assert.deepEqual(groups.owner.map((item) => item.title), ['Review executor boundary']); assert.equal(groups.owner[0].href, '#approval-owner-review'); assert.match(groups.owner[0].detail, /bounded scope/); + assert.equal(groups.owner[0].waitSince, '2026-10-01T06:00:00Z'); assert.equal(groups.fleet[0].owner, 'Independent QA'); assert.equal(groups.fleet[0].action, 'Open approval details'); assert.doesNotMatch(JSON.stringify(groups.fleet), /Approve|Reject/); @@ -47,20 +48,25 @@ test('SCN-console-attention-worktrees: findings group by owning area and disting doctor: { findings: [ { severity: 'warning', code: 'WORKTREE_PROBLEM', area: 'provider-runtime', path: '/work/provider', problem: 'unique-commits:2' }, { severity: 'warning', code: 'WORKTREE_PROBLEM', areaId: 'provider-runtime', path: '/work/provider', problem: 'worktree-dirty' }, + { severity: 'warning', code: 'WORKTREE_PROBLEM', area: 'project-kernel', path: '/work/kernel', problem: 'unique-commits:1' }, { severity: 'error', code: 'WORKTREE_PROBLEM', area: 'qa', path: '/work/qa', problem: 'git-operation:REBASE_HEAD' }, ] }, worktrees: [ { area: 'provider-runtime', branch: 'runtime/fix', path: '/work/provider', ahead: 2, behind: 0 }, + { area: 'project-kernel', branch: 'kernel/change', path: '/work/kernel', ahead: 1, behind: 0 }, { area: 'qa', branch: 'qa/audit', path: '/work/qa', ahead: 0, behind: 0 }, ], }); - assert.equal(groups.fleet.length, 2); + assert.equal(groups.fleet.length, 3); const runtime = groups.fleet.find((item) => item.owner === 'Provider Runtime'); assert.equal(runtime.tone, 'review'); - assert.match(runtime.detail, /retained work progress, not a broken repository/); + assert.match(runtime.detail, /Ahead commits are retained work progress, not a broken repository/); assert.match(runtime.evidence, /runtime\/fix · \/work\/provider/); assert.equal(runtime.requestOwner, 'provider-runtime'); + const kernel = groups.fleet.find((item) => item.owner === 'project-kernel'); + assert.equal(kernel.tone, 'info'); + assert.match(kernel.detail, /owning specialist or manager/); const qa = groups.fleet.find((item) => item.owner === 'qa'); assert.equal(qa.tone, 'urgent'); assert.match(qa.title, /worktree needs review/); @@ -76,12 +82,31 @@ test('SCN-console-attention-wait-reasons: recovery and blocked task evidence kee }); const recovery = groups.fleet.find((item) => item.title === 'Off-machine recovery copy is not verified'); - assert.equal(recovery.owner, 'Release and Self-host'); + assert.equal(recovery.owner, 'Responsible domain not recorded'); assert.match(recovery.detail, /single disk failure could remove/); assert.match(recovery.evidence, /ONE-DISK · abcdef012/); assert.match(groups.fleet.find((item) => item.evidence === 'TASK-BLOCKED').detail, /no image was saved/); }); +test('SCN-console-attention-authority: roster titles name owners and integration stays with Fleet unless arbiter authority is explicit', () => { + const groups = project({ + agents: [{ areaId: 'coordinator-7', title: 'Delivery Coordinator' }], + integration: [ + { state: 'awaiting-checks', sourceArea: 'build-team', sourceCommit: '1234567890abcdef', authorizedBy: 'coordinator-7' }, + { state: 'queued', sourceArea: 'docs-team', sourceCommit: 'abcdef0123456789' }, + ], + managerWakes: { blockingCount: 1, reservations: [{ managerId: 'coordinator-7', scheduleId: 'nightly-review', + outcome: 'reserved', blocksManagerWake: true }] }, + }); + + assert.equal(groups.fleet.length, 3); + assert.equal(groups.fleet[0].owner, 'Delivery Coordinator'); + assert.match(groups.fleet[0].evidence, /authorized by Delivery Coordinator/); + assert.equal(groups.fleet[1].owner, 'Integration authority not recorded'); + assert.equal(groups.fleet[2].owner, 'Delivery Coordinator'); + assert.deepEqual(groups.arbiter, []); +}); + test('SCN-console-attention-empty: an unavailable signal does not manufacture owner work', () => { const groups = project({ approvalRequests: { available: false, reason: 'Structured approval service unavailable.' },