@sema-agent/core 5.46.0 → 5.48.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/dist/agents/agent-transcript-tool.d.ts +4 -0
  3. package/dist/agents/agent-transcript-tool.js +10 -3
  4. package/dist/agents/send-message-tool.d.ts +43 -1
  5. package/dist/agents/send-message-tool.js +50 -11
  6. package/dist/agents/subagent.d.ts +18 -0
  7. package/dist/agents/subagent.js +231 -4
  8. package/dist/config/defaults.d.ts +20 -0
  9. package/dist/config/defaults.js +5 -0
  10. package/dist/core/background-agent-store.d.ts +1 -0
  11. package/dist/core/background-agent-store.js +13 -0
  12. package/dist/core/governance-codes.d.ts +13 -0
  13. package/dist/core/governance-codes.js +33 -0
  14. package/dist/core/mcp.d.ts +6 -1
  15. package/dist/core/mcp.js +34 -7
  16. package/dist/core/memory-engine/delegation-settlement.d.ts +318 -0
  17. package/dist/core/memory-engine/delegation-settlement.js +661 -0
  18. package/dist/core/memory-engine/engine.d.ts +159 -1
  19. package/dist/core/memory-engine/engine.js +699 -15
  20. package/dist/core/memory-engine/file-backend.d.ts +1 -0
  21. package/dist/core/memory-engine/file-backend.js +3 -1
  22. package/dist/core/memory-engine/frontmatter.d.ts +46 -19
  23. package/dist/core/memory-engine/frontmatter.js +91 -77
  24. package/dist/core/memory-engine/index.d.ts +4 -3
  25. package/dist/core/memory-engine/index.js +3 -2
  26. package/dist/core/memory-engine/layout.d.ts +14 -0
  27. package/dist/core/memory-engine/layout.js +2 -2
  28. package/dist/core/memory-engine/memory-backend-contract.js +43 -0
  29. package/dist/core/memory-engine/origin-clearance.d.ts +66 -0
  30. package/dist/core/memory-engine/origin-clearance.js +84 -0
  31. package/dist/core/memory-engine/provenance-wording.d.ts +50 -0
  32. package/dist/core/memory-engine/provenance-wording.js +15 -0
  33. package/dist/core/memory-engine/tools.d.ts +61 -7
  34. package/dist/core/memory-engine/tools.js +34 -9
  35. package/dist/core/memory-engine/types.d.ts +70 -2
  36. package/dist/core/reminder-disclosure.d.ts +90 -0
  37. package/dist/core/reminder-disclosure.js +64 -0
  38. package/dist/core/runner/prepare-acquire-reconcile.d.ts +6 -0
  39. package/dist/core/runner/prepare-acquire-reconcile.js +1 -1
  40. package/dist/core/runner/prepare-hands-readface.d.ts +4 -0
  41. package/dist/core/runner/prepare-hands-readface.js +1 -0
  42. package/dist/core/runner/prepare-memory.js +50 -15
  43. package/dist/core/runner/prepare-task.d.ts +39 -0
  44. package/dist/core/runner/prepare-task.js +128 -40
  45. package/dist/core/runner/runtask.js +3 -1
  46. package/dist/core/session-reconcile.js +3 -2
  47. package/dist/core/session-store.d.ts +59 -1
  48. package/dist/core/session-store.js +82 -14
  49. package/dist/core/session.d.ts +83 -1
  50. package/dist/core/task-registry-agent.d.ts +28 -0
  51. package/dist/core/task-registry-agent.js +63 -2
  52. package/dist/core/task-registry.d.ts +21 -0
  53. package/dist/core/task-registry.js +4 -1
  54. package/dist/core/types.d.ts +98 -3
  55. package/dist/core/types.js +3 -0
  56. package/dist/core/untrusted-text.d.ts +63 -0
  57. package/dist/core/untrusted-text.js +48 -0
  58. package/dist/core/wiring-manifest.d.ts +35 -0
  59. package/dist/core/wiring-manifest.js +21 -1
  60. package/dist/engine/harness/types.d.ts +36 -1
  61. package/dist/index.d.ts +7 -5
  62. package/dist/index.js +6 -4
  63. package/dist/internal/harness-types.d.ts +1 -0
  64. package/dist/stores/file/index.d.ts +19 -3
  65. package/dist/stores/file/index.js +24 -1
  66. package/dist/stores/file/session-store.d.ts +18 -4
  67. package/dist/stores/file/session-store.js +73 -12
  68. package/dist/tools/fs/fs-pdf.d.ts +12 -1
  69. package/dist/tools/fs/fs-pdf.js +17 -3
  70. package/dist/tools/fs/fs-read.d.ts +2 -1
  71. package/dist/tools/fs/fs-read.js +33 -5
  72. package/dist/tools/fs/fs-shared.d.ts +6 -2
  73. package/dist/tools/fs/index.d.ts +7 -0
  74. package/dist/tools/fs/index.js +1 -1
  75. package/dist/tools/task-list.d.ts +5 -1
  76. package/dist/tools/web.js +21 -2
  77. package/package.json +3 -2
  78. package/test/export-surface.snapshot.json +24 -2
