@nullsquare/agent-authority 0.4.5 → 0.4.6

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/ROADMAP.md CHANGED
@@ -1,26 +1,64 @@
1
1
  # Agent Authority Roadmap
2
2
 
3
- Agent Authority is implementation-first. We are not trying to invent a new authentication protocol or policy language.
3
+ Agent Authority is implementation-first, but the current bottleneck is now **product proof**, not another authorization subsystem.
4
4
 
5
- The product thesis we are validating is:
5
+ The product thesis is:
6
6
 
7
7
  > **Give an agent a task, not standing account permissions.**
8
8
 
9
- A human-approved task becomes temporary execution authority. As the agent discovers concrete resources through authorized work, authority may follow those resources through provenance-bound facts, but it may never silently broaden.
9
+ The differentiated mechanism is:
10
10
 
11
- ## Current invariant
11
+ > **Authority may follow exact resources discovered through already-authorized execution, without becoming ambient account authority.**
12
+
13
+ ## Core invariant
12
14
 
13
15
  ```text
14
16
  Task Lease authority <= Mission authority
15
17
  ```
16
18
 
17
- Across delegation and integrations:
19
+ Across delegation, transports and durable state:
18
20
 
19
21
  ```text
20
22
  authority may stay the same or shrink
21
23
  never silently grow
22
24
  ```
23
25
 
26
+ ## P0 — Task-first product proof — current priority
27
+
28
+ The engine has enough depth to test whether developers actually want this layer. Product work now outranks additional distributed/crypto infrastructure unless a real workflow proves the missing infrastructure is blocking adoption or safety.
29
+
30
+ - [x] task-first facade over Mission + Task Lease + Guard
31
+ - [x] explicit service permissions without requiring hand-authored Mission JSON
32
+ - [x] named task authority roots
33
+ - [x] `task.run()` guarded effect boundary
34
+ - [x] `task.authorityFrom()` strict evidence-derived authority
35
+ - [x] task-first binding of named authority to later effects
36
+ - [x] human-readable authority-delta explanation
37
+ - [x] same task-first calls can opt into durable local state by adding a store
38
+ - [x] self-contained GitHub-shaped task-first demo
39
+ - [x] deterministic utility regression benchmark
40
+ - [ ] coding workflow: issue -> branch -> files -> PR, with merge/deploy outside authority
41
+ - [ ] support/communications workflow: email -> customer -> meeting/CRM/reply target
42
+ - [ ] operations/finance workflow: ticket -> order -> payment -> bounded refund
43
+ - [ ] first-time developer can complete a meaningful integration in under 10 minutes
44
+ - [ ] at least one external developer adopts the package without project-author assistance
45
+
46
+ Current utility regression metrics:
47
+
48
+ ```text
49
+ normal task completion rate
50
+ false approval rate
51
+ true authority-delta step-up rate
52
+ unauthorized effect rate
53
+ provider effects per completed task
54
+ ```
55
+
56
+ The deterministic fixture target is 100% normal completion, 0% false approvals, 100% true-delta step-up and 0% unauthorized effects. It is a regression fixture, not a real-world benchmark.
57
+
58
+ See `docs/product-proof.md`.
59
+
60
+ **Product gate:** do not prioritize deeper distributed persistence, provider-attestation protocols, new token formats, broad OAuth platform work, A2A, a policy DSL, another MCP control plane, or connector-count expansion until the product proof moves or a concrete workflow shows one of those items is necessary.
61
+
24
62
  ## M0 — Enforcement foundation — complete
25
63
 
26
64
  - [x] mission validation
@@ -31,7 +69,7 @@ never silently grow
31
69
  - [x] delegation attenuation
32
70
  - [x] mission revocation
33
71
  - [x] action receipts and request hashes
34
- - [x] protocol-neutral `guard.run()` enforcement
72
+ - [x] protocol-neutral guard enforcement
35
73
  - [x] one-time approvals
