@sema-agent/core 5.34.0 → 5.36.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 (47) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/agents/subagent.js +29 -2
  3. package/dist/core/auto-compaction.d.ts +23 -0
  4. package/dist/core/auto-compaction.js +8 -0
  5. package/dist/core/checkpoint-store.d.ts +49 -4
  6. package/dist/core/context-guard.d.ts +41 -0
  7. package/dist/core/context-guard.js +76 -0
  8. package/dist/core/hooks.d.ts +98 -3
  9. package/dist/core/hooks.js +146 -8
  10. package/dist/core/memory-engine/engine.js +1 -1
  11. package/dist/core/park-selfcheck.d.ts +161 -0
  12. package/dist/core/park-selfcheck.js +251 -0
  13. package/dist/core/runner/assemble-result.d.ts +3 -0
  14. package/dist/core/runner/assemble-result.js +3 -0
  15. package/dist/core/runner/git-status-frame.d.ts +219 -0
  16. package/dist/core/runner/git-status-frame.js +212 -0
  17. package/dist/core/runner/prepare-acquire-reconcile.d.ts +6 -0
  18. package/dist/core/runner/prepare-acquire-reconcile.js +2 -1
  19. package/dist/core/runner/prepare-task.d.ts +28 -4
  20. package/dist/core/runner/prepare-task.js +86 -52
  21. package/dist/core/runner/runtask.d.ts +6 -1
  22. package/dist/core/runner/runtask.js +330 -19
  23. package/dist/core/task-registry-agent.d.ts +15 -0
  24. package/dist/core/task-registry-agent.js +9 -0
  25. package/dist/core/task-registry.d.ts +3 -0
  26. package/dist/core/task-registry.js +4 -1
  27. package/dist/core/tool-errors.d.ts +2 -2
  28. package/dist/core/tool-policy.d.ts +125 -0
  29. package/dist/core/tool-policy.js +35 -2
  30. package/dist/core/types.d.ts +98 -9
  31. package/dist/engine/harness/types.d.ts +65 -1
  32. package/dist/engine/harness/types.js +20 -0
  33. package/dist/engine/session/import-validate.js +10 -1
  34. package/dist/engine/session/session.d.ts +37 -1
  35. package/dist/engine/session/session.js +56 -1
  36. package/dist/index.d.ts +3 -2
  37. package/dist/index.js +3 -2
  38. package/dist/internal/harness-types.d.ts +1 -0
  39. package/dist/internal/harness.d.ts +2 -0
  40. package/dist/internal/harness.js +2 -0
  41. package/dist/orchestration/workflow.d.ts +1 -1
  42. package/dist/prompt-assembly/epoch.js +1 -1
  43. package/dist/prompt-assembly/event-registry.js +1 -0
  44. package/dist/prompts/default.d.ts +20 -7
  45. package/dist/prompts/default.js +2 -7
  46. package/package.json +1 -1
  47. package/test/export-surface.snapshot.json +17 -1
@@ -1,6 +1,6 @@
1
1
  import type { ImageContent, TextContent } from "../llm/index.js";
2
2
  import type { AgentMessage } from "../loop/types.js";
3
- import type { Session, SessionContext, SessionMetadata, SessionStorage, SessionTreeEntry, WorkspaceState } from "../harness/types.js";
3
+ import type { GitAnnouncementState, Session, SessionContext, SessionMetadata, SessionStorage, SessionTreeEntry, WorkspaceState } from "../harness/types.js";
4
4
  import type { BuildContextOptions } from "../harness/types.js";
5
5
  import type { PromptEpochDescriptor } from "../../prompt-assembly/epoch.js";