@@ -1,8 +1,10 @@
1
1
  import type { EngineNotice } from "../types.js";
2
+ import { foreignDanglingSessionAccounts, type EffectiveSettlement, type HoldRow } from "./delegation-settlement.js";
3
+ import { type OriginClearanceRow } from "./origin-clearance.js";
2
4
  import { type CommittedBinding, type EraseMemoryEntriesInput, type MemoryErasureAttestation, type TransferEvidence } from "./file-backend.js";
3
5
  import { type MemoryExportBundle, type MemoryImportReport } from "./export-bundle.js";
4
6
  import { type ChallengeAssignment, type ChallengeEvent, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, type MemoryPartitionIncidentSink, type RetrievedAccountRow, type SessionPollutionMarkOutcome, type SessionPollutionRecord } from "./layout.js";
5
- import type { HarvestReport, MemoryAnnouncement, MemoryBackend, MemorySessionHandle, ScanFinding } from "./types.js";
7
+ import type { HarvestReport, MemoryAnnouncement, MemoryBackend, MemoryEntryOrigin, MemorySessionHandle, ScanFinding } from "./types.js";
6
8
  /**
7
9
  * The CC `# Memory` instruction section — VERBATIM from the live capture
8
10
  * (bench/cc-parity-toolsuite/reminders/live-capture-main-session-2026-07-08.md §12), with the
@@ -34,6 +36,34 @@ export declare function buildMemoryInstruction(memoryDir: string, instructionFil
34
36
  * dual-root instruction merge ("the write plane's instruction wins") never sees a second candidate.
35
37
  */
36
38
  export declare const MEMORY_RECALL_DISCIPLINE = "Before answering questions about earlier work, decisions, dates, people, or the user's preferences, look them up: `memory_search` finds entries by keyword and `memory_get` reads a full entry \u2014 the injected memory index only lists what exists. When a lookup comes up empty, say that you checked memory and found nothing instead of guessing.";
39
+ /**
40
+ * design/336 §5.4 — the recall-discipline SEGMENT as the runner composes (and, on a retracted tool
41
+ * pair, strips) it: the base paragraph, plus — under `provenance: "carry"` only — the
42
+ * label-semantics sentence ({@link MEMORY_PROVENANCE_RECALL_SENTENCE}: what a `⚠ext` handle row /
43
+ * external-origin note means, "stays usable, verify before acting"). ONE function on purpose:
44
+ * prepare-memory appends this exact string and prepare-task's pair-retraction removes this exact
45
+ * string — two compositions would drift the moment either mode's wording moved. Under "off" this
46
+ * is byte-identical to {@link MEMORY_RECALL_DISCIPLINE} (the pre-336 segment).
47
+ */
48
+ export declare function memoryRecallDisciplineSegment(provenance: "off" | "carry"): string;
49
+ /**
50
+ * design/336 §5.5 (file-face half) — does the entry file at `absPath` carry a committed
51
+ * external-origin marker? A BOUNDED head read (default 64 KiB — an engine-projected frontmatter
52
+ * block sits at the head and is orders of magnitude smaller; the per-file store cap is 100 KB) +
53
+ * the one marker normalization ({@link committedOriginOf}: typed field or extra-form carrier).
54
+ * Consumed by the runner's Read-tool recall-taint judgment: a model that bypasses `memory_get` and
55
+ * Reads a marked entry file straight off a zero-copy plane takes up the same content, so the same
56
+ * derived mark must follow the delivery.
57
+ *
58
+ * FAIL-OPEN by design (`false` on any read/parse failure): this is a taint-propagation widening
59
+ * over a disclosure the file bytes already make themselves (the origin block is IN the file the
60
+ * model just read), not a gate — a refusal here would break ordinary reads on I/O hiccups. Named
61
+ * residuals (§5.5's standing bypass-channel class, disclosed): a frontmatter block larger than the
62
+ * bound reads as unmarked, and a file swapped between the tool's read and this one is judged on
63
+ * the swapped bytes (either direction; a spurious derived mark is the safe side — marks are
64
+ * over-approximations by law, and a missed one is exactly the residual Bash reads already carry).
65
+ */
66
+ export declare function entryFileHeadCarriesOrigin(absPath: string, maxBytes?: number): boolean;
37
67
  /**
38
68
  * design/180 B-3 — the preference-header discipline paragraph. Same carriage as
39
69
  * {@link MEMORY_RECALL_DISCIPLINE}: a runner-appended segment OUTSIDE `inject()`, so the
@@ -89,6 +119,12 @@ export declare const DEFAULT_HARVEST_DEADLINE_MS = 5000;
89
119
  /** M7 — default per-harvest processed-file budget (deliberately above the file-count cap, so it is
90
120
  * inert unless configured tighter). */