36
74
  - [x] mutation idempotency
37
75
  - [x] short-lived local agent-instance auth
@@ -41,143 +79,128 @@ never silently grow
41
79
  - [x] harness-managed connector grant proof
42
80
  - [x] Node 20/22 CI, coverage, package checks and CodeQL
43
81
 
44
- ## M1 — Task Lease / derived-authority proof — current
82
+ ## M1 — Task Lease / derived-authority proof — implementation established
45
83
 
46
- - [x] Task Lease object around an existing mission
84
+ - [x] Task Lease around an existing Mission
47
85
  - [x] explicit authority roots
48
- - [x] derived facts anchored to same-mission `ALLOW` receipts
86
+ - [x] derived facts anchored to same-Mission ALLOW receipts
49
87
  - [x] parent-fact lineage
50
88
  - [x] exact context-field bindings
51
89
  - [x] unresolved facts fail closed
52
- - [x] resource mismatch becomes an authority-delta step-up signal
53
- - [x] explicit mission deny remains the ceiling
90
+ - [x] resource mismatch becomes an authority-delta step-up
91
+ - [x] explicit Mission deny remains the ceiling
54
92
  - [x] task completion immediately removes authority
55
- - [x] independent task-lease expiry
56
- - [x] task-lease ID/hash in receipts
57
- - [x] self-contained cross-system demo: Gmail-thread fact -> Calendar attendee
58
- - [x] reusable Google REST adapter for Gmail thread reads and Calendar event mutations
59
- - [x] adversarial Gmail -> Calendar test proving unrelated and post-completion effects never invoke provider callbacks
60
- - [x] real connected-account smoke: Gmail self-test fixture -> exact attendee -> temporary Calendar event -> cleanup
61
- - [ ] rerun the same proof as a public GitHub Actions job after repository Google OAuth secrets are configured
93
+ - [x] independent Task Lease expiry
94
+ - [x] Task Lease ID/hash in receipts
95
+ - [x] self-contained Gmail-thread -> Calendar-attendee demo
96
+ - [x] reusable Google Gmail/Calendar adapter
97
+ - [x] adversarial Gmail -> Calendar zero-provider-call tests
98
+ - [x] connected-account Gmail -> Calendar smoke proof
99
+ - [ ] public GitHub Actions Gmail -> Calendar proof after repository OAuth secrets are configured
62
100
 
63
- **Success criterion:** a real multi-step agent workflow discovers a resource during an authorized read and can use exactly that resource in a later side effect, while an unrelated resource is technically blocked without requiring approval for every normal task step.
101
+ **Success criterion:** an authorized read can establish exactly one later resource as task authority while an unrelated resource is technically blocked without requiring approval for every normal task step.
64
102
 
65
- The core cross-provider behavior is now implemented and exercised against connected Gmail and Calendar accounts. Public Actions reproducibility remains the final M1 evidence gate because GitHub cannot reuse an interactive ChatGPT connector credential; the manual workflow is committed and expects a refresh token stored only as repository secrets.
103
+ The implementation criterion is met. Public Actions reproducibility remains a separate evidence gate because the interactive Google connector credential cannot be reused as repository secrets.
66
104
 
67
- ## M2 — Durable task execution — durable session established
68
-
69
- Build only what the real Task Lease workflows prove necessary.
105
+ ## M2 — Durable task execution — local durable session established
70
106
 
71
107
  - [x] authenticated local Task Lease persistence/recovery
108
+ - [x] exact Mission-hash binding on recovery
72
109
  - [x] atomic authenticated fact/binding/status transaction primitive
