@basou/core 0.31.0 → 0.33.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
@@ -1747,6 +1747,141 @@ declare function replayEvents(sessionDir: string, options?: ReplayOptions): Asyn
1747
1747
  */
1748
1748
  declare function readAllEvents(sessionDir: string, options?: ReplayOptions): Promise<Event[]>;
1749
1749
 
1750
+ /**
1751
+ * The language of the GENERATED-VIEW chrome (headings, labels, verdict prose)
1752
+ * in handoff.md / orientation.md / decisions.md / report output.
1753
+ *
1754
+ * This is deliberately narrower than the manifest's repo `language` axis
1755
+ * (`en | ja | en+ja`): a generated view has exactly one chrome language, so
1756
+ * `en+ja` resolves to `en`. User data (decision titles, notes, labels, file
1757
+ * paths) always passes through verbatim — only the tool-generated strings are
1758
+ * localized, which is exactly the split this type exists to keep honest.
1759
+ */
1760
+ type ViewLanguage = "en" | "ja";
1761
+ /**
1762
+ * Resolve the generated-view language from a manifest: the workspace speaks
1763
+ * the language of its ANCHOR repo (the `repos[]` entry whose path is `.`).
1764
+ *
1765
+ * Rules (fixed by design):
1766
+ * - anchor declares `ja` -> `ja`
1767
+ * - anchor declares `en` / `en+ja` -> `en` (a bilingual surface renders one
1768
+ * chrome; en is the shared floor)
1769
+ * - no roster / no anchor entry / no declared language -> `en` (the default
1770
+ * for basou's English-first OSS surface)
1771
+ *
1772
+ * Binding the view to the anchor's language is a deliberate, documented
1773
+ * coupling: the anchor is the planning/trail home the views live in, so its
1774
+ * declared audience is the views' audience. Other repos' languages do not
1775
+ * participate.
1776
+ */
1777
+ declare function resolveViewLanguage(manifest: Pick<Manifest, "repos"> | null): ViewLanguage;
1778
+ /**
1779
+ * Manifest-reading convenience for the renderers: resolve the view language
1780
+ * for a workspace, defaulting to `en` when the manifest is missing or
1781
+ * unreadable (mirrors the orientation renderer's tolerant source_roots read —
1782
+ * a broken manifest must never break a view render).
1783
+ */
1784
+ declare function resolveViewLanguageFromPaths(paths: BasouPaths): Promise<ViewLanguage>;
1785
+ /**
1786
+ * Every localized string the four view renderers emit, grouped per renderer
1787
+ * with a small `common` set for lines that are byte-identical across views.
1788
+ * Parameterized lines are functions so the two languages can order their
1789
+ * parts naturally.
1790
+ *
1791
+ * This module is the SINGLE home for generated-view Japanese (the E-5
1792
+ * language-lint allowlist points here, not at the renderers), so "user data
1793
+ * language" and "tool chrome language" can never blur together again.
1794
+ */
1795
+ type ViewStrings = {
1796
+ /** Localized relative age for prose lines, e.g. "3日4時間前" / "3d 4h ago". */
1797
+ relativeAge: (startedAt: string | null, now: Date) => string;
1798
+ common: {
1799
+ /** "最終 session" — the latest live session pointer. */
1800
+ lastSessionLabel: string;
1801
+ /** "直近の判断" — the latest recorded decision pointer. */
1802
+ latestDecisionLabel: string;
1803
+ /** "直近の変更ファイル" — the latest session's related files. */
1804
+ recentFilesLabel: string;
1805
+ /** "理由" — a track's rationale label. */
1806
+ trackWhyLabel: string;
1807
+ /** Note that the latest decision comes from a different session. */
1808
+ decisionOtherSessionNote: (shortSessionId: string) => string;
1809
+ };
1810
+ orientation: {
1811
+ headingWhere: string;
1812
+ headingRecent: (sessionCount: number) => string;
1813
+ headingInFlight: string;
1814
+ headingForward: string;
1815
+ headingCurrency: string;
1816
+ inFlightTasksHeading: (n: number) => string;
1817
+ pendingApprovalsHeading: (n: number) => string;
1818
+ suspectSessionsHeading: (n: number) => string;
1819
+ openTracksHeading: (n: number) => string;
1820
+ /** Stale-decision honesty note under 直近の判断. */
1821
+ decisionStaleNote: (activityAge: string) => string;
1822
+ outOfRootWarning: (count: number, files: string) => string;
1823
+ recentEmpty: string;
1824
+ recentDecisionsLabel: string;
1825
+ recentNextStepLabel: string;
1826
+ recentChangedLabel: string;
1827
+ trackCloseInstruction: string;
1828
+ nextStepRecordedLabel: (age: string) => string;
1829
+ noteStaleNote: (activityAge: string) => string;
1830
+ fallbackStaleDirection: string;
1831
+ fallbackStaleReferenceLabel: string;
1832
+ trackNudge: string;
1833
+ federatedFreshnessNote: string;
1834
+ bannerUnverifiable: (n: number) => string;
1835
+ bannerStale: (parts: string) => string;
1836
+ partNew: (n: number) => string;
1837
+ partUpdated: (n: number) => string;
1838
+ partsJoiner: string;
1839
+ verdictUnverifiable: (n: number) => [string, string];
1840
+ verdictStale: (parts: string) => [string, string];
1841
+ verdictUpdatedOnly: (n: number) => [string, string];
1842
+ verdictSuspectsAlso: (n: number) => string;
1843
+ verdictEmpty: [string, string];
1844
+ verdictUnprobed: (rel: string, tool: string) => [string, string];
1845
+ verdictCurrent: (rel: string, tool: string, hasHosts: boolean) => string;
1846
+ verdictSuspectsCaveat: (n: number) => string;
1847
+ verdictScopeDisclaimer: string;
1848
+ toolTerminal: string;
1849
+ toolHuman: string;
1850
+ toolImport: string;
1851
+ toolUnknown: string;
1852
+ };
1853
+ handoff: {
1854
+ headingCurrentState: string;
1855
+ headingRecentFiles: string;
1856
+ headingLatestDecision: string;
1857
+ headingOpenTracks: string;
1858
+ headingUnresolved: string;
1859
+ headingReadNext: string;
1860
+ headingNextWork: string;
1861
+ headingSessions: string;
1862
+ lastTaskLabel: string;
1863
+ decisionStaleNote: string;
1864
+ trackCloseInstruction: string;
1865
+ };
1866
+ decisions: {
1867
+ dateLabel: string;
1868
+ trackKindLine: string;
1869
+ decisionLabel: string;
1870
+ };
1871
+ report: {
1872
+ headingSummary: string;
1873
+ headingVolume: string;
1874
+ headingDecisions: string;
1875
+ headingApprovals: string;
1876
+ headingTasks: string;
1877
+ headingChangedFiles: string;
1878
+ headingSessions: string;
1879
+ headingIntegrity: string;
1880
+ };
1881
+ };
1882
+ /** Look up the string table for a resolved view language. */
1883
+ declare function viewStrings(language: ViewLanguage): ViewStrings;
1884
+
1750
1885
  /** Session lifecycle states. */
