phaedo-mcp 0.2.2 → 0.3.0
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/NOTICE +17 -0
- package/README.md +51 -9
- package/action-binding.js +82 -0
- package/agreement.js +38 -0
- package/ap2.js +214 -0
- package/autonomy-promotion.js +280 -0
- package/build-package.mjs +25 -10
- package/capture-a11y.js +116 -0
- package/capture-local.js +85 -0
- package/capture-sync.js +99 -0
- package/consult-core.js +50 -6
- package/consult-policy.js +427 -33
- package/consult.js +8 -1
- package/delegation-sync.js +89 -0
- package/escalation-policy.sample.json +13 -0
- package/escalation.js +383 -0
- package/fingerprint-source.js +78 -4
- package/health.js +54 -0
- package/hooks/session-end.mjs +240 -0
- package/install.mjs +164 -21
- package/lib/capture-home.js +46 -0
- package/lib/domain.js +101 -0
- package/lib/is-main.js +40 -0
- package/lib/phaedo-crypto.js +17 -1
- package/package.json +25 -5
- package/phone-source.js +79 -11
- package/projection.js +4 -1
- package/pull.js +19 -3
- package/receipts-sync.js +197 -0
- package/receipts.js +33 -2
- package/server.js +305 -15
- package/server.json +3 -3
- package/signing-audit.js +111 -0
- package/signing-request.js +217 -0
- package/signing.js +176 -0
- package/vendor/authored-source.js +250 -0
- package/vendor/capabilities.js +203 -0
- package/vendor/capture/capture-core.js +67 -0
- package/vendor/capture/detectors.js +287 -0
- package/vendor/capture/exchanges.js +77 -0
- package/vendor/capture/model-detect.js +195 -0
- package/vendor/capture/owner.js +35 -0
- package/vendor/capture/package.json +4 -0
- package/vendor/capture/source-id.js +56 -0
- package/vendor/capture/state.js +148 -0
- package/vendor/capture/transcript.js +153 -0
- package/vendor/commitments.js +169 -0
- package/vendor/context-block.js +251 -18
- package/vendor/envelope.js +50 -4
- package/vendor/extraction/capture-combine.js +160 -0
- package/vendor/extraction/catalog.js +232 -0
- package/vendor/extraction/delta-lift.js +109 -0
- package/vendor/extraction/fingerprint-update.js +227 -0
- package/vendor/extraction/package.json +4 -0
- package/vendor/extraction/persist.js +40 -0
- package/vendor/extraction/reconcile.js +269 -0
- package/vendor/extraction/resolve.js +178 -0
- package/vendor/extraction/rule-promotion.js +137 -0
- package/vendor/kdf.js +20 -1
- package/vendor/protocol.js +7 -0
- package/vendored-files.mjs +82 -0
package/consult-core.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
import { PhaedoError } from './errors.js';
|
|
18
18
|
import { loadPolicies, applyPolicies, matchAuthorization } from './consult-policy.js';
|
|
19
|
+
import { normalizeActionBinding, isBound } from './action-binding.js';
|
|
20
|
+
import { normalizeDomain, canonicalDomain } from './lib/domain.js';
|
|
19
21
|
|
|
20
22
|
export const CONSULTATION_TYPES = [
|
|
21
23
|
'action_approval',
|
|
@@ -367,14 +369,31 @@ export function normalizeRequest(request) {
|
|
|
367
369
|
}
|
|
368
370
|
const ctx = (request.context && typeof request.context === 'object') ? request.context : {};
|
|
369
371
|
const ev = ctx.evidence_provided;
|
|
372
|
+
// §10.2 action_binding: the concrete call this descriptor claims to describe.
|
|
373
|
+
// Optional — an unbound request resolves exactly as before — but an authored
|
|
374
|
+
// authorization may refuse to RELAX anything without it (§10.5 require_binding).
|
|
375
|
+
const binding = normalizeActionBinding(request.action_binding);
|
|
370
376
|
return {
|
|
371
377
|
type,
|
|
372
|
-
|
|
378
|
+
// NORMALIZED only (case/whitespace) — deliberately NOT vocabulary-mapped. The
|
|
379
|
+
// request domain feeds §10.5 matching, and a relaxing rule must keep matching on
|
|
380
|
+
// the literal the agent sent; `domainCovers` applies the vocabulary itself, and
|
|
381
|
+
// only for restrictive rules. Mapping here instead would let an alias widen a
|
|
382
|
+
// grant. The RECEIPT stores the canonical form (that is the evidence axis).
|
|
383
|
+
domain: typeof ad.domain === 'string' ? (normalizeDomain(ad.domain) || undefined) : undefined,
|
|
373
384
|
reversible: typeof ad.reversible === 'boolean' ? ad.reversible : undefined,
|
|
374
|
-
|
|
385
|
+
// UNSTATED STAYS UNSTATED (v0.1.68). This defaulted to 'medium', which meant the resolver could
|
|
386
|
+
// never tell "the agent said medium" from "the agent said nothing" — and §10.5 then let a
|
|
387
|
+
// medium-capped grant fire on the nothing. The receipt now records what was actually sent
|
|
388
|
+
// (null), which is also what situational precedent (OQ24) needs to band on. The inferred
|
|
389
|
+
// oracle path still reads an unknown as the middle of the scale (`magnitudeRank`); that is a
|
|
390
|
+
// disposition heuristic, not a grant, and it is unchanged.
|
|
391
|
+
magnitude,
|
|
375
392
|
amount: typeof ad.amount === 'number' && isFinite(ad.amount) ? ad.amount : undefined,
|
|
376
393
|
summary: typeof ad.summary === 'string' ? ad.summary : undefined,
|
|
377
394
|
evidenceProvided: Array.isArray(ev) ? ev : (ev != null ? [ev] : []),
|
|
395
|
+
binding,
|
|
396
|
+
bound: isBound(binding),
|
|
378
397
|
};
|
|
379
398
|
}
|
|
380
399
|
|
|
@@ -530,7 +549,15 @@ export function deriveDelegationSignals(receipts, { now = new Date().toISOString
|
|
|
530
549
|
const sig = r?.response?.signal;
|
|
531
550
|
const contribution = delegationCorrection(sig, r && r.user_action); // signed; 0 = agreement/no lesson
|
|
532
551
|
if (!contribution) continue;
|
|
533
|
-
|
|
552
|
+
// Canonicalize the domain BEFORE bucketing, or one concept spelled several ways
|
|
553
|
+
// (finance / financial / Finance) fragments into several near-identical buckets — the
|
|
554
|
+
// drift §10.2's published vocabulary exists to end. Both the live overlay
|
|
555
|
+
// (deriveDelegationSignals) and the promotion cards (buildDelegationPromotions) key on
|
|
556
|
+
// this, so both must canonicalize or a card floods / an overlay splits. Free text still
|
|
557
|
+
// survives — an unrecognized domain canonicalizes to itself — so only known synonyms
|
|
558
|
+
// merge, never distinct classes.
|
|
559
|
+
const domain = canonicalDomain(
|
|
560
|
+
(typeof r?.request?.action_descriptor?.domain === 'string') ? r.request.action_descriptor.domain : '');
|
|
534
561
|
for (const d of (Array.isArray(r.drivers) ? r.drivers : [])) {
|
|
535
562
|
if (!CUES[d && d.cue]) continue; // scalar caution cues only (ambiguity later)
|
|
536
563
|
const k = `${d.cue}|${domain}`;
|
|
@@ -627,7 +654,15 @@ export function buildDelegationPromotions(receipts, fp, { now = new Date().toISO
|
|
|
627
654
|
const sig = r?.response?.signal;
|
|
628
655
|
const contribution = delegationCorrection(sig, r && r.user_action);
|
|
629
656
|
if (!contribution) continue;
|
|
630
|
-
|
|
657
|
+
// Canonicalize the domain BEFORE bucketing, or one concept spelled several ways
|
|
658
|
+
// (finance / financial / Finance) fragments into several near-identical buckets — the
|
|
659
|
+
// drift §10.2's published vocabulary exists to end. Both the live overlay
|
|
660
|
+
// (deriveDelegationSignals) and the promotion cards (buildDelegationPromotions) key on
|
|
661
|
+
// this, so both must canonicalize or a card floods / an overlay splits. Free text still
|
|
662
|
+
// survives — an unrecognized domain canonicalizes to itself — so only known synonyms
|
|
663
|
+
// merge, never distinct classes.
|
|
664
|
+
const domain = canonicalDomain(
|
|
665
|
+
(typeof r?.request?.action_descriptor?.domain === 'string') ? r.request.action_descriptor.domain : '');
|
|
631
666
|
for (const d of (Array.isArray(r.drivers) ? r.drivers : [])) {
|
|
632
667
|
const dim = CUE_DIMENSION[d && d.cue];
|
|
633
668
|
if (!dim) continue;
|
|
@@ -744,6 +779,15 @@ export function ruleResponse(vd, n) {
|
|
|
744
779
|
return shape(n.type, resolved.signal, cal.confidence, resolved.hint, cal.deference_level);
|
|
745
780
|
}
|
|
746
781
|
|
|
782
|
+
// The §10.5 evaluation context, lifted out of `opts` once so both public entries
|
|
783
|
+
// gate identically. `clientId` is the SERVING paired client's own `client_id` (from
|
|
784
|
+
// the server's `pairing.json`, supplied by the transport layer) — the identity
|
|
785
|
+
// `agents` scoping matches on; never anything the caller asserted. Absent here means
|
|
786
|
+
// unpaired, which makes every `agents`-scoped relaxing rule inert. Passing `now`
|
|
787
|
+
// through as well keeps rule expiry on the same clock `loadPolicies` already gives
|
|
788
|
+
// §5.7 commitments; both fall back to `Date.now()` when a caller omits them.
|
|
789
|
+
const policyCtx = (opts = {}) => ({ now: opts.now, clientId: opts.clientId ?? null });
|
|
790
|
+
|
|
747
791
|
// ── Public pure entry ─────────────────────────────────────────────────────────
|
|
748
792
|
// (vd, request[, opts]) -> §10.3 response. Deterministic; applies authored §10.5
|
|
749
793
|
// policies last so a standing guardrail wins (even over an abstain). `opts.policies`
|
|
@@ -752,7 +796,7 @@ export function ruleResponse(vd, n) {
|
|
|
752
796
|
export function resolveConsultationCore(vd, request = {}, opts = {}) {
|
|
753
797
|
assertVaultUsable(vd);
|
|
754
798
|
const n = normalizeRequest(request);
|
|
755
|
-
return applyPolicies(ruleResponse(vd, n), n, loadPolicies(vd, opts));
|
|
799
|
+
return applyPolicies(ruleResponse(vd, n), n, loadPolicies(vd, opts), policyCtx(opts));
|
|
756
800
|
}
|
|
757
801
|
|
|
758
802
|
// Back-compat alias: the prior public name of the sync rule entry. Kept so existing
|
|
@@ -769,7 +813,7 @@ export const buildConsultationResponse = resolveConsultationCore;
|
|
|
769
813
|
export function checkAuthorization(vd, request = {}, opts = {}) {
|
|
770
814
|
assertVaultUsable(vd);
|
|
771
815
|
const n = normalizeRequest(request);
|
|
772
|
-
const auth = matchAuthorization(n, loadPolicies(vd, opts));
|
|
816
|
+
const auth = matchAuthorization(n, loadPolicies(vd, opts), policyCtx(opts));
|
|
773
817
|
return {
|
|
774
818
|
phaedo_response_version: '0.1',
|
|
775
819
|
request_type: 'authorization_check',
|