6
6
  /** Build model context from the active session branch and its latest state markers.
@@ -45,6 +45,31 @@ export declare class StoredSession<TMetadata extends SessionMetadata = SessionMe
45
45
  skills?: readonly string[];
46
46
  models?: readonly string[];
47
47
  }): Promise<string>;
48
+ /**
49
+ * Git-status frame announced state (branch-authority mirror): persist the `(kind, hash)` tuple —
50
+ * announced form carries the frame's own entry id; a compaction restates the tuple as `pending`
51
+ * inside its `details.gitAnnouncement` instead (same-CAS with the new baseline). Called
52
+ * best-effort at every frame COMMIT point (append receipt in hand) — an append failure degrades
53
+ * to a conservative re-announcement on the next leg (duplicate-tolerant), never fails the run.
54
+ */
55
+ appendGitAnnouncement(state: GitAnnouncementState): Promise<string>;
56
+ /**
57
+ * Branch-authority read of the git announced state: the nearest carrier walking back from the
58
+ * leaf (a `git_announcement` entry or a compaction's `details.gitAnnouncement` restatement;
59
+ * SNAPSHOT semantics — first hit wins). The pending gate is a MANDATORY one: a nearest carrier
60
+ * that is pending, or an announced carrier whose frame entryId is NOT on the active branch (a
61
+ * rewind cut the frame while a descendant mirror survived), reads as `status:"pending"` — the
62
+ * caller must conservatively re-announce rather than trust a mirror whose frame the model cannot
63
+ * see. Malformed carriers are skipped (defense in depth behind the import door). Undefined ⇒ no
64
+ * carrier visible on this branch (pre-migration session / bounded-tail floor cut every carrier) —
65
+ * callers fall back to the checkpoint mirror rung, then to conservative re-announcement.
66
+ */
67
+ getGitAnnouncement(): Promise<{
68
+ kind: GitAnnouncementState["kind"];
69
+ hash: string;
70
+ status: "announced" | "pending";
71
+ entryId?: string;
72
+ } | undefined>;
48
73
  /**
49
74
  * design/155 (cli [1580]): persist the settle-time workspace state (tracked cwd + active
50
75
  * EnterWorktree session) as a first-class typed entry. Called best-effort at task settle when the
@@ -115,3 +140,14 @@ export declare class StoredSession<TMetadata extends SessionMetadata = SessionMe
115
140
  appendLabel(targetId: string, label: string | undefined): Promise<string>;
116
141
  appendSessionName(name: string): Promise<string>;
117
142
  }
143
+ /**
144
+ * Falsification round 1 (F3) — is `entryId` not merely ON the active branch but inside the region
145
+ * a context rebuild can actually contain? A branch walk sees the whole tree; `buildSessionContext`
146
+ * replays only [latest compaction's firstKeptEntryId .. leaf] (plus the summary). A git frame that
147
+ * sits BEFORE the latest compaction's kept tail is therefore gone from every future request even
148
+ * though its id is a legitimate branch member — an announced mirror pointing at it must read as
149
+ * PENDING (re-announce), or the announced hash would suppress re-sends of bytes the model can no
150
+ * longer see. Shared by the session mirror walk and the run loop's checkpoint seeding rung (one
151
+ * rule, both readers). Conservative on damage: an unresolvable firstKeptEntryId reads as invisible.
152
+ */
153
+ export declare function gitFrameContextVisible(branch: SessionTreeEntry[], entryId: string): boolean;
@@ -1,5 +1,5 @@
1
1
  import { asAgentMessage, createCompactionSummaryMessage, createCustomMessage, } from "../harness/messages.js";
2
- import { SessionError, isValidModelChange, normalizeAnnouncedListing, normalizeCompactionStateCarrier, normalizeWorkspaceState } from "../harness/types.js";
2
+ import { SessionError, isValidModelChange, normalizeAnnouncedListing, normalizeCompactionStateCarrier, normalizeGitAnnouncement, normalizeWorkspaceState } from "../harness/types.js";
3
3
  import { normalizePromptEpoch } from "../../prompt-assembly/epoch.js";
4
4
  import { budgetInvokedSkillsRetention, readElidedMessages, readRetainedInvokedSkills, renderInvokedSkillsRetention, } from "../compaction/utils.js";
5
5
  const RETENTION_CLAMP_DEFAULT_CHARS_PER_TOKEN = 4;
@@ -181,6 +181,39 @@ export class StoredSession {
181
181
  ...shaped,
182
182
  });