73
- - [x] stale-writer compare-and-swap protection for independent recovered worker views
74
- - [x] local per-lease transaction lock that fails closed on overlap
75
- - [x] ordinary running Task Lease mutations can use the durable transaction boundary through `DurableTaskLeaseSession`
76
- - [x] security-critical session evaluation refreshes current durable state before the next authority decision
77
- - [ ] approved authority delta can safely attenuate/update a live lease
78
- - [x] completion state survives process restart
79
- - [ ] durable lineage query: why was this exact action authorized?
80
- - [ ] multi-process stress/recovery tests for multiple agent workers operating under one lease
81
- - [ ] crash-safe coupling between remote provider side effects, receipts and durable Task Lease state
82
-
83
- `JsonFileTaskLeaseStore` writes the complete lease snapshot atomically and authenticates it with a purpose-derived HMAC key from the local Agent Authority master key. Recovery verifies the envelope before authority hydration, binds the snapshot to the exact mission hash, validates status/timestamps and the authority-fact DAG, restores evidence-derived provenance hashes, and verifies the reconstructed Task Lease hash.
84
-
85
- `JsonFileTaskLeaseStore.transact()` is the local durable mutation boundary: acquire one per-lease filesystem lock, reload authenticated current state, compare an optional expected lease hash, apply one synchronous Task Lease mutation, validate the complete authority graph, and atomically replace the authenticated snapshot. Stale writers receive `task_lease_state_conflict`; overlapping local transactions receive `task_lease_state_locked`.
110
+ - [x] stale-writer compare-and-swap protection
111
+ - [x] local per-lease transaction lock
112
+ - [x] mission-alias hardening inside transactions
113
+ - [x] automatic durable Task Lease session
114
+ - [x] security-critical session refresh before authority evaluation
115
+ - [x] durable completion/expiry across restart
116
+ - [ ] approved authority delta safely updates a live durable task
117
+ - [ ] durable lineage query for one exact authorization decision
118
+ - [ ] stronger multi-process stress/recovery tooling
119
+ - [ ] crash-safe remote-effect/receipt/state coupling
86
120
 
87
- `DurableTaskLeaseSession` is the normal mutation facade over that primitive. `addRoot()`, legacy `derive()`, strict `deriveFromEvidence()`, `bind()` and `complete()` commit through compare-and-swap and update the session only after durable success. The session exposes detached mission/snapshot/fact views rather than its mutable internal Task Lease. It never auto-replays a stale semantic mutation after a conflict.
121
+ The existing local durability layer is sufficient for product proof. The unchecked items remain research/follow-on work unless a real workflow demonstrates that they block useful adoption or safety.
88
122
 
89
- The session also implements the Task Lease `evaluate(runtime, request)` shape used by guard/MCP/broker paths. Evaluation refreshes authenticated durable state first, so another worker's already-committed completion or narrowing is observed before the next decision. Tests also prove that execution evidence captured at H0 cannot be automatically converted into a derived fact after another worker commits H1; derivation fails on CAS and requires explicit reconsideration.
90
-
91
- This does **not** yet turn a remote provider side effect and a local Task Lease transition into one distributed transaction. A different worker can still change durable state after an ALLOW decision and before an asynchronous provider effect begins. That TOCTOU/effect-coupling problem remains explicit follow-on M2 work rather than being hidden behind the local filesystem lock. See `docs/durable-task-leases.md`.
92
-
93
- **Success criterion:** a Task Lease survives restart without gaining authority or losing provenance, cooperating local workers cannot silently overwrite newer authority, and ordinary durable mutations use the CAS boundary by default through the session API. Authenticated recovery, local transactions and the durable session are now demonstrated; approved deltas, stronger multi-process stress and remote-effect coupling remain open.
123
+ **Success criterion:** restart and cooperating local workers do not expand authority or silently overwrite newer task state. This is established for the reference local backend.
94
124
 
95
125
  ## M3 — Trustworthy derived facts — two-provider proof established
96
126
 
97
- The first real Gmail -> Calendar integration showed that recording a host-supplied value plus selector was too weak for the strongest derived-authority claim. The compatibility `derive()` path remains host-trusted; new provider work should prefer execution-bound evidence and reviewed adapter extractors.
98
-
99
- - [x] define a small trusted-adapter extractor contract for authority-relevant normalized provider fields
100
- - [x] bind successful guarded outputs to the exact ALLOW receipt, request and output hash
101
- - [x] add `TaskLease.deriveFromEvidence()` so the caller cannot provide the authority value
102
- - [x] migrate Gmail sender -> Calendar attendee derivation to the evidence-verified path
103
- - [x] migrate the real GitHub issue discovery -> comment mutation proof to the same evidence-verified path
104
- - [x] adversarial tests for value substitution, output/evidence tampering, receipt replay, cross-lease reuse, wrong-operation extraction and dangerous selectors
105
- - [x] shared conformance fixtures for reviewed operation -> authority-field mappings across Google and GitHub
106
- - [ ] define provider/result attestation stronger than a trusted host output hash where practical
107
- - [ ] define freshness/invalidation rules when a source resource changes
108
-
109
- The shared contract is documented in `docs/authority-extractor-conformance.md`. Google and GitHub now use the same `guard.run()` -> execution evidence -> reviewed extractor -> `deriveFromEvidence()` primitive, and the same conformance suite attacks both mappings.
127
+ - [x] reviewed adapter extractor contract
128
+ - [x] successful guarded output bound to exact ALLOW receipt/request/output hash
129
+ - [x] strict `deriveFromEvidence()` where caller cannot provide the authority value
130
+ - [x] Gmail sender -> Calendar attendee strict derivation
131
+ - [x] GitHub issue discovery -> comment strict derivation
132
+ - [x] substitution/tamper/replay/cross-lease/wrong-operation/dangerous-selector tests
133
+ - [x] shared Google/GitHub authority-extractor conformance fixtures
134
+ - [ ] stronger provider/result attestation where a real provider makes it practical
135
+ - [ ] source freshness/invalidation semantics where a real workflow requires it
110
136
 
111
- Do **not** build a general semantic policy language unless real integrations require it.
137
+ Do **not** build a general semantic policy language around this primitive.
112
138
 
113
- **Success criterion:** provider-derived authority cannot be established through the strict path unless the exact guarded output, ALLOW receipt and reviewed extractor contract agree on the selected value. This behavior is now exercised across two provider mappings. Stronger provider attestation and source invalidation remain separate follow-on problems.
139
+ **Success criterion:** strict provider-derived authority requires agreement between the exact guarded output, ALLOW receipt and reviewed extractor. This is demonstrated across Google and GitHub.
114
140
 
115
141
  ## M4 — Same task, multiple transports — complete
116
142
 
117
- Prove Agent Authority is not an MCP product or SDK wrapper.
118
-
119
- - [x] same Task Lease through ordinary `guard.run()` SDK call
143
+ - [x] same Task Lease through direct guard/SDK execution
120
144
  - [x] same Task Lease through MCP gateway
121
145
  - [x] same Task Lease through brokered provider execution
122
- - [x] at least one harness/tool-middleware integration whose configured executable tool path cannot bypass the Task Lease
123
- - [x] interoperability test vectors across transports
124
-
125
- `test/transport-invariance.test.js` establishes one `execution-evidence-v1` derived fact from brokered execution, then reuses that exact Task Lease and fact through direct SDK, MCP and brokered execution. The three paths produce the same `allow`, `authority_delta_required` and `task_lease_completed` outcomes, and blocked attempts execute zero host callbacks, MCP upstream calls or brokered provider operations.
126
-
127
- `test/integrations/ai-sdk.integration.mjs` drives the real Vercel AI SDK `ToolLoopAgent` through the protected tool set. An authorized task-bound tool executes once; an unrelated resource, an executable tool with no Agent Authority mapping, and a completed Task Lease are surfaced by the harness as `tool-error` results while the underlying side-effect counters remain zero. This proves the configured AI SDK tool execution path cannot silently bypass the Task Lease.
146
+ - [x] real Vercel AI SDK protected-tool path
147
+ - [x] interoperability/adversarial vectors across transports
128
148
 
129
- The harness claim is intentionally bounded: a malicious host that deliberately gives the model a separate unguarded executable channel remains outside Agent Authority's enforcement boundary.
149
+ Changing transport or configured harness execution path does not expand task authority in the demonstrated paths.
130
150
 
131
- Brokered Task Lease execution deliberately does not consume mission-level one-time approval to override a lease-level authority delta. Updating a live Task Lease after explicit approval remains separate M2 work.
151
+ ## M5 Adoption UX follows product proof, not infrastructure breadth
132
152
 
133
- **Success criterion:** changing transport or the configured harness execution path does not expand the task's authority. This is now demonstrated across direct SDK, MCP, brokered execution and the Vercel AI SDK `ToolLoopAgent` protected-tool path.
153
+ Prioritize only the UX needed by successful P0 workflows.
134
154
 
135
- ## M5 — Production credential and approval UX
136
-
137
- Only after the task-bound enforcement model is validated.
138
-
139
- - [ ] GitHub browser/App onboarding instead of token-stdin
140
- - [ ] reusable OAuth/OIDC connection engine
141
- - [ ] OS keychain / KMS-backed secret backend
142
- - [ ] automatic short-lived agent session bootstrap
143
155
  - [ ] compact approval UI showing the exact authority delta
144
- - [ ] signed receipt experiment
156
+ - [ ] one low-friction real provider onboarding path
157
+ - [ ] automatic short-lived agent session bootstrap where needed
158
+ - [ ] framework integration starter focused on task-first API
159
+ - [ ] external-developer quickstart feedback loop
145
160
 
146
- **Success criterion:** an external developer can install Agent Authority, connect one real provider, authorize one task, and complete it without exposing a long-lived credential to the model.
161
+ Items such as reusable OAuth/OIDC engines, KMS backends and signed-receipt experiments remain optional until product usage justifies them.
147
162
 
148
- ## M6 Ecosystem and contribution layer
163
+ **Success criterion:** an external developer can install Agent Authority, connect one real provider, authorize one meaningful task and complete it without exposing a long-lived credential to the model or learning the internal authority machinery first.
149
164
 
150
- - [ ] adapter/conformance starter template
151
- - [ ] framework integration examples
152
- - [ ] `good first issue` tasks based on real mappings/tests
153
- - [ ] independent contributor implementation of one adapter
154
- - [x] release packaging and npm publication
155
- - [ ] documentation site only when README/docs become too large
165
+ ## M6 Ecosystem only after repeatable adoption
156
166
 
157
- ## M7 Standards interoperability
167
+ - [ ] adapter/conformance starter template
168
+ - [ ] framework examples driven by real user requests
169
+ - [ ] good-first-issue tasks based on proven workflows
170
+ - [ ] independent contributor implementation of one mapping/adapter
171
+ - [x] npm release packaging and registry verification
172
+ - [ ] documentation site only when the current README/docs become genuinely limiting
158
173
 
159
- Only after operational evidence.
174
+ ## M7 — Standards interoperability only after operational evidence
160
175
 
161
176
  - [ ] map Task Lease concepts to emerging task/intent authorization work
162
177
  - [ ] accept external authorization envelopes where useful
163
178
  - [ ] avoid creating a competing identity/token standard
