@basou/core 0.48.1 → 0.50.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/dist/index.d.ts CHANGED
@@ -52,10 +52,17 @@ declare function summarizeAdapterOutput(_stream: "stdout" | "stderr", _raw: stri
52
52
  * merge/removal logic stays deterministic and unit-testable.
53
53
  *
54
54
  * settings.json holds many unrelated keys (permissions, model, other hooks);
55
- * these functions clone the input and touch ONLY the `hooks.Stop` entry that
56
- * basou owns, preserving everything else byte-for-byte through the round-trip.
55
+ * these functions clone the input and touch ONLY the `hooks.Stop` and
56
+ * `hooks.SessionStart` entries that basou owns, preserving everything else
57
+ * byte-for-byte through the round-trip.
58
+ *
59
+ * The SessionStart command, matcher and timeout are the Codex twin's
60
+ * (`../codex/hooks-json.ts`): both tools run the same `basou hook session-start`
61
+ * and apply the matcher to the same session sources (startup / resume / clear /
62
+ * compact), so one decision about when the position is worth its bytes serves
63
+ * both.
57
64
  */
58
- /** Seconds before Claude Code kills the hook process. Matches the documented orient (SessionStart) hook. */
65
+ /** Seconds before Claude Code kills the Stop hook process. */
59
66
  declare const STOP_HOOK_TIMEOUT_SECONDS = 20;
60
67
  declare function isBasouStopHookCommand(command: string): boolean;
61
68
  type BuildStopHookCommandOptions = {
@@ -105,6 +112,84 @@ declare function upsertStopHook(settings: unknown, command: string): StopHookUps
105
112
  declare function removeStopHook(settings: unknown): StopHookRemoval;
106
113
  /** Return the installed basou Stop hook command, or null if none is registered. */
107
114
  declare function findBasouStopHookCommand(settings: unknown): string | null;
115
+ /** Whether a command is basou's `hook session-start`, exactly as basou writes it. */
116
+ declare function isClaudeSessionStartHookCommand(command: string): boolean;
117
+ /**
118
+ * Whether a command is the documented hand-registered `basou orient` — basou's
119
+ * own reference told Claude Code users to register exactly this before
120
+ * `basou hook install` could, so an install that ignored it would put the
121
+ * position into every session twice. It counts as basou's ONLY inside
122
+ * `hooks.SessionStart`; anywhere else it is somebody's script.
123
+ */
124
+ declare function isBasouOrientSessionStartCommand(command: string): boolean;
125
+ /** Which of basou's two SessionStart forms a command is, if either. */
126
+ type ClaudeSessionStartHookKind = "session-start" | "orient";
127
+ type ClaudeSessionStartHookUpsert = {
128
+ settings: ClaudeSettings;
129
+ /**
130
+ * `installed` = a new group was appended; `updated` = an existing
131
+ * `hook session-start` entry was rewritten or a duplicate removed;
132
+ * `replaced` = a hand-registered `basou orient` was rewritten into
133
+ * `hook session-start`; `unchanged` = already canonical, nothing touched.
134
+ */
135
+ action: "installed" | "updated" | "replaced" | "unchanged";
136
+ };
137
+ type ClaudeSessionStartHookRemoval = {
138
+ settings: ClaudeSettings;
139
+ action: "removed" | "absent";
140
+ };
141
+ /**
142
+ * Register (or upgrade in place) basou's SessionStart hook in Claude Code's
143
+ * settings. The hook prints the workspace's position into the new session's
144
+ * context, and records the git baseline the Stop hook measures the session's
145
+ * file changes against — without it, a session's shell edits are invisible.
146
+ *
147
+ * - EVERY basou entry — `hook session-start`, or the hand-registered
148
+ * `basou orient` — is rewritten IN PLACE to the canonical command + timeout.
149
+ * Its group's matcher is left as it is: the matcher is when the hook fires,
150
+ * and the person who wrote it may have chosen it. Only a new install brings
151
+ * basou's own matcher, in a group of its own. Same rule as the Codex twin.
152
+ * - A later entry is removed as a duplicate only when an earlier one fires
153
+ * under the SAME matcher. Entries under different matchers are kept even if
154
+ * they overlap: collapsing them would silently narrow when the hook fires
155
+ * (`startup` and `resume|clear` are not duplicates). Overlap that survives is
156
+ * reported by {@link findClaudeSessionStartHooks}, not resolved by guessing.
157
+ * - Foreign hooks, other events and other keys are untouched.
158
+ */
159
+ declare function upsertClaudeSessionStartHook(settings: unknown, command: string): ClaudeSessionStartHookUpsert;
160
+ /**
161
+ * Remove every basou-owned SessionStart entry — `hook session-start` and the
162
+ * hand-registered `basou orient` alike, since install treats both as basou's.
163
+ * A group emptied by the removal is dropped; a now-empty `hooks.SessionStart`
164
+ * / `hooks` container is deleted. Foreign hooks and other keys are preserved.
165
+ */
166
+ declare function removeClaudeSessionStartHook(settings: unknown): ClaudeSessionStartHookRemoval;
167
+ /** One basou-owned SessionStart entry in Claude Code's settings. */
168
+ type ClaudeSessionStartHookLocation = {
169
+ command: string;
170
+ kind: ClaudeSessionStartHookKind;
171
+ /** The matcher of the group it sits in (undefined = fires on every source). */
172
+ matcher: string | undefined;
173
+ };
174
+ /**
175
+ * Every basou-owned SessionStart entry, in file order. More than one survives
176
+ * an install only under different matchers — which is exactly the case a
177
+ * reader needs to see, since overlapping matchers put the position in twice.
178
+ */
179
+ declare function findClaudeSessionStartHooks(settings: unknown): ClaudeSessionStartHookLocation[];
180
+ /** Whether `hooks.SessionStart` exists but cannot be read as a list of groups. */
181
+ declare function isClaudeSessionStartMalformed(settings: unknown): boolean;
182
+ /**
183
+ * What a SessionStart command that runs basou but is NOT one of the two
184
+ * recognized shapes appears to run: `orient` or `hook session-start`, inside a
185
+ * longer command (a `cd` first, an `&&` chain, node options, `npx`). Install
186
+ * leaves those exactly as written; this lets it and `status` say so.
187
+ */
188
+ type ClaudeUnrecognizedSessionStart = {
189
+ command: string;
190
+ runs: ClaudeSessionStartHookKind;
191
+ };
192
+ declare function findUnrecognizedSessionStart(settings: unknown): ClaudeUnrecognizedSessionStart[];
108
193
 
109
194
  /**
110
195
  * `schema_version` stamped on NEWLY WRITTEN `.basou/manifest.yaml`.
@@ -655,6 +740,174 @@ type SessionImportPayload = z.infer<typeof SessionImportPayloadSchema>;
655
740
  /** Inferred runtime type for {@link SessionInnerImportSchema}. */
656
741
  type SessionInnerImportInput = z.infer<typeof SessionInnerImportSchema>;
657
742
 
743
+ /**
744
+ * Status classification used by the `file_changed` event schema. Limited to
745
+ * the four classes that simple-git's `git diff --name-status` reliably
746
+ * surfaces; copy / unmerged / typechange entries are intentionally dropped
747
+ * to keep the event payload shape narrow.
748
+ */
749
+ type FileChangeStatus = "added" | "modified" | "deleted" | "renamed";
750
+ /**
751
+ * Single file-level change observed between two refs. `old_path` is set
752
+ * only for `renamed` entries (the previous path of the file).
753
+ */
754
+ type FileChange = {
755
+ path: string;
756
+ old_path?: string;
757
+ status: FileChangeStatus;
758
+ };
759
+ /**
760
+ * Result of {@link getDiff}. The `changed_files` array is in git's natural
761
+ * `--name-status` order; callers requiring deterministic ordering should
762
+ * sort by `path` themselves.
763
+ */
764
+ type DiffResult = {
765
+ changed_files: FileChange[];
766
+ };
767
+ /**
768
+ * Compute the file-level diff between two git refs.
769
+ *
770
+ * Returns a list of changed file paths classified by status (added /
771
+ * modified / deleted / renamed). Diff content is intentionally NOT
772
+ * returned — `file_changed` events record paths only, and raw diff bodies
773
+ * are excluded so the trace cannot inadvertently leak source code that may
774
+ * be sensitive. Use `git show <ref>` to obtain the underlying diff.
775
+ *
776
+ * Pathless contract: every thrown message is a fixed string from the set
777
+ * {`Not a git repository`, `Git executable not found in PATH. Install git
778
+ * first.`, `Invalid ref`, `Failed to compute git diff`}; native errors are
779
+ * preserved on `Error.cause`.
780
+ *
781
+ * Special cases:
782
+ * - `baseRef === headRef` short-circuits to an empty result
783
+ * - copy / unmerged / typechange / unknown status codes are skipped
784
+ *
785
+ * @param repoRoot absolute path to the git repository root
786
+ * @param baseRef base ref (e.g. session-start HEAD sha)
787
+ * @param headRef head ref (e.g. session-end HEAD sha)
788
+ */
789
+ declare function getDiff(repoRoot: string, baseRef: string, headRef: string): Promise<DiffResult>;
790
+ /**
791
+ * Files that differ between `baseRef` and the WORKING TREE — committed and
792
+ * uncommitted alike, in one question to git.
793
+ *
794
+ * This is the net change a session produced, which is not the same as the
795
+ * union of "what it committed" and "what it left dirty": a file created and
796
+ * then committed, then modified again, is one `added` entry relative to the
797
+ * base, not an `added` plus a `modified`. Asking git for the net directly is
798
+ * what keeps the two halves from having to be reconciled by hand.
799
+ *
800
+ * Untracked files are NOT included — `git diff` never reports them — so a
801
+ * caller that wants them unions this with {@link getWorkingTreeChanges}.
802
+ *
803
+ * {@link getDiff} does NOT set `core.quotePath=false` and still returns git's
804
+ * quoted rendering for a non-ASCII path. That is a separate defect on a
805
+ * shipped path (`basou run` / `exec` write those paths into `file_changed`
806
+ * events) and is deliberately not changed here.
807
+ *
808
+ * Pathless contract and error vocabulary are identical to {@link getDiff}.
809
+ *
810
+ * @param repoRoot absolute path to the git repository root
811
+ * @param baseRef the ref the session started from (e.g. its session-start HEAD)
812
+ */
813
+ declare function getChangesSince(repoRoot: string, baseRef: string): Promise<FileChange[]>;
814
+
815
+ /**
816
+ * On-disk shape of a session observation. Deliberately NOT one of the durable
817
+ * schemas under `schemas/`: an observation is working state that exists only
818
+ * between a session's start and the import that consumes it, never a
819
+ * provenance record. The record is the `file_changed` event the import writes;
820
+ * this file is the scratch the hooks accumulate it in, and a reader that
821
+ * cannot parse it must be able to drop it and lose nothing but one session's
822
+ * file list. That is why the version below is checked but unversioned in the
823
+ * repository's schema-artifact machinery, and why every read path returns
824
+ * `null` instead of throwing.
825
+ *
826
+ * Nothing deletes these files. An age-based sweep was written and removed
827
+ * before shipping: an observation that has not been imported yet is the ONLY
828
+ * record of what its session changed — the vendor log cannot reproduce it —
829
+ * so deleting one on a timer discards evidence to save a kilobyte. What a
830
+ * retention rule should key on (imported? superseded? the session ended?) is a
831
+ * decision, and an unbounded directory of small files is the honest state to
832
+ * leave it in until that decision is made.
833
+ */
834
+ declare const SESSION_OBSERVATION_SCHEMA_VERSION: "0.1.0";
835
+ declare const ObservedFileSchema: z.ZodObject<{
836
+ path: z.ZodString;
837
+ change_type: z.ZodEnum<{
838
+ added: "added";
839
+ modified: "modified";
840
+ deleted: "deleted";
841
+ renamed: "renamed";
842
+ }>;
843
+ old_path: z.ZodOptional<z.ZodString>;
844
+ }, z.core.$strip>;
845
+ declare const ObservedRepoSchema: z.ZodObject<{
846
+ path: z.ZodString;
847
+ base_head: z.ZodNullable<z.ZodString>;
848
+ base_dirty: z.ZodDefault<z.ZodArray<z.ZodString>>;
849
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
850
+ path: z.ZodString;
851
+ change_type: z.ZodEnum<{
852
+ added: "added";
853
+ modified: "modified";
854
+ deleted: "deleted";
855
+ renamed: "renamed";
856
+ }>;
857
+ old_path: z.ZodOptional<z.ZodString>;
858
+ }, z.core.$strip>>>;
859
+ }, z.core.$strip>;
860
+ declare const SessionObservationSchema: z.ZodObject<{
861
+ schema_version: z.ZodString;
862
+ external_id: z.ZodString;
863
+ started_at: z.ZodString;
864
+ updated_at: z.ZodString;
865
+ repos: z.ZodDefault<z.ZodArray<z.ZodObject<{
866
+ path: z.ZodString;
867
+ base_head: z.ZodNullable<z.ZodString>;
868
+ base_dirty: z.ZodDefault<z.ZodArray<z.ZodString>>;
869
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
870
+ path: z.ZodString;
871
+ change_type: z.ZodEnum<{
872
+ added: "added";
873
+ modified: "modified";
874
+ deleted: "deleted";
875
+ renamed: "renamed";
876
+ }>;
877
+ old_path: z.ZodOptional<z.ZodString>;
878
+ }, z.core.$strip>>>;
879
+ }, z.core.$strip>>>;
880
+ }, z.core.$strip>;
881
+ /** A file this session changed, as observed through git. */
882
+ type ObservedFile = z.infer<typeof ObservedFileSchema>;
883
+ /** Per-repository half of a {@link SessionObservation}. */
884
+ type ObservedRepo = z.infer<typeof ObservedRepoSchema>;
885
+ /** What the hooks accumulated for one vendor session, keyed by its external id. */
886
+ type SessionObservation = z.infer<typeof SessionObservationSchema>;
887
+ /**
888
+ * Path of the observation file for `externalId`, or `null` when the id could
889
+ * address something other than a file in `observationsDir`.
890
+ */
891
+ declare function sessionObservationPath(observationsDir: string, externalId: string): string | null;
892
+ /**
893
+ * Read one observation. Returns `null` for every failure mode — absent,
894
+ * unreadable, malformed, or written by a future version — because a caller
895
+ * that cannot read the scratch must fall back to "no observation", never to an
896
+ * error that would break a hook or an import.
897
+ */
898
+ declare function readSessionObservation(observationsDir: string, externalId: string): Promise<SessionObservation | null>;
899
+ /**
900
+ * Write one observation atomically. The caller owns the decision to write; a
901
+ * failure propagates so the hook wrapper can swallow it in one place.
902
+ */
903
+ declare function writeSessionObservation(observationsDir: string, observation: SessionObservation): Promise<void>;
904
+ /**
905
+ * Flatten an observation into the file list an importer consumes: repository
906
+ * order, then path order, with duplicates across repositories impossible
907
+ * because the paths are absolute.
908
+ */
909
+ declare function observedFilesOf(observation: SessionObservation): ObservedFile[];
910
+
658
911
  /**
659
912
  * The `source` string stamped on every event derived from a Claude Code
660
913
  * native transcript, and the matching session `source.kind`.
@@ -687,6 +940,26 @@ type ClaudeTranscriptToPayloadOptions = {
687
940
  * matches the imported content. Omitted => the field is not recorded.
688
941
  */
689
942
  sourceSizeBytes?: number;
943
+ /**
944
+ * Files this session changed, observed through git while it ran (see
945
+ * `session/observe.ts`). A transcript can only report an edit made with an
946
+ * editing TOOL; work done through the shell — a heredoc, a `sed -i`, a
947
+ * script — leaves no `file_path` anywhere in it, so a session that edits
948
+ * that way reads as having touched nothing. These observations join
949
+ * `related_files`.
950
+ *
951
+ * They do NOT become events. An observation is a SNAPSHOT that each pass
952
+ * recomputes — a file changed and then reverted leaves it — while the event
953
+ * stream is append-only and a re-import preserves every event it did not
954
+ * derive itself. Writing snapshots into it would duplicate them on every
955
+ * re-import of a growing transcript and leave events contradicting the
956
+ * session record rebuilt beside them. `related_files` is rebuilt from this
957
+ * derivation each time, which is the same shape the observation has.
958
+ *
959
+ * An OPTION rather than something read here: this function is pure, and the
960
+ * observation lives on disk beside the store.
961
+ */
962
+ observedFiles?: ReadonlyArray<ObservedFile>;
690
963
  };
691
964
  /**
692
965
  * Transform a Claude Code native transcript into a Basou
@@ -1146,6 +1419,20 @@ type BasouPaths = {
1146
1419
  };
1147
1420
  readonly locks: string;
1148
1421
  readonly logs: string;
1422
+ /**
1423
+ * Per-session git observations: what each vendor session changed on disk,
1424
+ * accumulated by the hooks while it runs and consumed by the import that
1425
+ * merges it into the session's related files. Working state, not a record —
1426
+ * see `session/observation.ts`.
1427
+ *
1428
+ * Lives UNDER `tmp/` on purpose. `basou init` only appends its ignore block
1429
+ * when the file carries no basou block yet, so a store initialized before
1430
+ * this directory existed never learns to ignore a new top-level entry — and
1431
+ * these files carry absolute machine paths. `.basou/tmp/` is in every
1432
+ * generation of that block, so the placement is what keeps them out of git
1433
+ * rather than an upgrade step nobody runs.
1434
+ */
1435
+ readonly observations: string;
1149
1436
  readonly raw: string;
1150
1437
  readonly tmp: string;
1151
1438
  readonly files: {
@@ -3273,54 +3560,6 @@ type ChainVerdict = {
3273
3560
  */
3274
3561
  declare function verifyEventsChain(paths: BasouPaths, sessionId: string): Promise<ChainVerdict>;
3275
3562
 
3276
- /**
3277
- * Status classification used by the `file_changed` event schema. Limited to
3278
- * the four classes that simple-git's `git diff --name-status` reliably
3279
- * surfaces; copy / unmerged / typechange entries are intentionally dropped
3280
- * to keep the event payload shape narrow.
3281
- */
3282
- type FileChangeStatus = "added" | "modified" | "deleted" | "renamed";
3283
- /**
3284
- * Single file-level change observed between two refs. `old_path` is set
3285
- * only for `renamed` entries (the previous path of the file).
3286
- */
3287
- type FileChange = {
3288
- path: string;
3289
- old_path?: string;
3290
- status: FileChangeStatus;
3291
- };
3292
- /**
3293
- * Result of {@link getDiff}. The `changed_files` array is in git's natural
3294
- * `--name-status` order; callers requiring deterministic ordering should
3295
- * sort by `path` themselves.
3296
- */
3297
- type DiffResult = {
3298
- changed_files: FileChange[];
3299
- };
3300
- /**
3301
- * Compute the file-level diff between two git refs.
3302
- *
3303
- * Returns a list of changed file paths classified by status (added /
3304
- * modified / deleted / renamed). Diff content is intentionally NOT
3305
- * returned — `file_changed` events record paths only, and raw diff bodies
3306
- * are excluded so the trace cannot inadvertently leak source code that may
3307
- * be sensitive. Use `git show <ref>` to obtain the underlying diff.
3308
- *
3309
- * Pathless contract: every thrown message is a fixed string from the set
3310
- * {`Not a git repository`, `Git executable not found in PATH. Install git
3311
- * first.`, `Invalid ref`, `Failed to compute git diff`}; native errors are
3312
- * preserved on `Error.cause`.
3313
- *
3314
- * Special cases:
3315
- * - `baseRef === headRef` short-circuits to an empty result
3316
- * - copy / unmerged / typechange / unknown status codes are skipped
3317
- *
3318
- * @param repoRoot absolute path to the git repository root
3319
- * @param baseRef base ref (e.g. session-start HEAD sha)
3320
- * @param headRef head ref (e.g. session-end HEAD sha)
3321
- */
3322
- declare function getDiff(repoRoot: string, baseRef: string, headRef: string): Promise<DiffResult>;
3323
-
3324
3563
  /**
3325
3564
  * Build a {@link SimpleGit} instance bound to `repoRoot`. Production callers
3326
3565
  * use this single helper so any future tightening (additional safety opts,
@@ -3413,6 +3652,43 @@ declare function tryRemoteUrl(repositoryRoot: string): Promise<string | undefine
3413
3652
  */
3414
3653
  declare function getSnapshot(repositoryRoot: string): Promise<GitSnapshot>;
3415
3654
 
3655
+ /**
3656
+ * Files that differ from `HEAD` in the working tree right now — the half of a
3657
+ * session's work that {@link getDiff} cannot see, because it has not been
3658
+ * committed yet.
3659
+ *
3660
+ * A session is observed from two angles that must be UNIONED, not chosen
3661
+ * between: `getDiff(baseHead, HEAD)` covers what the session committed, and
3662
+ * this covers what it left uncommitted. Either alone reports a session that
3663
+ * ends mid-change (or one that commits everything) as having touched nothing.
3664
+ *
3665
+ * Ignored files are excluded — git's own `status` omits them, which is what
3666
+ * makes this safe to run over a repository with a build tree: `dist/` and
3667
+ * friends are ignored by the repository's own rules, so they never enter a
3668
+ * session's file list.
3669
+ *
3670
+ * Conflicted entries are skipped, matching {@link getDiff}'s treatment of the
3671
+ * `U` status code: the `file_changed` status enum has no class for them.
3672
+ *
3673
+ * Pathless contract: every thrown message is a fixed string from the set
3674
+ * {`Not a git repository`, `Git executable not found in PATH. Install git
3675
+ * first.`, `Failed to read git status`}; native errors are preserved on
3676
+ * `Error.cause`.
3677
+ *
3678
+ * @param repoRoot absolute path to the git repository root
3679
+ */
3680
+ declare function getWorkingTreeChanges(repoRoot: string): Promise<FileChange[]>;
3681
+ /**
3682
+ * `HEAD`'s commit sha, or `null` when the repository has no commits yet (an
3683
+ * unborn branch — a `git init` nobody has committed into). The null case is a
3684
+ * legitimate state for a young repository, not a failure, so it is a value
3685
+ * rather than a throw; a caller then has only the working tree to observe.
3686
+ *
3687
+ * Throws the same fixed strings as {@link getWorkingTreeChanges} when the path
3688
+ * is not a repository or git is missing.
3689
+ */
3690
+ declare function readHeadSha(repoRoot: string): Promise<string | null>;
3691
+
3416
3692
  /**
3417
3693
  * Allowed ID type prefixes for Basou entities.
3418
3694
  *
@@ -7196,6 +7472,63 @@ declare class ChildProcessRunner implements ProcessRunner {
7196
7472
  run(command: string, args: readonly string[], options: RunOptions): Promise<RunResult>;
7197
7473
  }
7198
7474
 
7475
+ /**
7476
+ * Which repositories a session's file changes are looked for in: the roster
7477
+ * the workspace declares, resolved against the store's own root.
7478
+ *
7479
+ * `repos` (not `import.source_roots`) is the roster: source roots also carry
7480
+ * non-git entries such as the workspace view, and a view is a directory of
7481
+ * symlinks with no git of its own. A workspace that declares no roster is
7482
+ * observed in its own repository only.
7483
+ */
7484
+ declare function observedRepoRoots(root: string, manifest: Manifest): string[];
7485
+ /** Inputs shared by the two observation passes. */
7486
+ type ObserveSessionInput = {
7487
+ /** `.basou/observations` of the workspace the session belongs to. */
7488
+ observationsDir: string;
7489
+ /** Absolute git repository roots to observe. */
7490
+ repoRoots: readonly string[];
7491
+ /** The vendor's session id (Claude Code's `session_id`). */
7492
+ externalId: string;
7493
+ /** Timestamp to stamp the observation with. */
7494
+ nowIso: string;
7495
+ };
7496
+ /**
7497
+ * Record where each repository stood when the session started, so a later pass
7498
+ * can ask git what changed since. Without this, "what did this session change"
7499
+ * has no base to be measured from, and the only remaining answer would be a
7500
+ * time window over commits — which attributes by proximity rather than by
7501
+ * observation, and this product has already rejected that once.
7502
+ *
7503
+ * Re-entrant by design: a SessionStart that fires again for the SAME session id
7504
+ * (a resume, a compaction) must NOT re-baseline, or every commit the session
7505
+ * has already made would drop out of its own record. An existing observation is
7506
+ * therefore left exactly as it is.
7507
+ *
7508
+ * Returns the observation in force after the call, or `null` when nothing could
7509
+ * be observed (no repository among `repoRoots` was readable).
7510
+ */
7511
+ declare function recordSessionBaseline(input: ObserveSessionInput): Promise<SessionObservation | null>;
7512
+ /**
7513
+ * Recompute what the session has changed so far, against the baseline recorded
7514
+ * at its start, and persist the result.
7515
+ *
7516
+ * A FULL recomputation, not an accumulation: `git diff <base>` already answers
7517
+ * "net change since the session started" for tracked files, committed or not,
7518
+ * so there is nothing to merge across turns and no way for the two halves to
7519
+ * disagree. A file that was changed and then reverted correctly disappears.
7520
+ *
7521
+ * Per repository, a failure keeps that repository's PREVIOUS file list rather
7522
+ * than clearing it: the common cause is a base commit that no longer resolves
7523
+ * (a rebase, a reset), and forgetting what was already observed would be a
7524
+ * silent loss where a stale list is merely old.
7525
+ *
7526
+ * Returns `null` when the session has no baseline — it started before the hook
7527
+ * was installed, or outside a registered workspace — because inventing one now
7528
+ * would measure from the middle of the work.
7529
+ */
7530
+ declare function observeSessionChanges(input: Omit<ObserveSessionInput, "repoRoots">): Promise<SessionObservation | null>;
7531
+
7199
7532
  type AppendBasouGitignoreResult = {
7200
7533
  /** True if the block was appended (or the file was newly created). */
7201
7534
  readonly appended: boolean;
@@ -7665,4 +7998,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
7665
7998
  */
7666
7999
  declare const BASOU_CORE_VERSION = "0.1.0";
7667
8000
 
7668
- export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, APPROVAL_SCHEMA_VERSION, type ActiveTimeBasis, type AdapterOutputEvent, type AdoptCandidate, type AdoptCandidateKind, type AnchorStarterInput, type AnchorStarterRepo, type AppendBasouGitignoreOptions, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchivePlan, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_BUILD, BASOU_CORE_VERSION, type BasouPaths, type BuildStamp, type BuildStopHookCommandOptions, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type CitedReview, type ClaudeSettings, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexCommandLookup, type CodexHooksFile, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DECISION_GAPS_EPOCH, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, type DecisionGap, type DecisionGapsExcluded, type DecisionGapsIncomplete, type DecisionGapsInput, type DecisionGapsScope, type DecisionGapsSummary, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, EVENT_SCHEMA_VERSION, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, type ExistingViewLink, FailedToFinalizeError, type FederatedRoot, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type GitignorePlanSummary, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, type IncompleteWiring, type InstructionFileFact, type InstructionSymlinkFact, type InstructionSymlinkState, IsoTimestampSchema, JSON_SCHEMA_VERSIONS, type JsonSchemaArtifact, LOCAL_CLI_EVENT_SOURCE, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, MANIFEST_SCHEMA_VERSION, type Manifest, ManifestSchema, type MarkerSection, type Markers, type MeasureAvailability, type MissingCanonical, type NoteAddedEvent, ORIENTATION_END, ORIENTATION_START, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, PROTOCOL_END, PROTOCOL_START, PROTOCOL_UPDATE_TOKEN_PREFIX, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type PresetStrings, type ProcessRunner, type ProtocolStamp, type PublishKind, type PublishTarget, REVIEW_RECORD_NO_INPUT_HINT, type RechainOptions, type RechainResult, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type RenamePlan, type ReplayOptions, type ReplayWarning, type RepoEntry, type RepoGitignoreFacts, type RepoGitignorePlan, type RepoInstructions, type RepoLanguage, type RepoPathProblem, type RepoPresetFacts, type RepoPresetPlan, type RepoSymlinkFacts, type RepoSymlinkPlan, type RepoVisibility, type RepoWiringFacts, type ReportApprovalItem, type ReportData, type ReportDecisionItem, type ReportRendererInput, type ReportRendererResult, type ReportSessionItem, type ReportTaskItem, type RetrofitAction, type RetrofitAgentsState, type RetrofitFacts, type RetrofitPlan, type RetrofitReason, type ReviewBlocked, type ReviewFinding, type ReviewGapRepoSummary, type ReviewGapUnit, type ReviewGapVerdict, type ReviewGapsInput, type ReviewGapsSummary, type ReviewGateResult, type ReviewGateSilentReason, type ReviewRecordBlockedInput, type ReviewRecordFindingInput, type ReviewRecordInput, type ReviewRecordedEvent, type RiskLevel, RiskLevelSchema, type RosterAdoptionPlan, type RosterDriftSummary, type RunOptions, type RunResult, SESSION_IMPORT_SCHEMA_VERSION, SESSION_SCHEMA_VERSION, SESSION_START_HOOK_CONTEXT_LIMIT, SESSION_START_HOOK_MATCHER, SESSION_START_HOOK_STATUS_MESSAGE, SESSION_START_HOOK_TIMEOUT_SECONDS, STOP_HOOK_TIMEOUT_SECONDS, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type SelfReportedReview, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartHookLocation, type SessionStartHookRemoval, type SessionStartHookUpsert, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceRootScope, type SourceRootsReconcile, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type StopHookEvaluation, type StopHookEvaluationInput, type StopHookRemoval, type StopHookSilentReason, type StopHookUpsert, type SuspectReason, type SymlinkCollision, type SymlinkConflict, type SymlinkPlanSummary, TASK_SCHEMA_VERSION, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, type TaskStatusCount, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UnattachedSelfReports, type UnbindableRepo, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type ViewCollision, type ViewConflict, type ViewLanguage, type ViewLinkState, type ViewPresetInput, type ViewPresetRepo, type ViewRepoFact, type ViewStrayUnknown, type ViewStrings, type ViewWiringFacts, type WiringCollision, type WiringConflict, type WiringDriftSummary, type WiringRisk, type WiringSummary, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WorkspaceViewPlan, type WriteEventsBulkOptions, type WriteTaskFileMode, ZERO_DURATION_RETIRED_SINCE, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildReviewRecordLabel, buildReviewRecordedEvent, buildSessionStartHookCommand, buildStatusSnapshot, buildStopHookCommand, carryForwardProtocolStamp, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexAdapterMetadata, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouSessionStartHook, findBasouStopHookCommand, findDecisionGaps, findErrorCode, findReviewGaps, findUnbindableRepos, formatDurationMs, genesisHash, getDiff, getSnapshot, hasRetiredZeroDuration, importSessionFromJson, inspectChainTail, instructionMode, isBasouSessionStartHookCommand, isBasouStopHookCommand, isGitNotFound, isImportDerivedSource, isLazyExpired, isProtocolUpdateDue, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseBuildStamp, parseDuration, parseMarkers, parseProtocolStamp, parseReviewRecordInput, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, presetStrings, protocolBlockHash, protocolSectionsFrom, protocolUpdateToken, readAllEvents, readManifest, readMarkdownFile, readObservedDuration, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeSessionStartHook, removeStopHook, renderAnchorStarter, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderProtocolStamp, renderProtocolUpdate, renderReport, renderViewPresetBlock, renderWithMarkers, replayEvents, resolveAnchorContentLanguage, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveCodexCommand, resolveRepoContentLanguage, resolveRepoRoot, resolveRepositoryRoot, resolveSessionId, resolveTaskId, resolveViewLanguage, resolveViewLanguageFromPaths, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, seedMarkers, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, summarizeWiringDrift, transcriptStartedAt, tryRemoteUrl, ulid, unknownManifestKeys, unstampedProtocolSectionsFrom, updateTaskStatusWithEvent, upsertSessionStartHook, upsertStopHook, verifyEventsChain, viewStrings, writeEventsBulk, writeManifest, writeMarkdownFile, writeObservedDuration, writeStatus, writeTaskFile, writeYamlFile };
8001
+ export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, APPROVAL_SCHEMA_VERSION, type ActiveTimeBasis, type AdapterOutputEvent, type AdoptCandidate, type AdoptCandidateKind, type AnchorStarterInput, type AnchorStarterRepo, type AppendBasouGitignoreOptions, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchivePlan, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_BUILD, BASOU_CORE_VERSION, type BasouPaths, type BuildStamp, type BuildStopHookCommandOptions, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type CitedReview, type ClaudeSessionStartHookKind, type ClaudeSessionStartHookLocation, type ClaudeSessionStartHookRemoval, type ClaudeSessionStartHookUpsert, type ClaudeSettings, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type ClaudeUnrecognizedSessionStart, type CodexCommandLookup, type CodexHooksFile, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DECISION_GAPS_EPOCH, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, type DecisionGap, type DecisionGapsExcluded, type DecisionGapsIncomplete, type DecisionGapsInput, type DecisionGapsScope, type DecisionGapsSummary, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, EVENT_SCHEMA_VERSION, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, type ExistingViewLink, FailedToFinalizeError, type FederatedRoot, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type GitignorePlanSummary, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, type IncompleteWiring, type InstructionFileFact, type InstructionSymlinkFact, type InstructionSymlinkState, IsoTimestampSchema, JSON_SCHEMA_VERSIONS, type JsonSchemaArtifact, LOCAL_CLI_EVENT_SOURCE, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, MANIFEST_SCHEMA_VERSION, type Manifest, ManifestSchema, type MarkerSection, type Markers, type MeasureAvailability, type MissingCanonical, type NoteAddedEvent, ORIENTATION_END, ORIENTATION_START, type ObserveSessionInput, type ObservedFile, type ObservedRepo, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, PROTOCOL_END, PROTOCOL_START, PROTOCOL_UPDATE_TOKEN_PREFIX, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type PresetStrings, type ProcessRunner, type ProtocolStamp, type PublishKind, type PublishTarget, REVIEW_RECORD_NO_INPUT_HINT, type RechainOptions, type RechainResult, type ReconcileAllResult, type ReconcileAllTasksInput, type ReconcileAllTasksOptions, type ReconcileFailure, type ReconcileResult, type ReconcileTaskInput, type RefreshLinkageInput, type RefreshLinkageResult, type ReimportOptions, type ReimportResult, type RenamePlan, type ReplayOptions, type ReplayWarning, type RepoEntry, type RepoGitignoreFacts, type RepoGitignorePlan, type RepoInstructions, type RepoLanguage, type RepoPathProblem, type RepoPresetFacts, type RepoPresetPlan, type RepoSymlinkFacts, type RepoSymlinkPlan, type RepoVisibility, type RepoWiringFacts, type ReportApprovalItem, type ReportData, type ReportDecisionItem, type ReportRendererInput, type ReportRendererResult, type ReportSessionItem, type ReportTaskItem, type RetrofitAction, type RetrofitAgentsState, type RetrofitFacts, type RetrofitPlan, type RetrofitReason, type ReviewBlocked, type ReviewFinding, type ReviewGapRepoSummary, type ReviewGapUnit, type ReviewGapVerdict, type ReviewGapsInput, type ReviewGapsSummary, type ReviewGateResult, type ReviewGateSilentReason, type ReviewRecordBlockedInput, type ReviewRecordFindingInput, type ReviewRecordInput, type ReviewRecordedEvent, type RiskLevel, RiskLevelSchema, type RosterAdoptionPlan, type RosterDriftSummary, type RunOptions, type RunResult, SESSION_IMPORT_SCHEMA_VERSION, SESSION_OBSERVATION_SCHEMA_VERSION, SESSION_SCHEMA_VERSION, SESSION_START_HOOK_CONTEXT_LIMIT, SESSION_START_HOOK_MATCHER, SESSION_START_HOOK_STATUS_MESSAGE, SESSION_START_HOOK_TIMEOUT_SECONDS, STOP_HOOK_TIMEOUT_SECONDS, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type SelfReportedReview, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, type SessionObservation, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartHookLocation, type SessionStartHookRemoval, type SessionStartHookUpsert, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceRootScope, type SourceRootsReconcile, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type StopHookEvaluation, type StopHookEvaluationInput, type StopHookRemoval, type StopHookSilentReason, type StopHookUpsert, type SuspectReason, type SymlinkCollision, type SymlinkConflict, type SymlinkPlanSummary, TASK_SCHEMA_VERSION, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, type TaskStatusCount, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UnattachedSelfReports, type UnbindableRepo, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type ViewCollision, type ViewConflict, type ViewLanguage, type ViewLinkState, type ViewPresetInput, type ViewPresetRepo, type ViewRepoFact, type ViewStrayUnknown, type ViewStrings, type ViewWiringFacts, type WiringCollision, type WiringConflict, type WiringDriftSummary, type WiringRisk, type WiringSummary, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WorkspaceViewPlan, type WriteEventsBulkOptions, type WriteTaskFileMode, ZERO_DURATION_RETIRED_SINCE, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildReviewRecordLabel, buildReviewRecordedEvent, buildSessionStartHookCommand, buildStatusSnapshot, buildStopHookCommand, carryForwardProtocolStamp, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexAdapterMetadata, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouSessionStartHook, findBasouStopHookCommand, findClaudeSessionStartHooks, findDecisionGaps, findErrorCode, findReviewGaps, findUnbindableRepos, findUnrecognizedSessionStart, formatDurationMs, genesisHash, getChangesSince, getDiff, getSnapshot, getWorkingTreeChanges, hasRetiredZeroDuration, importSessionFromJson, inspectChainTail, instructionMode, isBasouOrientSessionStartCommand, isBasouSessionStartHookCommand, isBasouStopHookCommand, isClaudeSessionStartHookCommand, isClaudeSessionStartMalformed, isGitNotFound, isImportDerivedSource, isLazyExpired, isProtocolUpdateDue, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, observeSessionChanges, observedFilesOf, observedRepoRoots, overwriteYamlFile, parseBuildStamp, parseDuration, parseMarkers, parseProtocolStamp, parseReviewRecordInput, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, presetStrings, protocolBlockHash, protocolSectionsFrom, protocolUpdateToken, readAllEvents, readHeadSha, readManifest, readMarkdownFile, readObservedDuration, readSessionObservation, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, recordSessionBaseline, refreshTaskLinkedSessions, reimportPreservingId, removeClaudeSessionStartHook, removeMarkerSection, removeSessionStartHook, removeStopHook, renderAnchorStarter, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderProtocolStamp, renderProtocolUpdate, renderReport, renderViewPresetBlock, renderWithMarkers, replayEvents, resolveAnchorContentLanguage, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveCodexCommand, resolveRepoContentLanguage, resolveRepoRoot, resolveRepositoryRoot, resolveSessionId, resolveTaskId, resolveViewLanguage, resolveViewLanguageFromPaths, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, seedMarkers, serializeEventLine, serializeJsonSchema, sessionObservationPath, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, summarizeWiringDrift, transcriptStartedAt, tryRemoteUrl, ulid, unknownManifestKeys, unstampedProtocolSectionsFrom, updateTaskStatusWithEvent, upsertClaudeSessionStartHook, upsertSessionStartHook, upsertStopHook, verifyEventsChain, viewStrings, writeEventsBulk, writeManifest, writeMarkdownFile, writeObservedDuration, writeSessionObservation, writeStatus, writeTaskFile, writeYamlFile };