183
183
  }
184
+ async appendGitAnnouncement(state) {
185
+ const shaped = normalizeGitAnnouncement(state);
186
+ if (!shaped) {
187
+ throw new SessionError("invalid_entry", "appendGitAnnouncement: state is not a structurally valid git announcement (closed kind, sha256 hash, bounded entryId)");
188
+ }
189
+ return this.appendTypedEntry({
190
+ type: "git_announcement",
191
+ id: await this.storage.createEntryId(),
192
+ parentId: await this.storage.getLeafId(),
193
+ timestamp: new Date().toISOString(),
194
+ ...shaped,
195
+ });
196
+ }
197
+ async getGitAnnouncement() {
198
+ const branch = await this.getBranch();
199
+ for (let i = branch.length - 1; i >= 0; i--) {
200
+ const entry = branch[i];
201
+ let carried;
202
+ if (entry.type === "git_announcement") {
203
+ carried = normalizeGitAnnouncement(entry);
204
+ }
205
+ else if (entry.type === "compaction") {
206
+ carried = normalizeGitAnnouncement(entry.details?.gitAnnouncement);
207
+ }
208
+ if (carried === undefined)
209
+ continue;
210
+ const announced = carried.pending !== true && carried.entryId !== undefined && gitFrameContextVisible(branch, carried.entryId);
211
+ return announced
212
+ ? { kind: carried.kind, hash: carried.hash, status: "announced", entryId: carried.entryId }
213
+ : { kind: carried.kind, hash: carried.hash, status: "pending" };
214
+ }
215
+ return undefined;
216
+ }
184
217
  async appendWorkspaceState(state) {
185
218
  const shaped = normalizeWorkspaceState(state);
186
219
  if (!shaped) {
@@ -314,3 +347,25 @@ export class StoredSession {
314
347
  });
315
348
  }
316
349
  }
350
+ export function gitFrameContextVisible(branch, entryId) {
351
+ let frameIdx = -1;
352
+ let compactionIdx = -1;
353
+ let firstKeptId;
354
+ for (let i = 0; i < branch.length; i++) {
355
+ const e = branch[i];
356
+ if (e.id === entryId)
357
+ frameIdx = i;
358
+ if (e.type === "compaction") {
359
+ compactionIdx = i;
360
+ firstKeptId = e.firstKeptEntryId;
361
+ }
362
+ }
363
+ if (frameIdx === -1)
364
+ return false;
365
+ if (compactionIdx === -1 || frameIdx > compactionIdx)
366
+ return true;
367
+ if (firstKeptId === undefined)
368
+ return false;
369
+ const keptIdx = branch.findIndex((e) => e.id === firstKeptId);
370
+ return keptIdx !== -1 && frameIdx >= keptIdx;
371
+ }
package/dist/index.d.ts CHANGED
@@ -108,6 +108,7 @@ export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
108
108
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
109
109
  export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, } from "./core/task-notification.js";
110
110
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
111
+ export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
111
112
  export { type StoreDurability } from "./core/checkpoint-store.js";
112
113
  export { type StoreFidelity } from "./core/checkpoint-store.js";
113
114
  export { projectHumanInput, buildHumanInputEvent, type HumanInputSource, type HumanInputFrame, type HumanInputEvent, type HumanInputDelivery, } from "./core/human-input-projection.js";
@@ -131,7 +132,7 @@ export type { SchedulerCapability, SchedulerErrorCode, ScheduledIntent, Schedule
131
132
  export { createSchedulerTools, type SchedulerToolContext, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTINEL, AUTONOMOUS_LOOP_DYNAMIC_SENTINEL, } from "./tools/scheduler-tools.js";
132
133
  export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, type AutonomousLoopPromptOptions, } from "./tools/loop-tick.js";
133
134
  export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
134
- export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicyProjection, type ToolPolicyProjectionComponent, type ConstraintChainEntry, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type ApprovalSettledBy, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, } from "./core/tool-policy.js";
135
+ export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicyProjection, type ToolPolicyProjectionComponent, type ConstraintChainEntry, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type ApprovalSettledBy, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, type AskRuleEvidence, type AskEvidenceAbsence, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
135
136
  export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassifyFn, type AutoModeClassifyInput, } from "./core/auto-mode.js";
136
137
  export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
137
138
  export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
@@ -161,7 +162,7 @@ export { FilePermissionRuleStoreProvider } from "./stores/file/permission-rule-s
161
162
  export { adoptFilePermissionRuleStore, type AdoptFileRuleStoreResult } from "./stores/file/permission-rule-adopt.js";
162
163
  export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, type AdoptionErrorCode, type AdoptionSource, type AdoptionReport, type AdoptionReceipt, type AdoptionLegReport, type AffectedDeploymentConfig, type RootAdoptionFile, } from "./stores/file/adoption/marker.js";
163
164
  export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./stores/file/adoption/adopt.js";
164
- export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type Hooks, type HookToolContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
165
+ export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleUnreadable, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
165
166
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
166
167
  export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type MemoryGetDetails, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
167
168
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryPagedList, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
package/dist/index.js CHANGED
@@ -87,6 +87,7 @@ export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
87
87
  export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
88
88
  export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, } from "./core/task-notification.js";
89
89
  export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, } from "./core/wiring-manifest.js";
90
+ export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, } from "./core/park-selfcheck.js";
90
91
  export {} from "./core/checkpoint-store.js";
91
92
  export {} from "./core/checkpoint-store.js";
92
93
  export { projectHumanInput, buildHumanInputEvent, } from "./core/human-input-projection.js";
@@ -108,7 +109,7 @@ export { hasScheduler, isValidCronExpr, SchedulerError } from "./core/scheduler.
108
109
  export { createSchedulerTools, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTINEL, AUTONOMOUS_LOOP_DYNAMIC_SENTINEL, } from "./tools/scheduler-tools.js";
109
110
  export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, } from "./tools/loop-tick.js";
110
111
  export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
111
- export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, } from "./core/tool-policy.js";
112
+ export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
112
113
  export { parseAutoModeResponse, createAutoModeDecider, } from "./core/auto-mode.js";
113
114
  export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, } from "./core/auto-mode-prompt.js";
114
115
  export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
@@ -123,7 +124,7 @@ export { FilePermissionRuleStoreProvider } from "./stores/file/permission-rule-s
123
124
  export { adoptFilePermissionRuleStore } from "./stores/file/permission-rule-adopt.js";
124
125
  export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, } from "./stores/file/adoption/marker.js";
125
126
  export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, } from "./stores/file/adoption/adopt.js";
126
- export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, } from "./core/hooks.js";
127
+ export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, normalizePersistedRuleHit, } from "./core/hooks.js";
127
128
  export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, } from "./core/memory.js";
128
129
  export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, migrateScope, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, syncMemoryScope, } from "./core/memory-engine/index.js";
129
130
  export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, } from "./core/shared-memory/types.js";
@@ -12,4 +12,5 @@ export type { AgentHarnessEvent, CompactionSettings, ExecutionEnv, ExecutionErro
12
12
  export type { ExecutionEnvExecOptions, ExecResult } from "../engine/harness/types.js";
13
13
  export type { SessionWriteOptions, CompactionEntry } from "../engine/harness/types.js";
14
14
  export type { ActiveWorktreeSession, WorkspaceState } from "../engine/harness/types.js";
15
+ export type { GitAnnouncementKind, GitAnnouncementState } from "../engine/harness/types.js";
15
16
  export type { SessionForkOptions } from "../engine/harness/types.js";
@@ -23,3 +23,5 @@ export { InMemorySessionStorage } from "../engine/session/memory-storage.js";
23
23
  export { InMemorySessionRepo } from "../engine/session/memory-repo.js";
24
24
  export { uuidv7 } from "../engine/session/uuid.js";
25
25
  export { SessionError } from "../engine/harness/types.js";
26
+ export { normalizeGitAnnouncement } from "../engine/harness/types.js";
27
+ export { gitFrameContextVisible } from "../engine/session/session.js";
@@ -12,3 +12,5 @@ export { InMemorySessionStorage } from "../engine/session/memory-storage.js";
12
12
  export { InMemorySessionRepo } from "../engine/session/memory-repo.js";
13
13
  export { uuidv7 } from "../engine/session/uuid.js";
14
14
  export { SessionError } from "../engine/harness/types.js";
15
+ export { normalizeGitAnnouncement } from "../engine/harness/types.js";
16
+ export { gitFrameContextVisible } from "../engine/session/session.js";
@@ -198,7 +198,7 @@ export interface WorkflowAgentHandle {
198
198
  * its reply with the returned marker. Returns that MARKER so the launcher can correlate the worker's tagged
199
199
  * reply via the #5 transcript (the worker self-stamps; reply is best-effort). One-directional + leader-driven
200
200
  * (the worker can't address the leader except by the marker). A steer issued BEFORE the worker's loop goes
201
- * live is parked and delivered onto turn 1 (birth-window delivery, bounded — ledger item 36); steers are
201
+ * live is parked and delivered into the NEXT turn's context (birth-window delivery, bounded — ledger item 36); steers are
202
202
  * delivered in call order, the birth window included. Rejects with `steering.not_running` once the task has
203
203
  * finished (teardown included).
204
204
  */
@@ -50,7 +50,7 @@ const PROBE_INPUTS_BASE = {
50
50
  roleBase: "\u0000probe-role\u0000",
51
51
  roleAppend: "\u0000probe-append\u0000",
52
52
  mcpInstructionsBlock: "\u0000probe-mcp\u0000",
53
- environmentBlock: "\u0000probe-env\u0000",
53
+ environmentBlock: "\u0000probe-env@2\u0000",
54
54
  memoryBlock: "\u0000probe-memory\u0000",
55
55
  modelGuidance: "\u0000probe-guidance\u0000",
56
56
  };
@@ -13,6 +13,7 @@ export const EVENT_PROMPT_REGISTRY = new Map([
13
13
  { kind: "skills_listing", carrier: "message.user-prefix", trust: "operator", dedupe: "replace-by-key", defaultPolicy: "on", rendererRef: "turn-attachments.ts#renderSkillsListingDelta" },
14
14
  { kind: "mcp_instructions", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpInstructionsDelta" },
15
15
  { kind: "mcp_dropped_tools", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "off", rendererRef: "turn-attachments.ts#renderMcpDroppedTools" },
16
+ { kind: "git_status", carrier: "message.user-prefix", trust: "external", dedupe: "replace-by-key", defaultPolicy: "always", rendererRef: "git-status-frame.ts#renderGitStatusFrameBody" },
16
17
  { kind: "limit_approach_converge", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
17
18
  { kind: "limit_approach_deliver", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#limitApproachFrames" },
18
19
  { kind: "final_verification", carrier: "message.user-prefix", trust: "operator", dedupe: "once-per-run", defaultPolicy: "always", rendererRef: "runtask.ts#final-verification" },
@@ -271,9 +271,13 @@ export interface EnvironmentFacts {
271
271
  cwd?: string;
272
272
  isGitRepo?: boolean;
273
273
  /** design/99 §E14 — the current git branch (remote = the container's repo). `"HEAD (detached)"` when on a
274
- * detached HEAD. Absent when not a git repo / no git. A prepare-time snapshot, like cwd (may go stale mid-run). */
274
+ * detached HEAD. Absent when not a git repo / no git. A prepare-time snapshot, like cwd (may go stale mid-run).
275
+ * env-tail migration (#254 shape): NO LONGER RENDERED by {@link buildEnvironmentContext} — the
276
+ * branch is a turn-dynamic fact and rides the `git_status` frame instead; the field remains as a
277
+ * structured data carrier for callers that assembled it. */
275
278
  gitBranch?: string;
276
- /** design/99 §E14 — whether the working tree has uncommitted changes (`git status --porcelain` non-empty). */
279
+ /** design/99 §E14 — whether the working tree has uncommitted changes (`git status --porcelain` non-empty).
280
+ * env-tail migration: NO LONGER RENDERED here (turn-dynamic; rides the `git_status` frame). */
277
281
  gitDirty?: boolean;
278
282
  /** design/99 §E14 — the working tree's toplevel (`git rev-parse --show-toplevel`). Lets the agent/shell know
279
283
  * it may be in a linked worktree rather than the main checkout. */
@@ -319,10 +323,10 @@ export interface EnvironmentFacts {
319
323
  /** A1 — outbound-network posture; `none` renders an explicit downloads-will-fail caveat (TB
320
324
  * autopsy 2026-07-05: agents burned budget retrying downloads in a no-egress sandbox). */
321
325
  sandboxEgress?: "none" | "allowlist" | "full";
322
- /** H4 (CC 2.1.198 git snapshot) — the pre-rendered {@link buildGitSnapshot} block, appended to the
323
- * `# Environment` block as its own paragraph. A PREPARE-TIME snapshot by contract (its first line
324
- * self-declares "will not update during the conversation"); the date_change re-render carries it
325
- * unchanged. Absent when not a git repo / the probe failed (whole section skipped, CC-same). */
326
+ /** H4 (CC 2.1.198 git snapshot) — the pre-rendered {@link buildGitSnapshot} block. env-tail
327
+ * migration (#254 shape): NO LONGER RENDERED by {@link buildEnvironmentContext} the snapshot is
328
+ * the turn-dynamic git view and rides the `git_status` frame (re-sent only when the rendered view
329
+ * changes); the field remains as a structured data carrier for callers that assembled it. */
326
330
  gitSnapshot?: string;
327
331
  /** [1451] B-half — per-lane resume-continuity facts (deployment-supplied via `TaskSpec.envFacts.resumeFacts`,
328
332
  * copied by prepare ONLY on a durable-resume leg). Each present field renders one honest sentence; absent
@@ -353,11 +357,20 @@ export interface EnvironmentFacts {
353
357
  export declare function buildScratchpadSection(scratchpadDir: string): string;
354
358
  /** CC 2.1.198 `Juo` — the git status truncation bound (chars) for {@link buildGitSnapshot}. */
355
359
  export declare const GIT_STATUS_MAX_CHARS = 2000;
360
+ /** The CC-verbatim first paragraph of the git snapshot (CC 2.1.198 `Quo` head sentence). Kept as a
361
+ * named constant so the git-status FRAME renderer (the snapshot's carrier since the env-tail
362
+ * migration) can swap exactly this paragraph for its own update-semantics preamble — under the
363
+ * frame protocol the snapshot IS re-sent when the visible view changes, so the "will not update"
364
+ * claim would be false there. {@link buildGitSnapshot} itself still renders it byte-exact. */
365
+ export declare const GIT_SNAPSHOT_CC_PREAMBLE = "This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.";
356
366
  /**
357
367
  * H4 — the CC 2.1.198 ENV git snapshot block (B1/B2; template + truncation copy verified against
358
368
  * observed Claude Code v2.1.198 behavior). Pure renderer — the Runner gathers the raw values through the
359
369
  * ExecutionEnv seam (remote = the container's repo) and calls this once per prepareTask (a durable
360
- * resume re-prepares → re-snapshots, CC new-session 同型).
370
+ * resume re-prepares → re-snapshots, CC new-session 同型). env-tail migration (#254 shape): the
371
+ * rendered block now feeds the `git_status` TURN FRAME (src/core/runner/git-status-frame.ts, which
372
+ * swaps the {@link GIT_SNAPSHOT_CC_PREAMBLE} for an update-semantics preamble) instead of the
373
+ * `# Environment` system-prompt section — the template body itself stays CC-verbatim.
361
374
  *
362
375
  * Sanitization (deliberate CC deviation — CC injects raw): status/log/branch/user are REPO-controlled
363
376
  * text (filenames, commit subjects, a hostile clone's config) landing in the TRUSTED prompt region →
@@ -196,6 +196,7 @@ Only use \`/tmp\` if the user explicitly requests it.
196
196
  The scratchpad directory is session-specific, isolated from the user's project, and can generally be used without permission prompts. Treat it as ephemeral — it may not survive a long suspension or a resume on a different worker; keep durable outputs in the working directory.`;
197
197
  }
198
198
  export const GIT_STATUS_MAX_CHARS = 2000;
199
+ export const GIT_SNAPSHOT_CC_PREAMBLE = "This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.";
199
200
  export function buildGitSnapshot(p) {
200
201
  const tool = p.statusToolName ?? "Bash";
201
202
  const status = sanitizeUntrustedText(p.status.trim());
@@ -205,7 +206,7 @@ export function buildGitSnapshot(p) {
205
206
  `\n... (truncated because it exceeds 2k characters. If you need more information, run "git status" using ${tool})`
206
207
  : status;
207
208
  return [
208
- "This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.",
209
+ GIT_SNAPSHOT_CC_PREAMBLE,
209
210
  `Current branch: ${inlineUntrusted(p.branch)}`,
210
211
  `Main branch (you will usually use this for PRs): ${inlineUntrusted(p.mainBranch)}`,
211
212
  ...(p.userName ? [`Git user: ${inlineUntrusted(p.userName)}`] : []),
@@ -255,10 +256,6 @@ export function buildEnvironmentContext(facts) {
255
256
  }
256
257
  if (facts.isGitRepo !== undefined)
257
258
  lines.push(`Is a git repository: ${facts.isGitRepo ? "yes" : "no"}`);
258
- if (facts.gitBranch)
259
- lines.push(`Git branch: ${inlineUntrusted(facts.gitBranch)}`);
260
- if (facts.gitDirty !== undefined)
261
- lines.push(`Git working tree: ${facts.gitDirty ? "has uncommitted changes" : "clean"}`);
262
259
  if (facts.gitWorktreeRoot)
263
260
  lines.push(`Git worktree root: ${inlineUntrusted(facts.gitWorktreeRoot)}`);
264
261
  if (facts.isLinkedWorktree) {
@@ -302,8 +299,6 @@ export function buildEnvironmentContext(facts) {
302
299
  }
303
300
  const base = lines.length > 0 ? `# Environment\n${lines.join("\n")}` : "";
304
301
  const sections = [base, ...(facts.scratchpadDir ? [buildScratchpadSection(facts.scratchpadDir)] : [])].filter((s) => s.length > 0);
305
- if (facts.gitSnapshot)
306
- sections.push(facts.gitSnapshot);
307
302
  return sections.join("\n\n");
308
303
  }
309
304
  export const CODE_AGENT_PROMPT = `You are a capable software-engineering agent that acts through tools.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "5.34.0",
3
+ "version": "5.36.0",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "_comment": "design/87 L3 — frozen public export surface of src/index.ts (name -> kind). DO NOT edit by hand to silence a red test. A removed/changed entry = a SemVer-BREAKING change; bump MAJOR and update this fixture in the SAME commit (design/87 §4.2 / §5.2). Regenerate via REGEN in test/export-surface.test.ts.",
3
- "count": 1546,
3
+ "count": 1562,
4
4
  "exports": {
5
5
  "A2ATaskState": "type",
6
6
  "A2ATaskStateReversal": "type",
@@ -19,7 +19,9 @@
19
19
  "AGGREGATE_TOOL_RESULT_BUDGET_CHARS": "variable",
20
20
  "ANNOUNCEMENTS_FILE": "variable",
21
21
  "APPROVAL_SETTLED_BY_VALUES": "variable",
22
+ "APPROVER_ATTRIBUTION_MAX_CHARS": "variable",
22
23
  "ARTIFACT_LIMITS": "variable",
24
+ "ASK_EVIDENCE_ABSENCE_VALUES": "variable",
23
25
  "AUTONOMOUS_LOOP_DYNAMIC_SENTINEL": "variable",
24
26
  "AUTONOMOUS_LOOP_PREAMBLE": "variable",
25
27
  "AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT": "variable",
@@ -57,12 +59,14 @@
57
59
  "AskAnswerContinuationSource": "type",
58
60
  "AskDelegationProvenance": "interface",
59
61
  "AskEffective": "type",
62
+ "AskEvidenceAbsence": "type",
60
63
  "AskOutcome": "type",
61
64
  "AskQuestion": "interface",
62
65
  "AskQuestionCardDetails": "type",
63
66
  "AskQuestionOption": "interface",
64
67
  "AskQuestionRequest": "interface",
65
68
  "AskRequest": "interface",
69
+ "AskRuleEvidence": "interface",
66
70
  "AskSeamForm": "type",
67
71
  "AskUserQuestionToolOptions": "interface",
68
72
  "AssertOracleIsolationOptions": "interface",
@@ -539,6 +543,7 @@
539
543
  "OrphanToolCall": "interface",
540
544
  "OutputChunk": "type",
541
545
  "OwnOrgAdmissionVerdict": "interface",
546
+ "PARK_SELFCHECK_SCOPE_PREFIX": "variable",
542
547
  "PEER_ADMISSION_DEFAULTS": "variable",
543
548
  "PEER_HOP_CHAIN_WINDOW": "variable",
544
549
  "PEER_MESSAGE_NOTICE": "variable",
@@ -556,6 +561,9 @@
556
561
  "PROTOCOL_TABLE": "variable",
557
562
  "PackSectionDeclaration": "interface",
558
563
  "ParkLaneReason": "type",
564
+ "ParkProbeFinding": "interface",
565
+ "ParkProbeFindingCode": "type",
566
+ "ParkSelfCheckResult": "interface",
559
567
  "ParkedClaimTicket": "interface",
560
568
  "ParsedAllowRule": "interface",
561
569
  "ParsedEntryFile": "interface",
@@ -591,8 +599,11 @@
591
599
  "PermissionRuleWriter": "interface",
592
600
  "PersistedAllowRule": "interface",
593
601
  "PersistedOrgRuleState": "interface",
602
+ "PersistedRuleAnswer": "type",
603
+ "PersistedRuleHit": "interface",
594
604
  "PersistedRuleMatch": "type",
595
605
  "PersistedRuleTool": "type",
606
+ "PersistedRuleUnreadable": "interface",
596
607
  "PlatformLimitReason": "type",
597
608
  "PostCompactContext": "interface",
598
609
  "PostToolBatchCall": "interface",
@@ -1230,6 +1241,8 @@
1230
1241
  "devWorkflowScriptRunner": "variable",
1231
1242
  "dotAtOrBelowFrontier": "function",
1232
1243
  "drainMemoryAnnouncements": "function",
1244
+ "durableParkGapFor": "function",
1245
+ "durableParkGapOf": "function",
1233
1246
  "editBudget": "function",
1234
1247
  "effectivePermissionRules": "function",
1235
1248
  "emitTaskOutcome": "function",
@@ -1345,6 +1358,7 @@
1345
1358
  "normalizeAgentName": "function",
1346
1359
  "normalizeForExactMatch": "function",
1347
1360
  "normalizeMemorySpec": "function",
1361
+ "normalizePersistedRuleHit": "function",
1348
1362
  "normalizePromptEpoch": "function",
1349
1363
  "normalizeRules": "function",
1350
1364
  "normalizeToolResultProvenance": "function",
@@ -1375,6 +1389,7 @@
1375
1389
  "prepareCardApproval": "function",
1376
1390
  "prepareCcImport": "function",
1377
1391
  "prepareStarterBatch": "function",
1392
+ "probeParkRoundTrip": "function",
1378
1393
  "probeSearchBackend": "function",
1379
1394
  "projectHumanInput": "function",
1380
1395
  "projectToolManifest": "function",
@@ -1475,6 +1490,7 @@
1475
1490
  "scanRemediation": "function",
1476
1491
  "scopeCoversCwd": "function",
1477
1492
  "scopeDirName": "function",
1493
+ "screenApproverAttribution": "function",
1478
1494
  "screenInboundEntries": "function",
1479
1495
  "screenRuleSyncState": "function",
1480
1496
  "scrubSecretEnv": "function",