91
121
  export declare const DEFAULT_HARVEST_FILE_BUDGET = 2000;
122
+ /** design/336 §4.2 — the default settlement window: how long a delegation may stay `pending`
123
+ * before reconciliation judges it `expired` (holds disposed as unproven — LOUDLY, never silently
124
+ * dropped — and the session's unprovable window closes exposed). 72h = a comfortable upper bound
125
+ * on background-child lifetimes; the cost of the window is that a held instruction entry is
126
+ * delayed at most this long, never lost. */
127
+ export declare const DEFAULT_HOLD_SETTLE_TIMEOUT_MS: number;
92
128
  /** design/138 §2.4 删除防线 — the mass-deletion fuse threshold (fraction of materialized writable
93
129
  * entries missing at harvest above which the whole harvest is judged an incident and refused). The
94
130
  * fuse guards the BACKEND from having a wipe written back; renames (same id re-appearing elsewhere)
@@ -137,6 +173,16 @@ export interface MemoryEngineOptions {
137
173
  * spellings, never truthiness).
138
174
  */
139
175
  provenance?: "off" | "carry";
176
+ /**
177
+ * design/336 §4.2 — the delegation settlement window in ms (default
178
+ * {@link DEFAULT_HOLD_SETTLE_TIMEOUT_MS} = 72h): a `pending` settlement row older than this is
179
+ * judged `expired` at the next harvest reconciliation — the session's unprovable window closes
180
+ * exposed, and its instruction holds dispose (announced explicitly as a TIMEOUT, never a
181
+ * conviction; the `resolveHold` valve can still release them with a `"static"`-cause marker).
182
+ * A bad value (non-finite, zero, negative, non-number) refuses loudly at construction
183
+ * (`config.memory_hold_timeout`, #123 — never folded to the default).
184
+ */
185
+ holdSettleTimeoutMs?: number;
140
186
  /** M7 — harvest deadline in ms (default {@link DEFAULT_HARVEST_DEADLINE_MS}); over-deadline files
141
187
  * are deferred to the next harvest (report.degraded), never dropped. */
142
188
  harvestDeadlineMs?: number;
@@ -370,7 +416,16 @@ export declare function memoryHarvestQuarantinedNotice(input: {
370
416
  reason?: string;
371
417
  sessionId?: string;
372
418
  provenance?: "off" | "carry";
419
+ indexRolledBack?: boolean;
373
420
  }): EngineNotice;
421
+ /**
422
+ * design/336 §6.3 — the hold family's operator notices, derived from ONE harvest report's
423
+ * structured containment signal (`report.containment`), the same runner-minted posture as
424
+ * `memory.session_polluted`. Factual wording only (§13-2 model-psyche guardrail: no threat
425
+ * vocabulary — a hold is a sequencing fact, not an accusation); paths are model-controlled
426
+ * identifiers, neutralized and length-capped before they ride the message or the detail.
427
+ */
428
+ export declare function memoryHoldNotices(report: HarvestReport, sessionId?: string): EngineNotice[];
374
429
  export declare class MemoryEngine {
375
430
  private readonly backend;
376
431
  private readonly memoryDir;
@@ -382,6 +437,8 @@ export declare class MemoryEngine {
382
437
  private readonly maxDepth;
383
438
  private readonly harvestDeadlineMs;
384
439
  private readonly harvestFileBudget;
440
+ /** {@link MemoryEngineOptions.holdSettleTimeoutMs} (screened at construction, #123). */
441
+ private readonly holdSettleTimeoutMs;
385
442
  /** {@link MemoryEngineOptions.provenance} — the design/336 master switch (screened at construction). */
386
443
  private readonly provenance;
387
444
  /** {@link MemoryEngineOptions.onIncident} — the advisory disclosure seat (partition + announce codes). */
@@ -400,6 +457,10 @@ export declare class MemoryEngine {
400
457
  * failure produces no second-order disclosure — the alternative (announcing the announce failure)
401
458
  * would recurse through the very lane that just failed.
402
459
  */
460
+ /** design/336 §3.6 (slice 2) — the session-account incident channel (`memory.session_account_failed`):
461
+ * a degraded residue classification is DISCLOSED, never quiet (the behavioral fail-closed half —
462
+ * harvest refusing on `handle.sessionAccountFailed` — is enforced at the write boundary). */
463
+ private discloseSessionAccountIncident;
403
464
  private discloseAnnounceFailure;
404
465
  /**
405
466
  * Record retrieval hits (entries a memory tool actually RETURNED to the model) into this engine's
@@ -616,6 +677,7 @@ export declare class MemoryEngine {
616
677
  private settlePromotions;
617
678
  materialize(scopes: readonly string[], writeScope: string | null, opts?: {
618
679
  adoptionRestricted?: boolean;
680
+ sessionId?: string;
619
681
  }): Promise<MemorySessionHandle>;
620
682
  inject(handle: MemorySessionHandle, opts?: {
621
683
  writeToolMounted?: boolean;
@@ -658,6 +720,102 @@ export declare class MemoryEngine {
658
720
  };
659
721
  }): Promise<HarvestReport>;
660
722
  private harvestCore;
723
+ /**
724
+ * Settle every DUE hold at harvest opening (the reconciliation leg): a hold whose session's
725
+ * account is all-clean releases (the captured bytes re-walk the FULL gate set — content scan,
726
+ * size cap, origin strip — and commit under the ORIGINAL session's lineage: the true writer is
727
+ * who the retroaction machinery must find); a dirty/unprovable account disposes to quarantine
728
+ * (host-auditable, LOUD — a timeout is announced as a timeout, never as a conviction); the host
729
+ * valve's standing verdicts execute here. A hold whose settlements are still pending stays held.
730
+ * Throws only on a corrupt hold/settlement ledger — the caller's fail-closed reconciliation arm
731
+ * refuses the harvest (integrity unknown must not read as "no holds").
732
+ */
733
+ private settleDueHolds;
734
+ /**
735
+ * The release leg: re-walk the captured bytes through the FULL gate set and commit them under
736
+ * the ORIGINAL writer session's lineage. Returns the released relPath, or undefined when the
737
+ * hold did not release (disposed on a gate refusal / CAS conflict / lost capture, or kept held
738
+ * on a transient backend refusal — retried next harvest, never silently dropped).
739
+ */
740
+ private releaseHold;
741
+ /** §3.3 — the settlement valve: an audited host ruling over one delegation's outcome. `"clean"`
742
+ * releases the post-expiry gates (effective only — the history bit never flips, and a LATER
743
+ * observed `external` overrides the ruling); `"external"` convicts. Advisory trust plane. */
744
+ resolveSettlement(settleId: string, to: "clean" | "external", requestId: string): void;
745
+ /** §4.2③ — the hold valve: `"release"` commits the held entry at the next harvest WITH a
746
+ * `"static"`-cause marker (a valve release is not a cleanliness proof); `"discard"` disposes it
747
+ * to quarantine. Audited (requestId required). */
748
+ resolveHold(holdId: string, action: "release" | "discard", requestId: string): void;
749
+ /** §3.6 — the session-account valve: close a dangling foreign row WITHOUT adjudication (the
750
+ * residue arm keeps firing until the next full-domain harvest closes normally — a valve close
751
+ * must not launder the window it covers). Audited (requestId required). */
752
+ resolveSessionAccount(sessionId: string, requestId: string): void;
753
+ /** The engine's control-plane directory (the sidecar home: pollution markers, lineage/challenge
754
+ * ledgers, and the design/336 settlement/hold/session accounts). Exposed so a host (and the
755
+ * runner's settlement handle) can address the SAME plane the engine writes — a second derivation
756
+ * would be a drift seam. */
757
+ get controlPlaneDir(): string;
758
+ /** Read face: every delegation settlement row with its folded effective status (host audit). */
759
+ readDelegationSettlements(): EffectiveSettlement[];
760
+ /** Read face: every instruction-hold row (host audit; custody bytes are addressable through
761
+ * `captureName`/`disposition.quarantineName` under the control plane). */
762
+ readInstructionHolds(): HoldRow[];
763
+ /** Read face: the dangling foreign session-account rows a given session would classify residue
764
+ * against (host audit for the §3.6 valve). */
765
+ readDanglingSessionAccounts(selfSessionId: string): ReturnType<typeof foreignDanglingSessionAccounts>;
766
+ /** The committed, side-effect-free audit read: the adoption-restricted committed view when the
767
+ * backend offers one (zero-copy File — ledger+shadow, no disk adoption), else the non-adopting
768
+ * retrieval view (copy-out File), else the backend itself (Pg/TiDB shapes — naturally committed
769
+ * and side-effect-free per the getByIds contract clause). */
770
+ private committedAuditFace;
771
+ private static originClearRefusal;
772
+ /**
773
+ * §13-4① — the VIEW face: every marked entry in the given scopes, each with its marker (what /
774
+ * cause / when) and its assembled provenance account (来源委派: the lineage contributors joined
775
+ * with their sessions' pollution records — `provenanceOf`'s answer, one authority, never a
776
+ * second store). Committed state only; a marked entry that is also challenged still lists here
777
+ * (the exclusion rides inside the provenance account) — the host must SEE it to adjudicate it.
778
+ *
779
+ * Enumeration trusts the backend's `MemoryEntryHeader.exposure` clause (§6.2): a third-party
780
+ * backend that violates it UNDER-REPORTS here — the conformance suite is the acceptance
781
+ * contract (its exposure-carriage case reds on exactly that backend), and the B3 upgrade-order
782
+ * duty covers mixed fleets; the engine deliberately does not re-fetch whole scopes to
783
+ * second-guess a header face it published a contract for.
784
+ */
785
+ listExternalOriginEntries(scopes: readonly string[]): Promise<Array<{
786
+ id: string;
787
+ slug: string;
788
+ scope: string;
789
+ origin: MemoryEntryOrigin;
790
+ provenance: EntryProvenanceAccount;
791
+ }>>;
792
+ /** §13-4② read half — the clearance audit trail (pending rows are crash-recovery seats: their
793
+ * custody carries the cleared bytes; a later {@link clearEntryOrigin} call resumes them). */
794
+ listOriginClearances(): OriginClearanceRow[];
795
+ /**
796
+ * §13-4② — the audited UN-MARK valve. There is deliberately NO in-place strip spelling anywhere
797
+ * (the backend immutability law stands untouched); the clear rides the law's own single legal
798
+ * exit (§2.3-2): write-ahead clearance row (custody = the full cleared-entry text) → COMMITTED
799
+ * tombstone (CAS on the judged rev) → later-batch re-record of the SAME id with the marker
800
+ * stripped (the host's explicit vouching starts the entry's unmarked life; same id on purpose —
801
+ * links, usage accounts and the clearance join keep their key). Terminals are appended events
802
+ * (who/when/why stay queryable beside the entry); every failure leaves the custody row standing
803
+ * and a re-call RESUMES it idempotently. Refusals (#123 coded, caller-shape):
804
+ * unattributed/invalid input, unknown/unmarked entry, and a CHALLENGED entry — the clear valve
805
+ * is not a challenge exit (adjudicate the challenge first; clearing a challenged entry would
806
+ * launder the exclusion through the weaker credential).
807
+ */
808
+ clearEntryOrigin(entryId: string, input: {
809
+ requestId: string;
810
+ reason: string;
811
+ }): Promise<{
812
+ entryId: string;
813
+ clearanceId: string;
814
+ origin: MemoryEntryOrigin;
815
+ landedSlug: string;
816
+ }>;
817
+ /** The clear's effect half — replayable from the row alone (the resume arm re-enters here). */
818
+ private completeOriginClearance;
661
819
  /**
662
820
  * @param keepBaseline RB-440 (2026-07-31, hardening probe P3) — relative paths whose baseline must NOT
663
821
  * advance: the files a DEGRADED harvest deferred (`report.degraded.pending`).