164
- - [ ] publish stable test vectors for non-amplification and authority lineage
165
- - [ ] evaluate an appropriate standards venue only if multiple independent implementations exist
166
-
167
- ## What we are not prioritizing
168
-
169
- - another agent harness
170
- - a new OAuth replacement
171
- - an MCP replacement
172
- - a giant connector marketplace
173
- - a proprietary universal policy DSL
174
- - a dashboard-first enterprise product
175
- - A2A support before task-bound tool execution is validated
179
+ - [ ] publish stable non-amplification/authority-lineage test vectors
180
+ - [ ] evaluate standards participation only after independent implementations/users exist
181
+
182
+ ## Freeze list
183
+
184
+ Unless a real workflow proves one is necessary now:
185
+
186
+ - distributed Task Lease databases
187
+ - generic storage abstraction layers
188
+ - provider-signed attestation protocol design
189
+ - new token or identity formats
190
+ - a general delegation protocol
191
+ - proprietary universal policy DSL
192
+ - broad OAuth platform work
193
+ - another MCP control plane
194
+ - A2A protocol implementation
195
+ - connector-count expansion for its own sake
196
+ - full distributed transactions across arbitrary remote providers
197
+ - dashboard-first enterprise product work
176
198
 
177
199
  ## Research questions
178
200
 
179
- 1. What provider-side or transport-side evidence can strengthen output integrity without turning Agent Authority into an attestation protocol?
180
- 2. How should an approved authority delta update a running task without opening a broader wildcard permission?
181
- 3. How should source-data changes invalidate downstream derived authority?
182
- 4. What provider/tool metadata is required to map operations to resource context reliably?
183
- 5. How should a local ALLOW decision be coupled to an asynchronous remote effect without holding a filesystem lease lock across network I/O?
201
+ 1. Can a first-time developer understand and integrate the task-first model in under 10 minutes?
202
+ 2. Which real workflows benefit enough from derived authority that an `if` statement is no longer sufficient?
203
+ 3. Where does Agent Authority create unnecessary approval friction or reduce useful task completion?
204
+ 4. How should an explicitly approved authority delta update a running task without opening wildcard authority?
205
+ 5. Which source-data changes actually require downstream authority invalidation in real workflows?
206
+ 6. What remote-effect coupling is necessary in practice, and which providers already offer idempotency/transaction primitives we can reuse instead of inventing our own protocol?
@@ -0,0 +1,130 @@
1
+ import { createTask } from '../src/task.js';
2
+ import { AuthorityApprovalRequiredError } from '../src/guard.js';
3
+
4
+ const NORMAL_TASKS = 40;
5
+ const DELTA_ATTACKS = 10;
6
+
7
+ function selectedItemExtractor({ receipt, output } = {}) {
8
+ if (receipt?.service !== 'demo' || receipt?.action !== 'item.discover') {
9
+ const error = new Error('wrong operation');
10
+ error.code = 'trusted_extractor_operation_mismatch';
11
+ throw error;
12
+ }
13
+ if (typeof output?.selected_item !== 'string') {
14
+ const error = new Error('invalid selected item');
15
+ error.code = 'trusted_extractor_output_invalid';
16
+ throw error;
17
+ }
18
+ return { extractor_id: 'benchmark.selected-item.v1', selector: 'output.selected_item' };
19
+ }
20
+
21
+ function newTask(index) {
22
+ const catalog = `catalog:${index}`;
23
+ return {
24
+ catalog,
25
+ task: createTask({
26
+ principal: 'user:benchmark',
27
+ agent: 'agent:benchmark',
28
+ request: `Discover and update the selected item for benchmark task ${index}`,
29
+ permissions: {
30
+ demo: {
31
+ allow: ['item.discover', 'item.update'],
32
+ deny: ['item.delete'],
33
+ constraints: { catalog: [catalog] }
34
+ }
35
+ },
36
+ authority: {
37
+ catalog: { kind: 'demo.catalog', value: catalog }
38
+ },
39
+ bindings: [
40
+ { service: 'demo', action: 'item.discover', field: 'catalog', authority: 'catalog' },
41
+ { service: 'demo', action: 'item.update', field: 'catalog', authority: 'catalog' }
42
+ ]
43
+ })
44
+ };
45
+ }
46
+
47
+ const metrics = {
48
+ normal_tasks: NORMAL_TASKS,
49
+ completed_normal_tasks: 0,
50
+ normal_approval_interruptions: 0,
51
+ delta_attacks: DELTA_ATTACKS,
52
+ delta_step_ups: 0,
53
+ unauthorized_effects: 0,
54
+ provider_effects: 0
55
+ };
56
+
57
+ for (let index = 0; index < NORMAL_TASKS; index += 1) {
58
+ const { task, catalog } = newTask(index);
59
+ const item = `item:${index}`;
60
+
61
+ const discovery = await task.run({
62
+ service: 'demo',
63
+ action: 'item.discover',
64
+ context: { catalog }
65
+ }, async () => {
66
+ metrics.provider_effects += 1;
67
+ return { selected_item: item };
68
+ });
69
+
70
+ task.authorityFrom(discovery, {
71
+ name: 'item',
72
+ kind: 'demo.item',
73
+ from: 'catalog',
74
+ extractor: selectedItemExtractor
75
+ });
76
+ task.bind({ service: 'demo', action: 'item.update', field: 'item', authority: 'item' });
77
+
78
+ try {
79
+ await task.run({
80
+ service: 'demo',
81
+ action: 'item.update',
82
+ context: { catalog, item }
83
+ }, async () => {
84
+ metrics.provider_effects += 1;
85
+ return { updated: item };
86
+ });
87
+ metrics.completed_normal_tasks += 1;
88
+ } catch (error) {
89
+ if (error instanceof AuthorityApprovalRequiredError) metrics.normal_approval_interruptions += 1;
90
+ else throw error;
91
+ }
92
+
93
+ if (index < DELTA_ATTACKS) {
94
+ try {
95
+ await task.run({
96
+ service: 'demo',
97
+ action: 'item.update',
98
+ context: { catalog, item: `unrelated:${index}` }
99
+ }, async () => {
100
+ metrics.provider_effects += 1;
101
+ metrics.unauthorized_effects += 1;
102
+ return { updated: `unrelated:${index}` };
103
+ });
104
+ } catch (error) {
105
+ if (error instanceof AuthorityApprovalRequiredError && error.code === 'authority_delta_required') {
106
+ metrics.delta_step_ups += 1;
107
+ } else {
108
+ throw error;
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ const percent = (numerator, denominator) => denominator === 0 ? 0 : (numerator / denominator) * 100;
115
+ const report = {
116
+ ...metrics,
117
+ normal_task_completion_rate: percent(metrics.completed_normal_tasks, metrics.normal_tasks),
118
+ false_approval_rate: percent(metrics.normal_approval_interruptions, metrics.normal_tasks),
119
+ delta_step_up_rate: percent(metrics.delta_step_ups, metrics.delta_attacks),
120
+ unauthorized_effect_rate: percent(metrics.unauthorized_effects, metrics.delta_attacks)
121
+ };
122
+
123
+ console.log(JSON.stringify(report, null, 2));
124
+
125
+ if (report.normal_task_completion_rate !== 100) throw new Error('normal task completion regressed');
126
+ if (report.false_approval_rate !== 0) throw new Error('normal tasks were interrupted by approval');
127
+ if (report.delta_step_up_rate !== 100) throw new Error('authority deltas were not consistently surfaced');
128
+ if (report.unauthorized_effect_rate !== 0) throw new Error('an unrelated effect executed');
129
+
130
+ console.log('PASS -> deterministic product utility benchmark preserved useful task completion and blocked unrelated effects');
@@ -6,33 +6,37 @@ Before any publication:
6
6
 
7
7
  1. the release commit must pass CI, CodeQL, live GitHub validation, current AI SDK integration validation, and packed-consumer validation;
8
8
  2. `npm pack` must contain the documented public exports;
9
- 3. a fresh Node.js 20 consumer must install the tarball and run the core Task Lease smoke test;
9
+ 3. a fresh Node.js 20 consumer must install the tarball and run the current public behavior smoke test;
10
10
  4. the optional AI SDK integration must import without making `ai` a production dependency;
11
11
  5. the registry package must be public and its repository metadata must point to `https://github.com/Null-Square/agent-authority`.
12
12
 
13
13
  After publication, verify from a fresh project with:
14
14
 
15
15
  ```bash
16
- npm install @nullsquare/agent-authority@0.4.4
16
+ npm install @nullsquare/agent-authority@0.4.5
17
17
  ```
18
18
 
19
19
  Then run the same consumer smoke flow through the registry-installed package. Registry verification is part of the release gate; a successful `npm publish` command alone is not sufficient.
20
20
 
21
- The repository also includes `.github/workflows/verify-npm-registry.yml`, which verifies registry visibility and a clean consumer install. For v0.4.4 it verifies the public execution-evidence and two-provider authority-extractor APIs plus the Task-Lease-aware transport surfaces:
21
+ The repository includes `.github/workflows/verify-npm-registry.yml`, which verifies registry visibility, a clean Node.js 20 install, and the current public behavior from the registry artifact. For v0.4.5 the consumer exercises:
22
22
 
23
- - `gmailThreadSenderAuthorityExtractor` from `@nullsquare/agent-authority/providers/google`;
24
- - `githubIssueListSelectedNumberAuthorityExtractor` from `@nullsquare/agent-authority/providers/github`;
25
- - `ExecutingAuthorityRuntime.executeTaskLease()` from `@nullsquare/agent-authority/execution`;
26
- - `MissionMcpGateway` from `@nullsquare/agent-authority/mcp-gateway`.
23
+ - execution evidence and the reviewed Google/GitHub authority extractors;
24
+ - `ExecutingAuthorityRuntime.executeTaskLease()` and `MissionMcpGateway` transport surfaces;
25
+ - `JsonFileTaskLeaseStore` from `@nullsquare/agent-authority/storage`;
26
+ - `DurableTaskLeaseSession` and `createDurableTaskLeaseSession()` from `@nullsquare/agent-authority/durable-task-lease`;
27
+ - durable allow / `authority_delta_required` / completion behavior;
28
+ - the requirement that the optional `ai` package is not installed as a production dependency.
27
29
 
28
- This makes the registry artifact verification cover both the two-provider execution-evidence surface and the SDK/MCP/broker transport-invariance surface exercised by the repository conformance tests.
30
+ This makes the registry artifact verification cover the same public durability, evidence and transport surfaces exercised by the repository tests rather than checking export names alone.
31
+
32
+ The v0.4.5 independent registry verification passed after publication: npm visibility succeeded and the fresh registry-installed consumer completed the durable Task Lease smoke.
29
33
 
30
34
  ## npm vs GitHub release surfaces
31
35
 
32
36
  Publishing to the public npm registry does not automatically create either a GitHub Release or a GitHub Packages entry.
33
37
 
34
38
  - **npm registry** — `npm publish --access public` publishes `@nullsquare/agent-authority` to `registry.npmjs.org` / npmjs.com. This is the package users install with `npm install`.
35
- - **GitHub Releases** — a separate GitHub object, normally backed by a Git tag such as `v0.4.4`. A release must be created explicitly or by release automation.
39
+ - **GitHub Releases** — a separate GitHub object, normally backed by a Git tag such as `v0.4.5`. A release must be created explicitly or by release automation.
36
40
  - **GitHub Packages** — a separate package registry. It only appears when the package is published to GitHub's npm registry (`npm.pkg.github.com`); publishing to npmjs.com does not populate it.
37
41
 
38
42
  Agent Authority currently uses npmjs.com as its public package registry. Therefore an empty GitHub **Packages** section is expected unless the project intentionally adopts dual publication. A GitHub **Release** is still useful for source-release discoverability and should track published versions, but it is independent from npm publication.