1751
1886
  declare const SessionStatusSchema: z.ZodEnum<{
1752
1887
  initialized: "initialized";
@@ -2077,6 +2212,12 @@ type DecisionsRendererInput = {
2077
2212
  nowIso: string;
2078
2213
  onWarning?: (warning: ReplayWarning, sessionId: string) => void;
2079
2214
  onSessionSkip?: (sessionId: string, reason: SessionSkipReason) => void;
2215
+ /**
2216
+ * Generated-view chrome language. Omitted (the normal path) = resolved from
2217
+ * the manifest's anchor repo via {@link resolveViewLanguageFromPaths}; the
2218
+ * override exists for tests and programmatic callers that already resolved it.
2219
+ */
2220
+ language?: ViewLanguage;
2080
2221
  };
2081
2222
  type DecisionsRendererResult = {
2082
2223
  /** Generated body WITHOUT BASOU:GENERATED markers. */
@@ -3343,6 +3484,12 @@ type HandoffRendererInput = {
3343
3484
  onTaskSkip?: (taskId: string, reason: TaskSkipReason) => void;
3344
3485
  /** Maximum related_files entries to display before `... +N more`. Default 20. */
3345
3486
  relatedFilesLimit?: number;
3487
+ /**
3488
+ * Generated-view chrome language. Omitted (the normal path) = resolved from
3489
+ * the manifest's anchor repo via {@link resolveViewLanguageFromPaths}; the
3490
+ * override exists for tests and programmatic callers that already resolved it.
3491
+ */
3492
+ language?: ViewLanguage;
3346
3493
  };
3347
3494
  type HandoffRendererResult = {
3348
3495
  /** Generated body WITHOUT BASOU:GENERATED markers (markdown-store wraps them). */
@@ -3353,7 +3500,7 @@ type HandoffRendererResult = {
3353
3500
  suspectCount: number;
3354
3501
  /** Total number of task.md files successfully loaded. */
3355
3502
  taskCount: number;
3356
- /** Tasks whose status is `planned` or `in_progress` (= shown in 次に実行すべき作業). */
3503
+ /** Tasks whose status is `planned` or `in_progress` (= shown in the next-work section). */
3357
3504
  pendingTaskCount: number;
3358
3505
  };
3359
3506
  /**
@@ -3363,16 +3510,16 @@ type HandoffRendererResult = {
3363
3510
  * {@link loadSessionEntries} / {@link enumerateApprovals}). It assembles the
3364
3511
  * the spec's `handoff.md` sections in order:
3365
3512
  *
3366
- * 1. `現在の状態`: latest live session (status not archived, source not import).
3367
- * 2. `直近の変更ファイル`: the most recent session's `related_files`, dedup +
3513
+ * 1. Current state: latest live session (status not archived, source not import).
3514
+ * 2. Recently changed files: the most recent session's `related_files`, dedup +
3368
3515
  * sorted asc + truncated to `relatedFilesLimit` (default 20).
3369
- * 3. `直近の判断`: latest `decision_recorded` event (chronological).
3370
- * 4. `未決事項`: pending-approval count + suspect-session count.
3371
- * 5. `次に読むべきファイル`: `.basou/decisions.md` + top-3 related files
3516
+ * 3. Latest decision: latest `decision_recorded` event (chronological).
3517
+ * 4. Unresolved items: pending-approval count + suspect-session count.
3518
+ * 5. Files to read next: `.basou/decisions.md` + top-3 related files
3372
3519
  * (the same `displayedFiles` source is intentionally reused in two
3373
3520
  * sections — overview vs. resume context).
3374
- * 6. `次に実行すべき作業`: placeholder until task events land.
3375
- * 7. `セッション一覧`: all sessions newest first with inline suspect labels.
3521
+ * 6. Work to do next: placeholder until task events land.
3522
+ * 7. Sessions: all sessions newest first with inline suspect labels.
3376
3523
  *
3377
3524
  * Session enumeration goes through {@link loadSessionEntries} so the set of
3378
3525
  * sessions whose `decision_recorded` events we replay matches the
@@ -3595,7 +3742,7 @@ type OrientationRendererInput = {
3595
3742
  /**
3596
3743
  * Result of a read-only dry-run staleness probe (sessions a `basou refresh`
3597
3744
  * would add or update), computed by the CLI which holds the import context.
3598
- * Drives the plain "これは最新か" verdict. `null` / omitted = not probed, so
3745
+ * Drives the plain "is this current" verdict. `null` / omitted = not probed, so
3599
3746
  * the verdict says it cannot confirm freshness rather than claiming current.
3600
3747
  */
3601
3748
  staleness?: {
@@ -3609,6 +3756,12 @@ type OrientationRendererInput = {
3609
3756
  * reads as a verdict for a supervisor, not developer diagnostics.
3610
3757
  */
3611
3758
  verbose?: boolean;
3759
+ /**
3760
+ * Generated-view chrome language. Omitted (the normal path) = resolved from
3761
+ * the manifest's anchor repo via {@link resolveViewLanguageFromPaths}; the
3762
+ * override exists for tests and programmatic callers that already resolved it.
3763
+ */
3764
+ language?: ViewLanguage;
3612
3765
  /**
3613
3766
  * Additional trail stores to MERGE into this orientation, each a local path
3614
3767
  * (an SSHFS mount / rsync mirror of another host's `.basou`) tagged with a
@@ -3664,8 +3817,8 @@ type NoteRecord = {
3664
3817
  host: string | null;
3665
3818
  };
3666
3819
  /**
3667
- * One recent session condensed to its direction signal, for the "最近の流れ"
3668
- * (recent direction) section. Across the last N non-archived sessions
3820
+ * One recent session condensed to its direction signal, for the "recent
3821
+ * direction" section. Across the last N non-archived sessions
3669
3822
  * (newest first), this surfaces the ARC of recent intent — the decision titles
3670
3823
  * and next-step notes recorded in EACH session — rather than orientation's
3671
3824
  * single latest decision/note, which can be stale or missing. When a session
@@ -3748,7 +3901,7 @@ type OrientationSummary = {
3748
3901
  decisionCount: number;
3749
3902
  /**
3750
3903
  * Open (non-voided) `kind: "track"` decisions — strategic, unfinished
3751
- * directions that the forward section ("どこへ向かう") resurfaces every session
3904
+ * directions that the forward section ("where you are heading") resurfaces every session
3752
3905
  * until they are closed with `decision void` / supersede. Newest first. This
3753
3906
  * is the intent-continuity layer: distinct from the single latest decision
3754
3907
  * (point-in-time) and the recorded next step (`note`), an open track keeps
@@ -3758,12 +3911,12 @@ type OrientationSummary = {
3758
3911
  openTracks: TrackRecord[];
3759
3912
  /**
3760
3913
  * Most recent `note_added` over non-archived sessions — the recorded next
3761
- * step / handoff ("次の起点") surfaced in the forward section; null when none.
3914
+ * step / handoff ("next step") surfaced in the forward section; null when none.
3762
3915
  */
3763
3916
  latestNote: NoteRecord | null;
3764
3917
  /**
3765
3918
  * The last N non-archived sessions (newest first) condensed to their direction
3766
- * signal — the "最近の流れ" (recent direction) arc. Distinct from the single
3919
+ * signal — the "recent direction" arc. Distinct from the single
3767
3920
  * latest decision/note: it shows the trajectory of intent across recent
3768
3921
  * sessions, and falls back to each session's changed files when no decision or
3769
3922
  * note was captured, so a resuming agent has grounding even when explicit
@@ -3844,6 +3997,62 @@ declare function summarizeOrientation(input: OrientationRendererInput): Promise<
3844
3997
  */
3845
3998
  declare function renderOrientation(input: OrientationRendererInput): Promise<OrientationRendererResult>;
3846
3999
 
4000
+ /**
4001
+ * The anchor (planning master) repo's own AGENTS.md STARTER. Unlike a repo's
4002
+ * preset block or the workspace view's canonical — both marker-managed regions
4003
+ * that `basou project preset` keeps in sync — the anchor's own AGENTS.md is
4004
+ * HAND-MAINTAINED by design (preset deliberately skips the anchor, and its
4005
+ * canonical lives at the anchor root, never under `agents/`). A greenfield
4006
+ * bring-up (`basou project new` → declare → `basou project derive`) therefore
4007
+ * leaves the planning master with no conventions doc at all, while every project
4008
+ * onboarded the older way carries one from the start.
4009
+ *
4010
+ * This renders a MINIMAL starter so a greenfield anchor is not empty: identity,
4011
+ * commit-routing, per-repo AGENTS.md pointers, a pointer to the workspace view
4012
+ * for the LIVE roster, and TODO stubs for the policy basou cannot derive
4013
+ * (product facts, phase, secrets, language policy). It is meant to be written
4014
+ * ONCE if the file is absent and NEVER touched again (create-only, no
4015
+ * BASOU:GENERATED markers) — the operator owns and hand-maintains it thereafter,
4016
+ * preserving the anchor's hands-off design.
4017
+ *
4018
+ * It deliberately does NOT embed a roster snapshot table: a manifest-derived
4019
+ * table frozen into a markerless, never-resynced file would drift silently the
4020
+ * moment a repo is added / renamed / archived, with no staleness signal for a
4021
+ * reader (or an agent) that trusts it. The live roster lives in the workspace
4022
+ * view's own generated AGENTS.md, which stays in sync; the anchor points there.
4023
+ *
4024
+ * Pure and deterministic: it renders markdown from the declared fields only, so
4025
+ * the output is a function of the manifest snapshot at seed time. It embeds no
4026
+ * operator-specific string beyond the declared repo names / project name.
4027
+ */
4028
+ /** One roster repo referenced by the anchor starter's per-repo pointers. */
4029
+ type AnchorStarterRepo = {
4030
+ /** The repo's display name (its on-disk basename). */
4031
+ name: string;
4032
+ /** True when this repo IS the anchor (the planning master itself; excluded from the pointers). */
4033
+ anchor?: boolean | undefined;
4034
+ };
4035
+ /** The declared fields the anchor starter is rendered from. */
4036
+ type AnchorStarterInput = {
4037
+ /** The anchor repo's display name (its on-disk basename) — names the file heading. */
4038
+ anchorName: string;
4039
+ /** `manifest.project.name`, when declared — used in the identity line. */
4040
+ projectName?: string | undefined;
4041
+ /** The workspace view's directory basename, when the project has a view. */
4042
+ viewName?: string | undefined;
4043
+ /** The declared roster (the anchor included), in declared order. */
4044
+ repos: AnchorStarterRepo[];
4045
+ };
4046
+ /**
4047
+ * Render the anchor's starter AGENTS.md (a full file, NOT a marker block). The
4048
+ * manifest-derived parts (identity, per-repo pointers) are filled from the
4049
+ * declaration; everything basou cannot know (product facts, phase, secrets,
4050
+ * language policy) is left as an explicit `<!-- TODO -->` for the operator. The
4051
+ * live roster is NOT snapshotted here — the file points at the workspace view's
4052
+ * generated AGENTS.md for it. Returns the file content WITH a trailing newline.
4053
+ */
4054
+ declare function renderAnchorStarter(input: AnchorStarterInput): string;
4055
+
3847
4056
  /**
3848
4057
  * Project roster drift (the "saddle" model). A project's repos are DECLARED
3849
4058
  * once in the manifest's `repos` list; the capture config (`source_roots`) must
@@ -4184,6 +4393,48 @@ declare function isRenderable(repo: PresetRepo): boolean;
4184
4393
  * writer adds the surrounding structure.
4185
4394
  */
4186
4395
  declare function renderPresetBlock(repo: PresetRepo): string;
4396
+ /** One repo aggregated by the view, rendered with its short visibility / language. */
4397
+ type ViewPresetRepo = {
4398
+ name: string;
4399
+ visibility?: RepoVisibility | undefined;
4400
+ language?: RepoLanguage | undefined;
4401
+ /**
4402
+ * True when the repo declares `instructions: self` (it owns its AGENTS.md;
4403
+ * basou stays hands-off). Rendered in the instruction-ownership column so an
4404
+ * agent reading the view knows which AGENTS.md files are generated and which
4405
+ * are hand-maintained. Absent => the default `hub` (basou-generated).
4406
+ */
4407
+ self?: boolean | undefined;
4408
+ /**
4409
+ * True when this repo IS the project anchor (the planning master). Its own
4410
+ * AGENTS.md is hand-maintained at the anchor root — basou never generates it
4411
+ * (preset skips it), so the instruction column must NOT claim `hub`. Takes
4412
+ * precedence over `self` in the label.
4413
+ */
4414
+ anchor?: boolean | undefined;
4415
+ };
4416
+ /** The declared fields the view preset block is rendered from. */
4417
+ type ViewPresetInput = {
4418
+ /**
4419
+ * The view directory's basename — names the view's own canonical
4420
+ * (`agents/<viewName>/AGENTS.md`) in the block's self-description, so a reader
4421
+ * of the generated file learns where its editable source of truth lives.
4422
+ */
4423
+ viewName: string;
4424
+ repos: ViewPresetRepo[];
4425
+ };
4426
+ /**
4427
+ * Render the workspace-view instruction-file preset block (the content between
4428
+ * the BASOU:GENERATED markers in the view's own canonical). Like
4429
+ * {@link renderPresetBlock} it is deterministic and OSS-generic: it derives
4430
+ * entirely from the declared roster (repo names come from the manifest, no
4431
+ * operator-specific string is embedded), so re-running on an unchanged manifest
4432
+ * produces byte-identical output. The repos are listed in the order supplied.
4433
+ * An empty roster still renders cleanly (a header-only table, empty lists).
4434
+ * Returns the block WITHOUT a trailing newline; the marker writer adds the
4435
+ * surrounding structure.
4436
+ */
4437
+ declare function renderViewPresetBlock(input: ViewPresetInput): string;
4187
4438
  /**
4188
4439
  * The canonical's marker state as parsed by the caller (mirrors
4189
4440
  * `markdown-store`'s `MarkerSection.kind`). `ok` means exactly one well-ordered
@@ -4257,6 +4508,13 @@ type PresetMarkerConflict = {
4257
4508
  type PresetCollision = {
4258
4509
  canonicalName: string;
4259
4510
  repos: string[];
4511
+ /**
4512
+ * True when the shared canonical is the WORKSPACE VIEW's own
4513
+ * (`agents/<viewName>/AGENTS.md`): the listed repo(s) collide with the view,
4514
+ * not (only) with each other, so neither the repo side nor the view side is
4515
+ * generated. Absent for a plain repo↔repo collision.
4516
+ */
4517
+ view?: boolean;
4260
4518
  };
4261
4519
  type PresetPlanSummary = {
4262
4520
  /** Repos whose canonical's generated region will be created/updated (only those with work). */
@@ -4301,8 +4559,15 @@ type PresetPlanSummary = {
4301
4559
  * - Two DISTINCT repos resolving to the same canonical name are a
4302
4560
  * {@link PresetCollision} and neither is generated (silent clobbering of one
4303
4561
  * canonical is surfaced, not actioned).
4304
- */
4305
- declare function summarizePresetPlan(facts: RepoPresetFacts[]): PresetPlanSummary;
4562
+ * - When the caller passes `opts.viewCanonicalName` (the workspace view's own
4563
+ * canonical name), a repo whose canonical name equals it is ALSO a collision
4564
+ * (flagged `view: true`) and is suppressed — the repo and the view would
4565
+ * otherwise write over one shared `agents/<name>/AGENTS.md`. Without the
4566
+ * option the behavior is unchanged.
4567
+ */
4568
+ declare function summarizePresetPlan(facts: RepoPresetFacts[], opts?: {
4569
+ viewCanonicalName?: string;
4570
+ }): PresetPlanSummary;
4306
4571
 
4307
4572
  /**
4308
4573
  * Rename (re-path) a repo in a project's declared roster. When a repo's
@@ -4423,6 +4688,13 @@ type RetrofitReason =
4423
4688
  | "blocked"
4424
4689
  /** refuse: the destination canonical already exists (relocating would clobber it). */
4425
4690
  | "canonical-exists"
4691
+ /**
4692
+ * refuse: the repo's canonical name equals the workspace view's, so
4693
+ * `agents/<name>/AGENTS.md` would be owned by BOTH — relocating the repo's
4694
+ * file into it (and later generating the view block over it) would corrupt
4695
+ * one with the other. The operator renames the view directory or the repo.
4696
+ */
4697
+ | "view-collision"
4426
4698
  /** skip: AGENTS.md is already a symlink (likely already wired — idempotent). */
4427
4699
  | "already-symlink"
4428
4700
  /** skip: there is no AGENTS.md to relocate. */
@@ -4445,6 +4717,13 @@ type RetrofitFacts = {
4445
4717
  reachable: boolean;
4446
4718
  /** The repo basename used for the anchor canonical `agents/<canonicalName>/AGENTS.md`. */
4447
4719
  canonicalName: string;
4720
+ /**
4721
+ * The workspace view's own canonical name (`agents/<viewCanonicalName>/AGENTS.md`),
4722
+ * when a view is declared. A repo whose `canonicalName` equals it shares ONE
4723
+ * canonical file with the view, so the relocate is refused (`view-collision`).
4724
+ * Absent (no view declared) => no collision possible.
4725
+ */
4726
+ viewCanonicalName?: string | undefined;
4448
4727
  /** On-disk state of the repo's own `AGENTS.md`. */
4449
4728
  agentsState: RetrofitAgentsState;
4450
4729
  /** True when the destination canonical already exists (moving would clobber it). */
@@ -4475,9 +4754,11 @@ type RetrofitPlan = {
4475
4754
  * apply: undeclared → anchor → self → unreachable → uninspectable AGENTS.md. Then
4476
4755
  * the idempotent skips (already a symlink, or absent — nothing to move). Only a
4477
4756
  * genuine regular-file AGENTS.md reaches the relocate decision, and even then a
4478
- * pre-existing destination canonical refuses (relocating would clobber it).
4479
- * `regularSpokes` is echoed in every outcome (it is advisory, relevant whenever a
4480
- * relocate or skip leaves the operator to tidy the spokes).
4757
+ * canonical name shared with the workspace view refuses (`view-collision` — the
4758
+ * relocate would land in the view's own canonical) and a pre-existing destination
4759
+ * canonical refuses (relocating would clobber it). `regularSpokes` is echoed in
4760
+ * every outcome (it is advisory, relevant whenever a relocate or skip leaves the
4761
+ * operator to tidy the spokes).
4481
4762
  */
4482
4763
  declare function classifyRetrofit(facts: RetrofitFacts): RetrofitPlan;
4483
4764
 
@@ -4536,8 +4817,13 @@ type RepoSymlinkFacts = {
4536
4817
  /** Roster repo path (relative to the manifest root). */
4537
4818
  path: string;
4538
4819
  /**
4539
- * True when this repo IS the project anchor (it owns the canonical sources, so
4540
- * it never links to itself). An anchor entry is skipped entirely.
4820
+ * True when this repo IS the project anchor (it hosts the OTHER repos' hub
4821
+ * canonicals under `agents/`, so it is excluded from canonical-collision
4822
+ * detection — it owns those, never links to them). Its OWN AGENTS.md is a
4823
+ * regular committed file at the anchor root, the same shape as a `self` repo:
4824
+ * only its CLAUDE.md / Copilot spokes are generated, and only once that root
4825
+ * AGENTS.md exists (`canonicalPresent`). An anchor whose AGENTS.md is absent is
4826
+ * left alone (not reported missing) until it is seeded.
4541
4827
  */
4542
4828
  isAnchor: boolean;
4543
4829
  /**
@@ -4567,7 +4853,7 @@ type RepoSymlinkFacts = {
4567
4853
  * caller for reachable, canonical-present repos; undefined otherwise.
4568
4854
  */
4569
4855
  canonicalName?: string;
4570
- /** Per instruction-file facts (empty when anchor / unreachable / canonical absent). */
4856
+ /** Per instruction-file facts (empty when an un-seeded anchor / unreachable / canonical absent). */
4571
4857
  files: InstructionSymlinkFact[];
4572
4858
  };
4573
4859
  /** The instruction-file symlinks to CREATE in one repo (only the `missing` ones). */
@@ -4628,12 +4914,18 @@ type SymlinkPlanSummary = {
4628
4914
  };
4629
4915
  /**
4630
4916
  * Compute the {@link SymlinkPlanSummary} from per-repo facts. For each declared,
4631
- * non-anchor, reachable repo whose canonical exists: a `missing` link becomes a
4632
- * create, a `mismatch`/`occupied`/`blocked` link becomes a {@link SymlinkConflict}
4633
- * (never a create — we do not overwrite), and a `correct` link is a no-op. The
4634
- * anchor is skipped (it owns the canonical), an absent canonical is reported as
4635
- * `missingCanonical` (no links planned, since the hub would dangle), and an
4636
- * unresolvable repo as `unreachable`.
4917
+ * reachable repo whose canonical exists: a `missing` link becomes a create, a
4918
+ * `mismatch`/`occupied`/`blocked` link becomes a {@link SymlinkConflict} (never a
4919
+ * create — we do not overwrite), and a `correct` link is a no-op. An absent
4920
+ * canonical is reported as `missingCanonical` (no links planned, since the hub
4921
+ * would dangle), and an unresolvable repo as `unreachable`.
4922
+ *
4923
+ * The anchor is a special case: it hosts the other repos' hub canonicals (so it
4924
+ * is excluded from collision detection — it owns those), but its OWN AGENTS.md is
4925
+ * a root committed file (self-style), so its CLAUDE.md / Copilot spokes ARE wired
4926
+ * — once that root AGENTS.md exists. An anchor whose AGENTS.md is absent is left
4927
+ * alone (not reported as missing): the seed step / operator creates it, then a
4928
+ * re-run wires the spokes.
4637
4929
  *
4638
4930
  * Robustness:
4639
4931
  * - Facts are deduped by normalized path (first wins), so a repo listed twice in
@@ -4739,6 +5031,124 @@ type WiringSummary = {
4739
5031
  */
4740
5032
  declare function summarizeWiring(facts: RepoWiringFacts[]): WiringSummary;
4741
5033
 
5034
+ /**
5035
+ * Wiring drift for `basou project check`: given the gathered instruction-file
5036
+ * facts for every declared repo AND the workspace view, classify what is DRIFTED
5037
+ * from basou's native hub-and-spoke topology — an ABSENT instruction canonical
5038
+ * (AGENTS.md), an incompletely wired repo/view, an existing file/link that is not
5039
+ * what basou would wire, a canonical-name collision, or an unreachable repo.
5040
+ *
5041
+ * The motivating gap: `project check` compared only the roster against the
5042
+ * capture config (`source_roots`) and did no filesystem probe, so a MISSING
5043
+ * instruction canonical — most sharply the workspace view's own AGENTS.md — went
5044
+ * unnoticed until an operator eyeballed it. This makes `check` surface that class
5045
+ * as drift, leading with canonical absence (the missing-AGENTS.md case).
5046
+ *
5047
+ * Pure: it composes {@link summarizeSymlinkPlan} (which already judges the repo
5048
+ * side) with the view's gathered facts and re-frames both as read-only drift. The
5049
+ * realpath / symlink reading that produces the facts is the caller's job (the CLI
5050
+ * reuses the same gatherers `project symlinks` uses), so this stays testable
5051
+ * without disk I/O.
5052
+ */
5053
+
5054
+ /**
5055
+ * The workspace view's gathered instruction facts, structurally identical to the
5056
+ * CLI's `ViewSymlinksOutcome` so the CLI passes its gathered value straight
5057
+ * through. `no-view` = no `workspace.view` declared; `collision` = the view name
5058
+ * clashes with a roster repo's canonical; `missing-canonical` = the view's own
5059
+ * canonical (`agents/<viewName>/AGENTS.md`) is absent (the my-favorites case);
5060
+ * `gathered` = the canonical exists and each spoke's on-disk state was inspected.
5061
+ */
5062
+ type ViewWiringFacts = {
5063
+ kind: "no-view";
5064
+ } | {
5065
+ kind: "collision";
5066
+ viewName: string;
5067
+ repoPath: string;
5068
+ } | {
5069
+ kind: "missing-canonical";
5070
+ viewName: string;
5071
+ } | {
5072
+ kind: "gathered";
5073
+ viewName: string;
5074
+ files: InstructionSymlinkFact[];
5075
+ };
5076
+ /**
5077
+ * An absent instruction canonical (AGENTS.md) — the primary drift this surfaces.
5078
+ * `repo-hub`: a `hub` repo's anchor canonical (`agents/<repo>/AGENTS.md`) is
5079
+ * missing; `repo-self`: a `self` repo's own committed AGENTS.md is missing;
5080
+ * `view`: the workspace view's canonical (`agents/<viewName>/AGENTS.md`) is
5081
+ * missing. `name` is the repo's roster path (repo targets) or the view name.
5082
+ */
5083
+ type MissingCanonical = {
5084
+ target: "repo-hub" | "repo-self" | "view";
5085
+ name: string;
5086
+ };
5087
+ /** A repo or the view whose canonical exists but whose spoke links are not all wired. */
5088
+ type IncompleteWiring = {
5089
+ target: "repo" | "view";
5090
+ /** Repo roster path, or the view name. */
5091
+ path: string;
5092
+ /** Instruction files still missing their link (e.g. "AGENTS.md", "CLAUDE.md"). */
5093
+ files: string[];
5094
+ };
5095
+ /** An existing file/link that is not what basou would wire — surfaced, never touched. */
5096
+ type WiringConflict = {
5097
+ target: "repo" | "view";
5098
+ /** Repo roster path, or the view name. */
5099
+ path: string;
5100
+ file: string;
5101
+ reason: "mismatch" | "occupied" | "blocked";
5102
+ /** The conflicting link's current target, present only when `reason` is `mismatch`. */
5103
+ actualTarget?: string;
5104
+ };
5105
+ /** Distinct repos (or view↔repo) resolving to the same `agents/<canonicalName>/AGENTS.md`. */
5106
+ type WiringCollision = {
5107
+ canonicalName: string;
5108
+ /** The colliding roster repo paths. */
5109
+ repos: string[];
5110
+ /** True when the workspace view is one side of the collision. */
5111
+ view?: boolean;
5112
+ };
5113
+ type WiringDriftSummary = {
5114
+ /** Absent instruction canonicals (repo hub, repo self, or view) — the headline gap. */
5115
+ missingCanonicals: MissingCanonical[];
5116
+ /** Repos/view whose canonical exists but whose spoke links are not fully wired. */
5117
+ incompleteWiring: IncompleteWiring[];
5118
+ /** Existing links that are not what basou would wire (left untouched). */
5119
+ conflicts: WiringConflict[];
5120
+ /** Ambiguous canonical-name collisions (repo↔repo or view↔repo). */
5121
+ collisions: WiringCollision[];
5122
+ /**
5123
+ * Declared repos not present on this machine (unresolvable / not a usable git
5124
+ * repo). ADVISORY: expected on a partial checkout (a workspace declares N repos;
5125
+ * a given machine has a subset cloned), so it is reported but does NOT fail
5126
+ * `ok` — otherwise `check` would read chronically dirty on every partial
5127
+ * checkout and drown the actionable drift it exists to surface.
5128
+ */
5129
+ unreachable: string[];
5130
+ /**
5131
+ * True when there is no ACTIONABLE drift: no missing canonical, no incomplete
5132
+ * wiring, no conflict, no collision. `unreachable` is deliberately excluded (it
5133
+ * is advisory — see above), so a partial checkout with otherwise-correct wiring
5134
+ * is `ok`. A missing view/repo AGENTS.md, a mismatched link, or a collision all
5135
+ * deny `ok`.
5136
+ */
5137
+ ok: boolean;
5138
+ };
5139
+ /**
5140
+ * Compute the {@link WiringDriftSummary} from the per-repo instruction facts and
5141
+ * the view's gathered facts. The repo side is delegated to
5142
+ * {@link summarizeSymlinkPlan} (so its dedup, collision, and canonical-absence
5143
+ * judgments are reused verbatim) and re-labelled as drift; the view side is folded
5144
+ * in from {@link ViewWiringFacts}. Leads with `missingCanonicals` because an absent
5145
+ * AGENTS.md is the drift the caller most needs to see.
5146
+ */
5147
+ declare function summarizeWiringDrift(input: {
5148
+ repos: RepoSymlinkFacts[];
5149
+ view: ViewWiringFacts;
5150
+ }): WiringDriftSummary;
5151
+
4742
5152
  /**
4743
5153
  * Plan the symlinks a project's throwaway "view" needs (the generation step
4744
5154
  * after the instruction-file symlinks in the "saddle" model). When a project
@@ -4762,7 +5172,12 @@ declare function summarizeWiring(facts: RepoWiringFacts[]): WiringSummary;
4762
5172
  * Pruning stray entries already in the view IS now in scope (see `toPrune` /
4763
5173
  * `strayUnknown` and {@link ExistingViewLink}): the ownership model that tells an
4764
5174
  * orphaned repo link from the view's own instruction files / local state lives
4765
- * here. Still NOT in scope: generating the view's own instruction files.
5175
+ * here. Generating the view's OWN instruction files (its AGENTS.md canonical and
5176
+ * the CLAUDE.md / Copilot spokes) is handled by `project preset` / `project
5177
+ * symlinks`, which treat the view as a second instruction target — this planner's
5178
+ * job stays the repo-aggregation symlinks and their strays. The prune ownership
5179
+ * model here (which excludes the view's own top-level instruction-file symlinks
5180
+ * from stray detection) is what keeps those generated files safe from pruning.
4766
5181
  */
4767
5182
  /**
4768
5183
  * The on-disk state of one repo's view symlink. `correct` = the expected link
@@ -5287,6 +5702,12 @@ type ReportRendererInput = {
5287
5702
  onWarning?: (warning: ReplayWarning, sessionId: string) => void;
5288
5703
  onSessionSkip?: (sessionId: string, reason: SessionSkipReason) => void;
5289
5704
  onTaskSkip?: (taskId: string, reason: TaskSkipReason) => void;
5705
+ /**
5706
+ * Generated-view chrome language. Omitted (the normal path) = resolved from
5707
+ * the manifest's anchor repo via {@link resolveViewLanguageFromPaths}; the
5708
+ * override exists for tests and programmatic callers that already resolved it.
5709
+ */
5710
+ language?: ViewLanguage;
5290
5711
  };
5291
5712
  type ReportSessionItem = {
5292
5713
  id: string;
@@ -5911,6 +6332,27 @@ declare function parseMarkers(content: string, markers?: Markers): MarkerSection
5911
6332
  * so the error message is informative without leaking an absolute path.
5912
6333
  */
5913
6334
  declare function renderWithMarkers(existing: string | null, generated: string, fileLabel: string, markers?: Markers): string;
6335
+ /**
6336
+ * Seed a marker region into a file, migrating a markerless (hand-authored) file
6337
+ * IN PLACE instead of refusing it the way {@link renderWithMarkers} does. Used by
6338
+ * `project retrofit` to auto-migrate an existing prose canonical: the generated
6339
+ * block is prepended and every byte of the existing content is preserved.
6340
+ *
6341
+ * - `existing === null` (no file yet): identical to `renderWithMarkers(null, …)`
6342
+ * — a fresh `<START>\n<generated>\n<END>\n` block.
6343
+ * - existing parses to `ok`: delegated to {@link renderWithMarkers} — the marked
6344
+ * region is replaced, everything before START / after END is kept.
6345
+ * - `no_markers` (including a 0-byte / empty-string file): the block is PREPENDED
6346
+ * (`<START>\n<generated><END>\n\n<existing>`) so the hand-authored prose is kept
6347
+ * verbatim after one blank-line separator. A leading UTF-8 BOM is re-placed at
6348
+ * the FILE head (before the seeded block), never left mid-file — matching
6349
+ * {@link parseMarkers}' BOM tolerance. A leading YAML frontmatter (`---`) is
6350
+ * NOT special-cased: the block is prepended above it (a known limitation).
6351
+ * - any malformed result (`missing_start` / `missing_end` / `multiple_pairs` /
6352
+ * `wrong_order`): throws a pathless error referencing `fileLabel`, exactly like
6353
+ * {@link renderWithMarkers} (a broken marker pair must never be silently rewritten).
6354
+ */
6355
+ declare function seedMarkers(existing: string | null, generated: string, fileLabel: string, markers?: Markers): string;
5914
6356
  /**
5915
6357
  * Remove a marker region from `existing`, returning the body without the block.
5916
6358
  *
@@ -6148,4 +6590,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
6148
6590
  */
6149
6591
  declare const BASOU_CORE_VERSION = "0.1.0";
6150
6592
 
6151
- export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, type ActiveTimeBasis, type AdapterOutputEvent, type AdoptCandidate, type AdoptCandidateKind, 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_VERSION, type BasouPaths, 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 CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, 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 InstructionFileFact, type InstructionSymlinkFact, type InstructionSymlinkState, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type Markers, type MeasureAvailability, type NoteAddedEvent, ORIENTATION_END, ORIENTATION_START, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, PROTOCOL_END, PROTOCOL_START, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type ProcessRunner, 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 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, STOP_HOOK_TIMEOUT_SECONDS, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, 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 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, 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 UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type ViewCollision, type ViewConflict, type ViewLinkState, type ViewRepoFact, type ViewStrayUnknown, type WiringRisk, type WiringSummary, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WorkspaceViewPlan, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildReviewRecordLabel, buildReviewRecordedEvent, buildStatusSnapshot, buildStopHookCommand, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexAdapterMetadata, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouStopHookCommand, findErrorCode, findReviewGaps, formatDurationMs, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, instructionMode, isBasouStopHookCommand, isGitNotFound, isImportDerivedSource, isLazyExpired, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseDuration, parseMarkers, parseReviewRecordInput, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeStopHook, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderReport, renderWithMarkers, replayEvents, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveCodexCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, upsertStopHook, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
6593
+ export { ACTIVE_GAP_CAP_MS, AGENT_INFRA_DIRS, 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_VERSION, type BasouPaths, 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 CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, DEFAULT_STOP_HOOK_MIN_EDITS, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, 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_VERSION, type JsonSchemaArtifact, type LoadFederatedOptions, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, 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, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type ProcessRunner, 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 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, STOP_HOOK_TIMEOUT_SECONDS, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, 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 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, 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 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, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildReviewRecordLabel, buildReviewRecordedEvent, buildStatusSnapshot, buildStopHookCommand, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexAdapterMetadata, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouStopHookCommand, findErrorCode, findReviewGaps, formatDurationMs, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, instructionMode, isBasouStopHookCommand, isGitNotFound, isImportDerivedSource, isLazyExpired, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseDuration, parseMarkers, parseReviewRecordInput, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeStopHook, renderAnchorStarter, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, renderReport, renderViewPresetBlock, renderWithMarkers, replayEvents, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveCodexCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, resolveViewLanguage, resolveViewLanguageFromPaths, safeSimpleGit, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, seedMarkers, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, summarizePresetPlan, summarizeRosterDrift, summarizeSymlinkPlan, summarizeWiring, summarizeWiringDrift, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, upsertStopHook, verifyEventsChain, viewStrings, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };