@basou/core 0.44.0 → 0.45.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 +1039 -712
- package/dist/index.js +3466 -3201
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/approval.schema.json +7 -7
- package/schemas/event.schema.json +45 -45
- package/schemas/manifest.schema.json +5 -5
- package/schemas/retired/0.1.0/approval.schema.json +119 -0
- package/schemas/retired/0.1.0/manifest.schema.json +264 -0
- package/schemas/retired/0.1.0/session-import.schema.json +1703 -0
- package/schemas/retired/0.1.0/session.schema.json +254 -0
- package/schemas/retired/0.1.0/task.schema.json +84 -0
- package/schemas/retired/0.2.0/event.schema.json +1452 -0
- package/schemas/session-import.schema.json +55 -55
- package/schemas/session.schema.json +9 -9
- package/schemas/status.schema.json +2 -2
- package/schemas/task-index.schema.json +4 -4
- package/schemas/task.schema.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -106,6 +106,19 @@ declare function removeStopHook(settings: unknown): StopHookRemoval;
|
|
|
106
106
|
/** Return the installed basou Stop hook command, or null if none is registered. */
|
|
107
107
|
declare function findBasouStopHookCommand(settings: unknown): string | null;
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* `schema_version` stamped on NEWLY WRITTEN `.basou/manifest.yaml`.
|
|
111
|
+
*
|
|
112
|
+
* 0.2.0 requires seconds in every timestamp. That NARROWS the field's domain,
|
|
113
|
+
* which §7.3 forbids except under the vacuous-narrowing rule the same section
|
|
114
|
+
* states: no value basou has ever written omits seconds, so the set of
|
|
115
|
+
* documents this refuses is empty. See `docs/spec/schemas.md` for the read
|
|
116
|
+
* rule and the measurement. The narrowing is shared with the event format, so
|
|
117
|
+
* every durable document bumps together.
|
|
118
|
+
*
|
|
119
|
+
* Note: basou writes this document.
|
|
120
|
+
*/
|
|
121
|
+
declare const MANIFEST_SCHEMA_VERSION: "0.2.0";
|
|
109
122
|
/**
|
|
110
123
|
* The manifest, plus one guard the loose object cannot express: a TOP-LEVEL
|
|
111
124
|
* `confidential` is refused. It belongs under `policies`, and because the
|
|
@@ -278,9 +291,17 @@ declare const SessionInnerImportSchema: z.ZodObject<{
|
|
|
278
291
|
* validates a payload against the published artifact gets the same answer the
|
|
279
292
|
* importer will give, instead of passing validation and being rejected at run
|
|
280
293
|
* time. Unrelated to the events INSIDE the envelope, which carry their own
|
|
281
|
-
* `schema_version` and are at 0.
|
|
294
|
+
* `schema_version` and are at 0.3.0.
|
|
295
|
+
*
|
|
296
|
+
* Bumped to 0.2.0 when timestamps began requiring seconds. That narrowing
|
|
297
|
+
* reaches the envelope's OWN fields -- `session.started_at`, `session.ended_at`
|
|
298
|
+
* and both `active_intervals` bounds -- so unlike the 0.2.0 event bump, whose
|
|
299
|
+
* bytes changed only because of the union it embeds, the envelope's own
|
|
300
|
+
* accepted set moved and the `$id` moves with it. A third party still gets one
|
|
301
|
+
* answer from the artifact and the importer, which is the whole point of
|
|
302
|
+
* pinning the version here.
|
|
282
303
|
*/
|
|
283
|
-
declare const SESSION_IMPORT_SCHEMA_VERSION: "0.
|
|
304
|
+
declare const SESSION_IMPORT_SCHEMA_VERSION: "0.2.0";
|
|
284
305
|
declare const SessionImportPayloadSchema: z.ZodObject<{
|
|
285
306
|
schema_version: z.ZodString;
|
|
286
307
|
session: z.ZodObject<{
|
|
@@ -1016,6 +1037,19 @@ type CodexRolloutToPayloadOptions = {
|
|
|
1016
1037
|
*/
|
|
1017
1038
|
declare function codexRolloutToImportPayload(records: ReadonlyArray<CodexRolloutRecord>, options: CodexRolloutToPayloadOptions): SessionImportPayload | null;
|
|
1018
1039
|
|
|
1040
|
+
/**
|
|
1041
|
+
* `schema_version` stamped on NEWLY WRITTEN `.basou/approvals/**`.
|
|
1042
|
+
*
|
|
1043
|
+
* 0.2.0 requires seconds in every timestamp. That NARROWS the field's domain,
|
|
1044
|
+
* which §7.3 forbids except under the vacuous-narrowing rule the same section
|
|
1045
|
+
* states: no value basou has ever written omits seconds, so the set of
|
|
1046
|
+
* documents this refuses is empty. See `docs/spec/schemas.md` for the read
|
|
1047
|
+
* rule and the measurement. The narrowing is shared with the event format, so
|
|
1048
|
+
* every durable document bumps together.
|
|
1049
|
+
*
|
|
1050
|
+
* Note: basou only READS this document -- approvals are placed by an outside orchestrator, so nothing in this tree stamps the version; the constant exists so the published artifact and the accepted set are declared in one place.
|
|
1051
|
+
*/
|
|
1052
|
+
declare const APPROVAL_SCHEMA_VERSION: "0.2.0";
|
|
1019
1053
|
/**
|
|
1020
1054
|
* Lifecycle states of a Basou approval. The status is stored directly on
|
|
1021
1055
|
* the approval YAML (flat shape) so that pending → resolved transitions
|
|
@@ -1177,9 +1211,16 @@ declare function enumerateApprovals(paths: BasouPaths): Promise<{
|
|
|
1177
1211
|
declare function isLazyExpired(approval: Approval, now: Date): boolean;
|
|
1178
1212
|
|
|
1179
1213
|
/**
|
|
1180
|
-
* `schema_version` stamped on NEWLY WRITTEN events.
|
|
1181
|
-
*
|
|
1182
|
-
*
|
|
1214
|
+
* `schema_version` stamped on NEWLY WRITTEN events.
|
|
1215
|
+
*
|
|
1216
|
+
* 0.3.0 requires seconds in every timestamp. That NARROWS the field's domain,
|
|
1217
|
+
* which §7.3 forbids except under the vacuous-narrowing rule the same section
|
|
1218
|
+
* states: no value basou has ever written omits seconds, so the set of
|
|
1219
|
+
* documents this refuses is empty. See `docs/spec/schemas.md` for the read
|
|
1220
|
+
* rule and the measurement.
|
|
1221
|
+
*
|
|
1222
|
+
* 0.2.0 made `command_executed.duration_ms` nullable, which widened the
|
|
1223
|
+
* field's domain and so is a breaking change to the format.
|
|
1183
1224
|
*
|
|
1184
1225
|
* The bump does not change what any value already on disk means: `0` meant "not
|
|
1185
1226
|
* observed" before and still does. What changes is that a writer now says so
|
|
@@ -1188,13 +1229,17 @@ declare function isLazyExpired(approval: Approval, now: Date): boolean;
|
|
|
1188
1229
|
* `readObservedDuration`), and the
|
|
1189
1230
|
* version is a statement about validation, not about interpretation.
|
|
1190
1231
|
*
|
|
1191
|
-
* Reading is unaffected — {@link SchemaVersionSchema}
|
|
1192
|
-
* events already on disk keep validating, and are not
|
|
1193
|
-
* session IS re-derived, and restamped, when its source
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1232
|
+
* Reading is unaffected by the 0.2.0 bump — {@link SchemaVersionSchema}
|
|
1233
|
+
* accepts any 0.x.y — so events already on disk keep validating, and are not
|
|
1234
|
+
* rewritten in place (a session IS re-derived, and restamped, when its source
|
|
1235
|
+
* log grows). The 0.3.0 narrowing is what a stored value IS checked against,
|
|
1236
|
+
* which is why it had to be empty of real documents before it could land.
|
|
1237
|
+
*
|
|
1238
|
+
* The 0.3.0 timestamp narrowing is shared, so the other durable documents
|
|
1239
|
+
* (manifest, session, task, approval) bump alongside it. The two caches
|
|
1240
|
+
* (`status`, `task-index`) are rebuilt rather than versioned.
|
|
1196
1241
|
*/
|
|
1197
|
-
declare const EVENT_SCHEMA_VERSION: "0.
|
|
1242
|
+
declare const EVENT_SCHEMA_VERSION: "0.3.0";
|
|
1198
1243
|
declare const SessionStartedEventSchema: z.ZodObject<{
|
|
1199
1244
|
schema_version: z.ZodString;
|
|
1200
1245
|
id: z.ZodString & z.ZodType<`evt_${string}`, string, z.core.$ZodTypeInternals<`evt_${string}`, string>>;
|
|
@@ -1911,747 +1956,951 @@ declare function replayEvents(sessionDir: string, options?: ReplayOptions): Asyn
|
|
|
1911
1956
|
declare function readAllEvents(sessionDir: string, options?: ReplayOptions): Promise<Event[]>;
|
|
1912
1957
|
|
|
1913
1958
|
/**
|
|
1914
|
-
*
|
|
1915
|
-
* once in the manifest's `repos` list; the capture config (`source_roots`) must
|
|
1916
|
-
* cover every declared repo. This computes the drift between the two so
|
|
1917
|
-
* `basou project check` can surface a declared repo that is NOT being captured
|
|
1918
|
-
* — the class of bug where a companion repo was wired into the workspace but
|
|
1919
|
-
* never added to `source_roots`, so its work silently fell out of capture.
|
|
1959
|
+
* `schema_version` stamped on NEWLY WRITTEN `.basou/sessions/<id>/session.yaml`.
|
|
1920
1960
|
*
|
|
1921
|
-
*
|
|
1922
|
-
*
|
|
1923
|
-
*
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
*
|
|
1928
|
-
*
|
|
1929
|
-
* `ja` for a single audience, `en+ja` when both are served.
|
|
1930
|
-
*/
|
|
1931
|
-
type RepoLanguage = "en" | "ja" | "en+ja";
|
|
1932
|
-
/** A published surface a repo emits: a deployed website or a package registry. */
|
|
1933
|
-
type PublishKind = "web" | "npm";
|
|
1934
|
-
/**
|
|
1935
|
-
* Where a repo's agent instruction files live (the instruction-source axis),
|
|
1936
|
-
* independent of visibility / language / publishes. `hub` is basou's native,
|
|
1937
|
-
* generated hub-and-spoke topology (canonical in the anchor, gitignored symlinks
|
|
1938
|
-
* in each repo); `self` is the additive opt-in where the canonical AGENTS.md is a
|
|
1939
|
-
* regular committed file in the repo itself and basou stays hands-off about its
|
|
1940
|
-
* content. See {@link instructionMode} for the default (absent => `hub`).
|
|
1941
|
-
*/
|
|
1942
|
-
type RepoInstructions = "hub" | "self";
|
|
1943
|
-
/**
|
|
1944
|
-
* One published surface. Its visibility and language are INDEPENDENT of the
|
|
1945
|
-
* source repo's: a private repo commonly publishes a public website. Both are
|
|
1946
|
-
* optional so a surface can be declared
|
|
1947
|
-
* before those facts are pinned down (mirroring how `adopt` leaves repo
|
|
1948
|
-
* visibility unset for the operator to fill in).
|
|
1949
|
-
*/
|
|
1950
|
-
type PublishTarget = {
|
|
1951
|
-
kind: PublishKind;
|
|
1952
|
-
visibility?: RepoVisibility | undefined;
|
|
1953
|
-
language?: RepoLanguage | undefined;
|
|
1954
|
-
};
|
|
1955
|
-
type RepoEntry = {
|
|
1956
|
-
/** Path relative to the manifest repo root (e.g. ".", "../takuhon"). */
|
|
1957
|
-
path: string;
|
|
1958
|
-
visibility?: RepoVisibility | undefined;
|
|
1959
|
-
/** Source language (commits/comments/code, read by contributors). Independent of visibility. */
|
|
1960
|
-
language?: RepoLanguage | undefined;
|
|
1961
|
-
/** Published surfaces this repo emits (opt-in; absent for a repo that publishes nothing). */
|
|
1962
|
-
publishes?: PublishTarget[] | undefined;
|
|
1963
|
-
/**
|
|
1964
|
-
* Instruction-source mode. Absent => `hub` (basou's native generated topology),
|
|
1965
|
-
* so an existing roster's behavior is unchanged. `self` opts the repo out of
|
|
1966
|
-
* generation: its AGENTS.md is a hand-authored committed file and basou stays
|
|
1967
|
-
* hands-off. Resolve the effective mode with {@link instructionMode}.
|
|
1968
|
-
*/
|
|
1969
|
-
instructions?: RepoInstructions | undefined;
|
|
1970
|
-
};
|
|
1971
|
-
/**
|
|
1972
|
-
* The effective instruction-source mode for a repo: the declared `instructions`,
|
|
1973
|
-
* defaulting to `hub` when absent. The default is the single guarantee that an
|
|
1974
|
-
* existing roster (which has no `instructions` field) keeps basou's current
|
|
1975
|
-
* hub-and-spoke behavior byte-for-byte — every generator branches on this, never
|
|
1976
|
-
* on the raw optional field, so "absent => hub" is decided in exactly one place.
|
|
1961
|
+
* 0.2.0 requires seconds in every timestamp. That NARROWS the field's domain,
|
|
1962
|
+
* which §7.3 forbids except under the vacuous-narrowing rule the same section
|
|
1963
|
+
* states: no value basou has ever written omits seconds, so the set of
|
|
1964
|
+
* documents this refuses is empty. See `docs/spec/schemas.md` for the read
|
|
1965
|
+
* rule and the measurement. The narrowing is shared with the event format, so
|
|
1966
|
+
* every durable document bumps together.
|
|
1967
|
+
*
|
|
1968
|
+
* Note: basou writes this document.
|
|
1977
1969
|
*/
|
|
1978
|
-
declare
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
};
|
|
1970
|
+
declare const SESSION_SCHEMA_VERSION: "0.2.0";
|
|
1971
|
+
/** Session lifecycle states. */
|
|
1972
|
+
declare const SessionStatusSchema: z.ZodEnum<{
|
|
1973
|
+
initialized: "initialized";
|
|
1974
|
+
running: "running";
|
|
1975
|
+
waiting_approval: "waiting_approval";
|
|
1976
|
+
completed: "completed";
|
|
1977
|
+
failed: "failed";
|
|
1978
|
+
interrupted: "interrupted";
|
|
1979
|
+
imported: "imported";
|
|
1980
|
+
archived: "archived";
|
|
1981
|
+
}>;
|
|
1982
|
+
/** Inferred runtime type for {@link SessionStatusSchema}. */
|
|
1983
|
+
type SessionStatus = z.infer<typeof SessionStatusSchema>;
|
|
1993
1984
|
/**
|
|
1994
|
-
*
|
|
1995
|
-
*
|
|
1996
|
-
*
|
|
1997
|
-
*
|
|
1998
|
-
*
|
|
1985
|
+
* Source kind that produced the session.
|
|
1986
|
+
*
|
|
1987
|
+
* - `claude-code-adapter` — a live `basou run claude-code` process wrap.
|
|
1988
|
+
* - `claude-code-import` — derived after the fact from a Claude Code native
|
|
1989
|
+
* transcript (`~/.claude/projects/*.jsonl`) by `basou import claude-code`.
|
|
1990
|
+
* - `codex-adapter` — a live `basou run codex` process wrap.
|
|
1991
|
+
* - `codex-import` — derived after the fact from an OpenAI Codex native
|
|
1992
|
+
* rollout log (date-partitioned `~/.codex/sessions`) by `basou import codex`.
|
|
1993
|
+
* - `import` — a round-trip of a Basou-format export (`basou session import`).
|
|
1994
|
+
* - `human` / `terminal` — manually-authored / terminal-recorded sessions.
|
|
1999
1995
|
*/
|
|
2000
|
-
declare
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
/** Declared repo paths (normalized) that were appended because `source_roots` did not cover them. */
|
|
2012
|
-
added: string[];
|
|
2013
|
-
/** True when `source_roots` already covers every declared repo (`next` equals the current list). */
|
|
2014
|
-
unchanged: boolean;
|
|
2015
|
-
};
|
|
1996
|
+
declare const SessionSourceKindSchema: z.ZodEnum<{
|
|
1997
|
+
"claude-code-adapter": "claude-code-adapter";
|
|
1998
|
+
import: "import";
|
|
1999
|
+
"claude-code-import": "claude-code-import";
|
|
2000
|
+
"codex-adapter": "codex-adapter";
|
|
2001
|
+
"codex-import": "codex-import";
|
|
2002
|
+
human: "human";
|
|
2003
|
+
terminal: "terminal";
|
|
2004
|
+
}>;
|
|
2005
|
+
/** Inferred runtime type for {@link SessionSourceKindSchema}. */
|
|
2006
|
+
type SessionSourceKind = z.infer<typeof SessionSourceKindSchema>;
|
|
2016
2007
|
/**
|
|
2017
|
-
*
|
|
2018
|
-
*
|
|
2019
|
-
* project; this is the actuator behind `basou project sync`, computing the
|
|
2020
|
-
* additive reconciliation so every declared repo is captured.
|
|
2008
|
+
* Optional per-session metrics, computed at import time from the source tool's
|
|
2009
|
+
* native log. Two groups, both optional because not every source records them:
|
|
2021
2010
|
*
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
2024
|
-
*
|
|
2025
|
-
*
|
|
2026
|
-
* the
|
|
2027
|
-
*
|
|
2011
|
+
* - Model-usage rollup (`*_tokens`): the transcript carries per-message token
|
|
2012
|
+
* usage; these are the session totals. `reasoning_output_tokens` is
|
|
2013
|
+
* Codex-only, and live `run`/`exec` sessions carry no token usage at all.
|
|
2014
|
+
* - Engaged-time metrics (`active_*`): the billing-oriented active time derived
|
|
2015
|
+
* from the session's genuine engagement timestamps (conversation turns plus
|
|
2016
|
+
* action events), with idle gaps capped. `active_intervals` are the merged
|
|
2017
|
+
* wall-clock ranges (so cross-session totals can de-duplicate overlapping
|
|
2018
|
+
* work by interval union); `active_time_ms` is their summed duration;
|
|
2019
|
+
* `active_gap_cap_ms` and `active_time_method` lock the methodology so the
|
|
2020
|
+
* stored numbers stay interpretable if the method changes later. When a
|
|
2021
|
+
* source records explicit per-turn intervals (Codex), `active_time_method` is
|
|
2022
|
+
* `turn-intervals` and the in-turn time is the log's real wall-clock span
|
|
2023
|
+
* rather than a gap-capped approximation; the active semantics are unchanged.
|
|
2024
|
+
* - `machine_active_time_ms`: model compute time — the summed duration of the
|
|
2025
|
+
* source's per-turn spans (Codex `task_complete.duration_ms`), a SUBSET of a
|
|
2026
|
+
* single session's engaged active time. Unlike `active_intervals` it is a
|
|
2027
|
+
* plain sum, NOT wall-clock-deduplicated, so two concurrent sessions can sum
|
|
2028
|
+
* past their billable (union) active wall-clock — that is intended (two models
|
|
2029
|
+
* working at once did two machine-hours in one wall-clock hour). Captured only
|
|
2030
|
+
* for sources that record per-turn duration (Codex); absent otherwise.
|
|
2028
2031
|
*
|
|
2029
|
-
*
|
|
2030
|
-
*
|
|
2031
|
-
*
|
|
2032
|
+
* Absent on sessions imported before a given field existed (re-import to
|
|
2033
|
+
* backfill). Live sessions carry no engaged-time metrics and fall back to
|
|
2034
|
+
* event-derived active time at stats time.
|
|
2032
2035
|
*/
|
|
2033
|
-
declare
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2036
|
+
declare const SessionMetricsSchema: z.ZodObject<{
|
|
2037
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2038
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2039
|
+
cached_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2040
|
+
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2041
|
+
active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2042
|
+
active_intervals: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2043
|
+
start: z.ZodString;
|
|
2044
|
+
end: z.ZodString;
|
|
2045
|
+
}, z.core.$loose>>>;
|
|
2046
|
+
active_gap_cap_ms: z.ZodOptional<z.ZodNumber>;
|
|
2047
|
+
active_time_method: z.ZodOptional<z.ZodString>;
|
|
2048
|
+
machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2049
|
+
}, z.core.$loose>;
|
|
2050
|
+
/** Inferred runtime type for {@link SessionMetricsSchema}. */
|
|
2051
|
+
type SessionMetrics = z.infer<typeof SessionMetricsSchema>;
|
|
2037
2052
|
/**
|
|
2038
|
-
*
|
|
2039
|
-
*
|
|
2040
|
-
*
|
|
2041
|
-
*
|
|
2053
|
+
* Tamper-evidence head anchor for a session whose `events.jsonl` is hash
|
|
2054
|
+
* chained: `head_hash` is the hex sha-256 of the last written event line
|
|
2055
|
+
* (excluding the trailing newline), `event_count` the number of chained lines.
|
|
2056
|
+
* Written by the import / in-place re-import writers and, for a live session
|
|
2057
|
+
* (`exec` / `run` / ad-hoc), by the finalize once it reaches a terminal status.
|
|
2058
|
+
* Absent on a still-live session (the anchor is stamped at finalize) and on a
|
|
2059
|
+
* pre-feature unchained session. Additive optional => no schema_version bump.
|
|
2060
|
+
* `.strict()` because the writers fully own the shape.
|
|
2042
2061
|
*/
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
};
|
|
2050
|
-
type RosterAdoptionPlan = {
|
|
2051
|
-
/** Proposed `repos` entries: the candidates that are git repos (visibility left unset for the operator). */
|
|
2052
|
-
repos: RepoEntry[];
|
|
2053
|
-
/** Candidates excluded from the roster, with why (a non-repo directory, or an unresolvable path). */
|
|
2054
|
-
excluded: {
|
|
2055
|
-
path: string;
|
|
2056
|
-
kind: Exclude<AdoptCandidateKind, "repo">;
|
|
2057
|
-
}[];
|
|
2058
|
-
};
|
|
2062
|
+
declare const SessionIntegritySchema: z.ZodObject<{
|
|
2063
|
+
head_hash: z.ZodString;
|
|
2064
|
+
event_count: z.ZodNumber;
|
|
2065
|
+
}, z.core.$strict>;
|
|
2066
|
+
/** Inferred runtime type for {@link SessionIntegritySchema}. */
|
|
2067
|
+
type SessionIntegrity = z.infer<typeof SessionIntegritySchema>;
|
|
2059
2068
|
/**
|
|
2060
|
-
*
|
|
2061
|
-
*
|
|
2062
|
-
*
|
|
2063
|
-
* `kind` is the caller's job, so this stays testable without disk I/O.
|
|
2064
|
-
*
|
|
2065
|
-
* A git repo becomes a roster entry (path only; visibility is left unset because
|
|
2066
|
-
* it is a human judgment, kept independent of the other axes). A non-repo
|
|
2067
|
-
* (commonly the generated workspace view) or an unresolvable path is excluded and
|
|
2068
|
-
* reported, so the operator sees what was dropped and why before editing. Repo
|
|
2069
|
-
* paths are deduped by normalized form, preserving the first declared form and
|
|
2070
|
-
* order.
|
|
2069
|
+
* Schema for `.basou/sessions/<session_id>/session.yaml`. The minimal
|
|
2070
|
+
* session document carries the actual fields nested under the outer
|
|
2071
|
+
* `session:` key.
|
|
2071
2072
|
*/
|
|
2072
|
-
declare
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2073
|
+
declare const SessionSchema: z.ZodObject<{
|
|
2074
|
+
schema_version: z.ZodString;
|
|
2075
|
+
session: z.ZodObject<{
|
|
2076
|
+
id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
|
|
2077
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2078
|
+
task_id: z.ZodOptional<z.ZodNullable<z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>>>;
|
|
2079
|
+
workspace_id: z.ZodString & z.ZodType<`ws_${string}`, string, z.core.$ZodTypeInternals<`ws_${string}`, string>>;
|
|
2080
|
+
source: z.ZodObject<{
|
|
2081
|
+
kind: z.ZodEnum<{
|
|
2082
|
+
"claude-code-adapter": "claude-code-adapter";
|
|
2083
|
+
import: "import";
|
|
2084
|
+
"claude-code-import": "claude-code-import";
|
|
2085
|
+
"codex-adapter": "codex-adapter";
|
|
2086
|
+
"codex-import": "codex-import";
|
|
2087
|
+
human: "human";
|
|
2088
|
+
terminal: "terminal";
|
|
2089
|
+
}>;
|
|
2090
|
+
version: z.ZodLiteral<"0.1.0">;
|
|
2091
|
+
external_id: z.ZodOptional<z.ZodString>;
|
|
2092
|
+
source_size_bytes: z.ZodOptional<z.ZodNumber>;
|
|
2093
|
+
}, z.core.$loose>;
|
|
2094
|
+
started_at: z.ZodString;
|
|
2095
|
+
ended_at: z.ZodOptional<z.ZodString>;
|
|
2096
|
+
status: z.ZodEnum<{
|
|
2097
|
+
initialized: "initialized";
|
|
2098
|
+
running: "running";
|
|
2099
|
+
waiting_approval: "waiting_approval";
|
|
2100
|
+
completed: "completed";
|
|
2101
|
+
failed: "failed";
|
|
2102
|
+
interrupted: "interrupted";
|
|
2103
|
+
imported: "imported";
|
|
2104
|
+
archived: "archived";
|
|
2105
|
+
}>;
|
|
2106
|
+
working_directory: z.ZodString;
|
|
2107
|
+
invocation: z.ZodObject<{
|
|
2108
|
+
command: z.ZodString;
|
|
2109
|
+
args: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2110
|
+
exit_code: z.ZodNullable<z.ZodNumber>;
|
|
2111
|
+
}, z.core.$loose>;
|
|
2112
|
+
related_files: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2113
|
+
events_log: z.ZodDefault<z.ZodString>;
|
|
2114
|
+
summary: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2115
|
+
metrics: z.ZodOptional<z.ZodObject<{
|
|
2116
|
+
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2117
|
+
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2118
|
+
cached_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2119
|
+
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2120
|
+
active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2121
|
+
active_intervals: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2122
|
+
start: z.ZodString;
|
|
2123
|
+
end: z.ZodString;
|
|
2124
|
+
}, z.core.$loose>>>;
|
|
2125
|
+
active_gap_cap_ms: z.ZodOptional<z.ZodNumber>;
|
|
2126
|
+
active_time_method: z.ZodOptional<z.ZodString>;
|
|
2127
|
+
machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2128
|
+
}, z.core.$loose>>;
|
|
2129
|
+
integrity: z.ZodOptional<z.ZodObject<{
|
|
2130
|
+
head_hash: z.ZodString;
|
|
2131
|
+
event_count: z.ZodNumber;
|
|
2132
|
+
}, z.core.$strict>>;
|
|
2133
|
+
}, z.core.$loose>;
|
|
2134
|
+
}, z.core.$loose>;
|
|
2135
|
+
/** Inferred runtime type for {@link SessionSchema}. */
|
|
2136
|
+
type Session = z.infer<typeof SessionSchema>;
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* Threshold above which a still-`running` session with no `session_ended`
|
|
2140
|
+
* event is flagged suspect.
|
|
2077
2141
|
*
|
|
2078
|
-
*
|
|
2079
|
-
*
|
|
2080
|
-
*
|
|
2081
|
-
* paths) always passes through verbatim — only the tool-generated strings are
|
|
2082
|
-
* localized, which is exactly the split this type exists to keep honest.
|
|
2142
|
+
* 24h: long enough that an active long-running session will not be flagged,
|
|
2143
|
+
* short enough that an abandoned process is surfaced within a working day.
|
|
2144
|
+
* Tunable via CLI option in a later step (continuation backlog #23).
|
|
2083
2145
|
*/
|
|
2084
|
-
|
|
2146
|
+
declare const STUCK_THRESHOLD_MS: number;
|
|
2147
|
+
type SuspectReason = "events_say_ended_but_yaml_running" | "running_no_end_event";
|
|
2148
|
+
type SessionEntry = {
|
|
2149
|
+
sessionId: string;
|
|
2150
|
+
session: Session;
|
|
2151
|
+
suspect: boolean;
|
|
2152
|
+
suspectReason: SuspectReason | null;
|
|
2153
|
+
/**
|
|
2154
|
+
* The trail store this entry was read from. Its `sessions` directory locates
|
|
2155
|
+
* the session's `events.jsonl`, so a federated caller can replay events from
|
|
2156
|
+
* the store the session actually lives in (not the local store). For a plain
|
|
2157
|
+
* local load this is the `paths` passed to {@link loadSessionEntries}.
|
|
2158
|
+
*/
|
|
2159
|
+
sourceRoot: BasouPaths;
|
|
2160
|
+
/**
|
|
2161
|
+
* Federation host label from the registry (`~/.basou/hosts.yaml`), or `null`
|
|
2162
|
+
* for the local store. Surfaced by orientation so a merged, multi-host view
|
|
2163
|
+
* can attribute the latest session / decision / next-step to its host.
|
|
2164
|
+
*/
|
|
2165
|
+
host: string | null;
|
|
2166
|
+
};
|
|
2085
2167
|
/**
|
|
2086
|
-
*
|
|
2087
|
-
* the language of its ANCHOR repo (the `repos[]` entry whose path is `.`).
|
|
2168
|
+
* Per-session degradation reason emitted by {@link loadSessionEntries.onSkip}.
|
|
2088
2169
|
*
|
|
2089
|
-
*
|
|
2090
|
-
*
|
|
2091
|
-
* -
|
|
2092
|
-
*
|
|
2093
|
-
*
|
|
2094
|
-
*
|
|
2170
|
+
* - `session_yaml_missing` (ENOENT) and `session_yaml_invalid` (parse or schema
|
|
2171
|
+
* failure) both omit the entry from the result.
|
|
2172
|
+
* - `events_jsonl_unreadable` still pushes the entry with `suspect=false` so
|
|
2173
|
+
* the session row remains visible to the caller; only the suspect check is
|
|
2174
|
+
* degraded. Matches the existing CLI behaviour at
|
|
2175
|
+
* `packages/cli/src/commands/session.ts` (suspect-check stderr warning).
|
|
2176
|
+
*/
|
|
2177
|
+
type SessionSkipReason = "session_yaml_missing" | "session_yaml_invalid" | "events_jsonl_unreadable";
|
|
2178
|
+
type LoadSessionEntriesOptions = {
|
|
2179
|
+
/**
|
|
2180
|
+
* Single `now` shared across every {@link classifySuspect} call so that
|
|
2181
|
+
* sessions classified back-to-back observe the same instant. Avoids
|
|
2182
|
+
* boundary races where a session at age ≈ 24h would flip between calls.
|
|
2183
|
+
*/
|
|
2184
|
+
now: Date;
|
|
2185
|
+
onWarning?: (warning: ReplayWarning, sessionId: string) => void;
|
|
2186
|
+
onSkip?: (sessionId: string, reason: SessionSkipReason) => void;
|
|
2187
|
+
};
|
|
2188
|
+
/**
|
|
2189
|
+
* A trail store to read in a federated load, tagged with its host label.
|
|
2190
|
+
* `host: null` denotes the local store; a non-null label comes from the host
|
|
2191
|
+
* registry (`~/.basou/hosts.yaml`). `paths` is where that store is reachable
|
|
2192
|
+
* as a local path on this machine (an SSHFS mount, an rsync mirror, etc.) —
|
|
2193
|
+
* basou itself never performs any network I/O to obtain it.
|
|
2194
|
+
*/
|
|
2195
|
+
type FederatedRoot = {
|
|
2196
|
+
paths: BasouPaths;
|
|
2197
|
+
host: string | null;
|
|
2198
|
+
};
|
|
2199
|
+
type LoadFederatedOptions = LoadSessionEntriesOptions & {
|
|
2200
|
+
/**
|
|
2201
|
+
* Called when a NON-local root cannot be enumerated (present-but-unreadable
|
|
2202
|
+
* mount, permission error). That root is skipped best-effort so the local
|
|
2203
|
+
* store and other roots still load. The local root (`host: null`) is never
|
|
2204
|
+
* degraded here — its errors propagate, preserving single-store behaviour.
|
|
2205
|
+
* (An absent root path is not an error: {@link enumerateSessionDirs} returns
|
|
2206
|
+
* `[]` on ENOENT, so a dropped mount is simply an empty host.)
|
|
2207
|
+
*/
|
|
2208
|
+
onRootUnavailable?: (host: string, error: unknown) => void;
|
|
2209
|
+
};
|
|
2210
|
+
/**
|
|
2211
|
+
* List session directory names under `paths.sessions`, ULID ascending.
|
|
2095
2212
|
*
|
|
2096
|
-
*
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
*
|
|
2213
|
+
* - Returns `[]` when the sessions directory does not exist (empty workspace
|
|
2214
|
+
* or pre-init state).
|
|
2215
|
+
* - Throws `Error("Failed to enumerate sessions", { cause })` on other I/O.
|
|
2216
|
+
* - Only directories are returned (`.gitkeep` and other files are filtered).
|
|
2217
|
+
*
|
|
2218
|
+
* Sort order is `Array.prototype.sort()` default (Unicode code-point
|
|
2219
|
+
* compare). ULIDs are Crockford base32 in uppercase, so the natural sort
|
|
2220
|
+
* is also chronological session-start order.
|
|
2100
2221
|
*/
|
|
2101
|
-
declare function
|
|
2222
|
+
declare function enumerateSessionDirs(paths: BasouPaths): Promise<string[]>;
|
|
2102
2223
|
/**
|
|
2103
|
-
*
|
|
2104
|
-
*
|
|
2105
|
-
*
|
|
2106
|
-
*
|
|
2224
|
+
* Read and validate `<paths.sessions>/<sessionId>/session.yaml`.
|
|
2225
|
+
*
|
|
2226
|
+
* - Re-throws the yaml-store fixed-message `"YAML file not found"` for
|
|
2227
|
+
* ENOENT so the caller can branch on it.
|
|
2228
|
+
* - Throws `Error("Failed to read session.yaml", { cause })` for parse
|
|
2229
|
+
* failures and schema violations (cause is either the YAML parser error
|
|
2230
|
+
* or the zod error).
|
|
2107
2231
|
*/
|
|
2108
|
-
declare function
|
|
2232
|
+
declare function readSessionYaml(paths: BasouPaths, sessionId: string): Promise<Session>;
|
|
2109
2233
|
/**
|
|
2110
|
-
*
|
|
2111
|
-
*
|
|
2112
|
-
*
|
|
2113
|
-
*
|
|
2234
|
+
* Apply a terminal-status mutation to a live session's `session.yaml` AND, in
|
|
2235
|
+
* the same locked write, stamp the tamper-evidence head anchor derived from the
|
|
2236
|
+
* on-disk `events.jsonl` tail. Used by the `exec` / `run` orchestrators for
|
|
2237
|
+
* BOTH terminal writers (the normal end-of-run finalize and the spawn-failure
|
|
2238
|
+
* `failed` finalize).
|
|
2114
2239
|
*
|
|
2115
|
-
*
|
|
2116
|
-
*
|
|
2117
|
-
*
|
|
2118
|
-
*
|
|
2119
|
-
*
|
|
2240
|
+
* Why locked + anchor-from-tail: live appends chain the LOG only and leave the
|
|
2241
|
+
* anchor for finalize. Reading the final tail under the session lock means a
|
|
2242
|
+
* foreign line appended just before finalize (e.g. a `decision record` attached
|
|
2243
|
+
* to a still-running session) is included in the anchor, and a foreign attach
|
|
2244
|
+
* that arrives after the terminal status is set is rejected by the attach gate
|
|
2245
|
+
* — so the anchor can never disagree with the at-rest log. The whole-document
|
|
2246
|
+
* read-modify-write also preserves any field a foreign locked writer set (e.g.
|
|
2247
|
+
* a task attach's `task_id`).
|
|
2248
|
+
*
|
|
2249
|
+
* The anchor is written only when the log is actually chained with at least one
|
|
2250
|
+
* line; a legacy unchained session (and an empty log) is left with no
|
|
2251
|
+
* `integrity` anchor, matching the import writers. The mutator receives the
|
|
2252
|
+
* full {@link Session} document and typically sets
|
|
2253
|
+
* `session.session.status` / `ended_at` / `invocation.exit_code` /
|
|
2254
|
+
* `related_files`.
|
|
2255
|
+
*
|
|
2256
|
+
* Throws the {@link inspectChainTail} errors (torn / mixed log), the
|
|
2257
|
+
* {@link readSessionYaml} errors, a zod error if the mutation produces an
|
|
2258
|
+
* invalid document, or `Error("Failed to overwrite YAML file")` on a disk
|
|
2259
|
+
* failure.
|
|
2120
2260
|
*/
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2261
|
+
declare function finalizeSessionYaml(paths: BasouPaths, sessionId: string, mutate: (session: Session) => void): Promise<void>;
|
|
2262
|
+
/**
|
|
2263
|
+
* Classify a `running` session as suspect using one of two rules:
|
|
2264
|
+
*
|
|
2265
|
+
* - Rule A (`events_say_ended_but_yaml_running`): events.jsonl contains a
|
|
2266
|
+
* `session_ended` event but the session.yaml is still `running`. The
|
|
2267
|
+
* session ended cleanly in the event log but the YAML write was lost or
|
|
2268
|
+
* never reached.
|
|
2269
|
+
* - Rule B (`running_no_end_event`): no `session_ended` event and the last
|
|
2270
|
+
* event is older than {@link STUCK_THRESHOLD_MS}. The process likely
|
|
2271
|
+
* crashed or was killed.
|
|
2272
|
+
*
|
|
2273
|
+
* Sessions that are not `running` are never suspect.
|
|
2274
|
+
*
|
|
2275
|
+
* I/O failure on events.jsonl is re-thrown unwrapped so the caller can
|
|
2276
|
+
* degrade with a warning instead of treating the session as healthy. The
|
|
2277
|
+
* caller is also responsible for surfacing replay warnings via `onWarning`.
|
|
2278
|
+
*/
|
|
2279
|
+
declare function classifySuspect(paths: BasouPaths, sessionId: string, session: Session, now: Date, onWarning?: (warning: ReplayWarning) => void): Promise<{
|
|
2280
|
+
suspect: boolean;
|
|
2281
|
+
suspectReason: SuspectReason | null;
|
|
2282
|
+
}>;
|
|
2283
|
+
declare function loadSessionEntries(paths: BasouPaths, options: LoadSessionEntriesOptions): Promise<SessionEntry[]>;
|
|
2284
|
+
/**
|
|
2285
|
+
* Federated load across multiple trail stores. Each root's sessions are tagged
|
|
2286
|
+
* with that root's host label and `sourceRoot`, so a caller replays events from
|
|
2287
|
+
* the store the session lives in. De-duped by `sessionId` (a per-host random
|
|
2288
|
+
* ULID), then by `source.external_id` when present — first occurrence wins, so
|
|
2289
|
+
* pass the local root FIRST to keep it authoritative (e.g. over a re-imported
|
|
2290
|
+
* copy of the same vendor session on another host). A non-local root that
|
|
2291
|
+
* cannot be enumerated is reported via `onRootUnavailable` and skipped; the
|
|
2292
|
+
* local root's errors propagate, matching {@link loadSessionEntries}.
|
|
2293
|
+
*/
|
|
2294
|
+
declare function loadFederatedSessionEntries(roots: ReadonlyArray<FederatedRoot>, options: LoadFederatedOptions): Promise<SessionEntry[]>;
|
|
2295
|
+
|
|
2296
|
+
/**
|
|
2297
|
+
* Decision-gap surfacer: which recorded decisions are still waiting for someone.
|
|
2298
|
+
*
|
|
2299
|
+
* The rule it applies, stated by the report that motivated it: a decision that
|
|
2300
|
+
* changes what gets built should have a task carrying it, and the ones with no
|
|
2301
|
+
* task are listed. It reads only captured provenance and writes nothing.
|
|
2302
|
+
*
|
|
2303
|
+
* The question is a RELATION — "is any task carrying this decision" — and the
|
|
2304
|
+
* text scan below is only today's way of answering it. Stating it that way is
|
|
2305
|
+
* deliberate: when `task_created` grows a field naming the decision it serves,
|
|
2306
|
+
* honouring that field answers the same question better and is an
|
|
2307
|
+
* implementation change, where redefining the question would not be.
|
|
2308
|
+
*
|
|
2309
|
+
* Two properties are load-bearing:
|
|
2310
|
+
*
|
|
2311
|
+
* - Nothing here reads what a decision MEANS, so the answer does not depend on
|
|
2312
|
+
* a model and does not change between runs over the same store.
|
|
2313
|
+
* - The default is fail-closed: a decision with no task is listed. An opt-in
|
|
2314
|
+
* mark ("this one produces work") was rejected upstream because forgetting
|
|
2315
|
+
* the mark is the same failure the report exists to catch.
|
|
2316
|
+
*
|
|
2317
|
+
* Fail-closed only pays for itself if the list is drainable, so the population
|
|
2318
|
+
* is cut on four structural grounds — a timestamp, a `source`, a `kind`, and a
|
|
2319
|
+
* void. None requires reading meaning, and each is reported as a count so the
|
|
2320
|
+
* cut is never silent:
|
|
2321
|
+
*
|
|
2322
|
+
* - {@link DECISION_GAPS_EPOCH}: decisions predating this feature are out of
|
|
2323
|
+
* scope. Applying the rule to a whole history measured ~1450 entries on the
|
|
2324
|
+
* store it was built against, which buries the signal on day one.
|
|
2325
|
+
* - {@link LOCAL_CLI_EVENT_SOURCE}: only decisions somebody recorded by
|
|
2326
|
+
* running basou (`basou decision capture` or `basou decision record`), as
|
|
2327
|
+
* opposed to ones a reader derived. An importer derives decisions from a
|
|
2328
|
+
* transcript's in-conversation questions ("how far should I implement? ->
|
|
2329
|
+
* findings 1 and 3"), which were 70% of that store's decisions and 0 of the
|
|
2330
|
+
* ones any task carried. Those are answers given while working, not plans
|
|
2331
|
+
* anybody ratified.
|
|
2332
|
+
* - `kind: "track"`: a track is ALREADY resurfaced, every session, until it is
|
|
2333
|
+
* voided — orientation and handoff both carry it under "open tracks". For a
|
|
2334
|
+
* track the premise "recorded, then never surfaced again" is false by
|
|
2335
|
+
* construction, so listing it here says nothing the reader is not already
|
|
2336
|
+
* shown, and it measured 27-45% of the list.
|
|
2337
|
+
* - voided: `basou decision void` is the closing verb this product tells the
|
|
2338
|
+
* operator to use, and a direction no longer in force is not waiting for
|
|
2339
|
+
* anyone. Honouring it everywhere gives the operator ONE verb that closes;
|
|
2340
|
+
* refusing it here would leave a list drainable only by writing a sham task.
|
|
2341
|
+
*
|
|
2342
|
+
* What it will not do is decide a decision's fate on anything it cannot check.
|
|
2343
|
+
* A task naming an id that no decision in the store has does NOT count as
|
|
2344
|
+
* carrying it, and a store it could only partly read says so rather than
|
|
2345
|
+
* reporting a clean answer over the part it managed.
|
|
2346
|
+
*/
|
|
2347
|
+
/**
|
|
2348
|
+
* Start of the population: decisions recorded before this instant are out of
|
|
2349
|
+
* scope, whatever else is true of them.
|
|
2350
|
+
*
|
|
2351
|
+
* A fixed constant rather than per-workspace state, so every workspace answers
|
|
2352
|
+
* the same question and nothing has to be initialised or migrated. The value is
|
|
2353
|
+
* the instant this was written; a release landing later, or a workspace first
|
|
2354
|
+
* running it later, only means that run starts with the decisions recorded in
|
|
2355
|
+
* between, and {@link DecisionGapsSummary.scope} reports the boundary on every
|
|
2356
|
+
* run so the head start is never silent. `--since` overrides it.
|
|
2357
|
+
*/
|
|
2358
|
+
declare const DECISION_GAPS_EPOCH = "2026-09-18T12:00:00.000Z";
|
|
2359
|
+
/** A decision in the population that no task carries. */
|
|
2360
|
+
type DecisionGap = {
|
|
2361
|
+
decisionId: string;
|
|
2362
|
+
title: string;
|
|
2363
|
+
recordedAt: string;
|
|
2364
|
+
sessionId: string;
|
|
2365
|
+
};
|
|
2366
|
+
/** The population's boundaries, as the run actually applied them. */
|
|
2367
|
+
type DecisionGapsScope = {
|
|
2368
|
+
/** Decisions recorded before this instant are out of scope. */
|
|
2369
|
+
start: string;
|
|
2370
|
+
/** Only decisions this event source recorded are in scope. */
|
|
2371
|
+
source: string;
|
|
2222
2372
|
};
|
|
2223
|
-
/** Look up the string table for a resolved view language. */
|
|
2224
|
-
declare function viewStrings(language: ViewLanguage): ViewStrings;
|
|
2225
2373
|
/**
|
|
2226
|
-
*
|
|
2227
|
-
*
|
|
2228
|
-
*
|
|
2229
|
-
* so its audience is that repo's declared audience: `ja` renders Japanese
|
|
2230
|
-
* (byte-identical to the pre-i18n output), `en` / `en+ja` / undeclared render
|
|
2231
|
-
* English (one content language per generated block; en is the shared floor).
|
|
2374
|
+
* Why decisions left the population, by ground. The grounds are applied in this
|
|
2375
|
+
* order and each decision is counted under the FIRST that excludes it, so these
|
|
2376
|
+
* partition the excluded set.
|
|
2232
2377
|
*/
|
|
2233
|
-
|
|
2378
|
+
type DecisionGapsExcluded = {
|
|
2379
|
+
/** Recorded before {@link DecisionGapsScope.start}. */
|
|
2380
|
+
byStart: number;
|
|
2381
|
+
/** Recorded by something other than {@link DecisionGapsScope.source}. */
|
|
2382
|
+
bySource: number;
|
|
2383
|
+
/** `kind: "track"` — already resurfaced every session until closed. */
|
|
2384
|
+
track: number;
|
|
2385
|
+
/** Closed with `basou decision void`. */
|
|
2386
|
+
voided: number;
|
|
2387
|
+
};
|
|
2234
2388
|
/**
|
|
2235
|
-
*
|
|
2236
|
-
*
|
|
2237
|
-
*
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2389
|
+
* What the run could not read. Every field here can only make {@link
|
|
2390
|
+
* DecisionGapsSummary.gaps} wrong in a way the reader cannot see, so a non-zero
|
|
2391
|
+
* count is reported rather than absorbed.
|
|
2392
|
+
*/
|
|
2393
|
+
type DecisionGapsIncomplete = {
|
|
2394
|
+
/**
|
|
2395
|
+
* Sessions this run could not read in full — a `session.yaml` that is missing
|
|
2396
|
+
* or does not validate, or an event log that failed to read.
|
|
2397
|
+
*
|
|
2398
|
+
* What was lost is not knowable from here: a log that fails partway through
|
|
2399
|
+
* has already yielded some events, so a session counted here may have
|
|
2400
|
+
* contributed everything, nothing, or part of what it holds. A decision of
|
|
2401
|
+
* theirs can therefore be missing from every count, and a void of theirs may
|
|
2402
|
+
* not have closed what it closes — so both a missing row and a wrongly
|
|
2403
|
+
* present one are possible.
|
|
2404
|
+
*/
|
|
2405
|
+
sessions: number;
|
|
2406
|
+
/** Task files that could not be read, so any decision they carry looks uncarried. */
|
|
2407
|
+
tasks: number;
|
|
2408
|
+
/**
|
|
2409
|
+
* Ids named by a task that no decision in the store has. Counted, and
|
|
2410
|
+
* deliberately NOT treated as carrying anything: a string nobody recorded
|
|
2411
|
+
* must not be able to take a decision off this list.
|
|
2412
|
+
*/
|
|
2413
|
+
unknownReferences: number;
|
|
2414
|
+
};
|
|
2415
|
+
type DecisionGapsSummary = {
|
|
2416
|
+
generatedAt: string;
|
|
2417
|
+
scope: DecisionGapsScope;
|
|
2418
|
+
/** Decisions with no task carrying them, newest first. Capped by `limit`. */
|
|
2419
|
+
gaps: DecisionGap[];
|
|
2420
|
+
/** Entries omitted from `gaps` by `limit`; 0 when nothing was cut. */
|
|
2421
|
+
truncated: number;
|
|
2422
|
+
/** Population members some task carries. */
|
|
2423
|
+
carried: number;
|
|
2424
|
+
/** `gaps.length + truncated + carried`. */
|
|
2425
|
+
populationCount: number;
|
|
2426
|
+
excluded: DecisionGapsExcluded;
|
|
2427
|
+
incomplete: DecisionGapsIncomplete;
|
|
2428
|
+
/** Task files read (live and archived). */
|
|
2429
|
+
tasksScanned: number;
|
|
2430
|
+
};
|
|
2431
|
+
type DecisionGapsInput = {
|
|
2432
|
+
paths: BasouPaths;
|
|
2433
|
+
nowIso: string;
|
|
2434
|
+
/** Defaults to {@link DECISION_GAPS_EPOCH}. */
|
|
2435
|
+
start?: string;
|
|
2436
|
+
/**
|
|
2437
|
+
* Maximum entries in `gaps`; the rest are counted in `truncated`. `0` yields
|
|
2438
|
+
* an empty `gaps` with everything in `truncated` — it is a cap of zero, not
|
|
2439
|
+
* "uncapped". Omit the field for uncapped. (The CLI's `--limit 0` means
|
|
2440
|
+
* uncapped and omits this.)
|
|
2441
|
+
*/
|
|
2442
|
+
limit?: number;
|
|
2443
|
+
onWarning?: (warning: ReplayWarning, sessionId: string) => void;
|
|
2444
|
+
onSessionSkip?: (sessionId: string, reason: SessionSkipReason) => void;
|
|
2445
|
+
};
|
|
2446
|
+
/**
|
|
2447
|
+
* Find decisions in the population that no task carries.
|
|
2241
2448
|
*
|
|
2242
|
-
*
|
|
2243
|
-
*
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2449
|
+
* Ordering is `recordedAt` descending with the decision id (a ULID, so
|
|
2450
|
+
* monotonic) as tie-breaker, giving a stable newest-first list.
|
|
2451
|
+
*/
|
|
2452
|
+
declare function findDecisionGaps(input: DecisionGapsInput): Promise<DecisionGapsSummary>;
|
|
2453
|
+
|
|
2454
|
+
/**
|
|
2455
|
+
* Project roster drift (the "saddle" model). A project's repos are DECLARED
|
|
2456
|
+
* once in the manifest's `repos` list; the capture config (`source_roots`) must
|
|
2457
|
+
* cover every declared repo. This computes the drift between the two so
|
|
2458
|
+
* `basou project check` can surface a declared repo that is NOT being captured
|
|
2459
|
+
* — the class of bug where a companion repo was wired into the workspace but
|
|
2460
|
+
* never added to `source_roots`, so its work silently fell out of capture.
|
|
2461
|
+
*
|
|
2462
|
+
* Pure: it compares declared relative paths against captured relative paths and
|
|
2463
|
+
* performs no filesystem or git I/O. Paths are compared as declared (both lists
|
|
2464
|
+
* use the same machine-portable relative-path form), not resolved on disk.
|
|
2465
|
+
*/
|
|
2466
|
+
type RepoVisibility = "public" | "private" | "future-public";
|
|
2467
|
+
/**
|
|
2468
|
+
* The audience-driven language axis. Independent of visibility: a private repo
|
|
2469
|
+
* can publish English content, a public repo can carry bilingual docs. `en` /
|
|
2470
|
+
* `ja` for a single audience, `en+ja` when both are served.
|
|
2471
|
+
*/
|
|
2472
|
+
type RepoLanguage = "en" | "ja" | "en+ja";
|
|
2473
|
+
/** A published surface a repo emits: a deployed website or a package registry. */
|
|
2474
|
+
type PublishKind = "web" | "npm";
|
|
2475
|
+
/**
|
|
2476
|
+
* Where a repo's agent instruction files live (the instruction-source axis),
|
|
2477
|
+
* independent of visibility / language / publishes. `hub` is basou's native,
|
|
2478
|
+
* generated hub-and-spoke topology (canonical in the anchor, gitignored symlinks
|
|
2479
|
+
* in each repo); `self` is the additive opt-in where the canonical AGENTS.md is a
|
|
2480
|
+
* regular committed file in the repo itself and basou stays hands-off about its
|
|
2481
|
+
* content. See {@link instructionMode} for the default (absent => `hub`).
|
|
2248
2482
|
*/
|
|
2249
|
-
|
|
2250
|
-
|
|
2483
|
+
type RepoInstructions = "hub" | "self";
|
|
2484
|
+
/**
|
|
2485
|
+
* One published surface. Its visibility and language are INDEPENDENT of the
|
|
2486
|
+
* source repo's: a private repo commonly publishes a public website. Both are
|
|
2487
|
+
* optional so a surface can be declared
|
|
2488
|
+
* before those facts are pinned down (mirroring how `adopt` leaves repo
|
|
2489
|
+
* visibility unset for the operator to fill in).
|
|
2490
|
+
*/
|
|
2491
|
+
type PublishTarget = {
|
|
2492
|
+
kind: PublishKind;
|
|
2493
|
+
visibility?: RepoVisibility | undefined;
|
|
2251
2494
|
language?: RepoLanguage | undefined;
|
|
2252
|
-
}
|
|
2495
|
+
};
|
|
2496
|
+
type RepoEntry = {
|
|
2497
|
+
/** Path relative to the manifest repo root (e.g. ".", "../takuhon"). */
|
|
2498
|
+
path: string;
|
|
2499
|
+
visibility?: RepoVisibility | undefined;
|
|
2500
|
+
/** Source language (commits/comments/code, read by contributors). Independent of visibility. */
|
|
2501
|
+
language?: RepoLanguage | undefined;
|
|
2502
|
+
/** Published surfaces this repo emits (opt-in; absent for a repo that publishes nothing). */
|
|
2503
|
+
publishes?: PublishTarget[] | undefined;
|
|
2504
|
+
/**
|
|
2505
|
+
* Instruction-source mode. Absent => `hub` (basou's native generated topology),
|
|
2506
|
+
* so an existing roster's behavior is unchanged. `self` opts the repo out of
|
|
2507
|
+
* generation: its AGENTS.md is a hand-authored committed file and basou stays
|
|
2508
|
+
* hands-off. Resolve the effective mode with {@link instructionMode}.
|
|
2509
|
+
*/
|
|
2510
|
+
instructions?: RepoInstructions | undefined;
|
|
2511
|
+
};
|
|
2253
2512
|
/**
|
|
2254
|
-
*
|
|
2255
|
-
*
|
|
2256
|
-
*
|
|
2257
|
-
*
|
|
2258
|
-
*
|
|
2259
|
-
* lookup, never a hardcode.
|
|
2513
|
+
* The effective instruction-source mode for a repo: the declared `instructions`,
|
|
2514
|
+
* defaulting to `hub` when absent. The default is the single guarantee that an
|
|
2515
|
+
* existing roster (which has no `instructions` field) keeps basou's current
|
|
2516
|
+
* hub-and-spoke behavior byte-for-byte — every generator branches on this, never
|
|
2517
|
+
* on the raw optional field, so "absent => hub" is decided in exactly one place.
|
|
2260
2518
|
*/
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
sourceLanguageLabel: (l: RepoLanguage | undefined) => string;
|
|
2276
|
-
/** Published-surface kind. */
|
|
2277
|
-
publishKindLabel: (k: PublishTarget["kind"]) => string;
|
|
2278
|
-
/** A published surface's visibility (independent of the source repo's). */
|
|
2279
|
-
publishVisibilityLabel: (v: RepoVisibility | undefined) => string;
|
|
2280
|
-
/** A published surface's content language (read by end users; may differ from source). */
|
|
2281
|
-
contentLanguageLabel: (l: RepoLanguage | undefined) => string;
|
|
2282
|
-
/** "ソース可視性" — the source-visibility line label. */
|
|
2283
|
-
sourceVisibilityLabel: string;
|
|
2284
|
-
/** "ソース言語" — the source-language line label. */
|
|
2285
|
-
sourceLanguageLineLabel: string;
|
|
2286
|
-
/** "- 配信物: なし" — no published surfaces. */
|
|
2287
|
-
publishesNone: string;
|
|
2288
|
-
/** "- 配信物:" — the published-surfaces list header. */
|
|
2289
|
-
publishesHeader: string;
|
|
2290
|
-
};
|
|
2291
|
-
viewBlock: {
|
|
2292
|
-
heading: string;
|
|
2293
|
-
intro: string;
|
|
2294
|
-
selfNote: (viewName: string) => string;
|
|
2295
|
-
aggregates: (repoCount: number) => string;
|
|
2296
|
-
reposHeading: string;
|
|
2297
|
-
tableHeader: string;
|
|
2298
|
-
/** Instruction-file ownership labels: who writes the repo's AGENTS.md. */
|
|
2299
|
-
instructionsAnchor: string;
|
|
2300
|
-
instructionsSelf: string;
|
|
2301
|
-
instructionsHub: string;
|
|
2302
|
-
/** "未設定" — the short table cell for an undeclared visibility / language. */
|
|
2303
|
-
unsetShort: string;
|
|
2304
|
-
commitHeading: string;
|
|
2305
|
-
commitBody: string;
|
|
2306
|
-
conventionsHeading: string;
|
|
2307
|
-
conventionsBody: string;
|
|
2308
|
-
principlesHeading: string;
|
|
2309
|
-
principleStateless: string;
|
|
2310
|
-
principleNoFiles: string;
|
|
2311
|
-
};
|
|
2312
|
-
anchorStarter: {
|
|
2313
|
-
identityLine: (title: string) => string;
|
|
2314
|
-
starterNote: string;
|
|
2315
|
-
basicsHeading: string;
|
|
2316
|
-
basicsTodo: string;
|
|
2317
|
-
commitHeading: string;
|
|
2318
|
-
commitPlanning: string;
|
|
2319
|
-
commitImplementation: string;
|
|
2320
|
-
commitView: string;
|
|
2321
|
-
conventionsHeading: string;
|
|
2322
|
-
conventionsBody: string;
|
|
2323
|
-
viewPointerLine: (viewName: string) => string;
|
|
2324
|
-
policyHeading: string;
|
|
2325
|
-
policyTodo: string[];
|
|
2326
|
-
};
|
|
2519
|
+
declare function instructionMode(entry: {
|
|
2520
|
+
instructions?: RepoInstructions | undefined;
|
|
2521
|
+
}): RepoInstructions;
|
|
2522
|
+
type RosterDriftSummary = {
|
|
2523
|
+
declaredCount: number;
|
|
2524
|
+
capturedCount: number;
|
|
2525
|
+
/** Declared in `repos` but absent from `source_roots`: a capture gap. */
|
|
2526
|
+
gaps: RepoEntry[];
|
|
2527
|
+
/** In `source_roots` but not declared in `repos` (e.g. a workspace view, or a stray). */
|
|
2528
|
+
extra: string[];
|
|
2529
|
+
/** Declared paths that are also captured. */
|
|
2530
|
+
matched: string[];
|
|
2531
|
+
/** True when there is no capture gap (every declared repo is covered). */
|
|
2532
|
+
ok: boolean;
|
|
2327
2533
|
};
|
|
2328
|
-
/** Look up the instruction-file string table for a resolved content language. */
|
|
2329
|
-
declare function presetStrings(language: ViewLanguage): PresetStrings;
|
|
2330
|
-
|
|
2331
|
-
/** Session lifecycle states. */
|
|
2332
|
-
declare const SessionStatusSchema: z.ZodEnum<{
|
|
2333
|
-
initialized: "initialized";
|
|
2334
|
-
running: "running";
|
|
2335
|
-
waiting_approval: "waiting_approval";
|
|
2336
|
-
completed: "completed";
|
|
2337
|
-
failed: "failed";
|
|
2338
|
-
interrupted: "interrupted";
|
|
2339
|
-
imported: "imported";
|
|
2340
|
-
archived: "archived";
|
|
2341
|
-
}>;
|
|
2342
|
-
/** Inferred runtime type for {@link SessionStatusSchema}. */
|
|
2343
|
-
type SessionStatus = z.infer<typeof SessionStatusSchema>;
|
|
2344
2534
|
/**
|
|
2345
|
-
*
|
|
2346
|
-
*
|
|
2347
|
-
*
|
|
2348
|
-
*
|
|
2349
|
-
*
|
|
2350
|
-
* - `codex-adapter` — a live `basou run codex` process wrap.
|
|
2351
|
-
* - `codex-import` — derived after the fact from an OpenAI Codex native
|
|
2352
|
-
* rollout log (date-partitioned `~/.codex/sessions`) by `basou import codex`.
|
|
2353
|
-
* - `import` — a round-trip of a Basou-format export (`basou session import`).
|
|
2354
|
-
* - `human` / `terminal` — manually-authored / terminal-recorded sessions.
|
|
2535
|
+
* Compute the {@link RosterDriftSummary} for a project. A declared repo missing
|
|
2536
|
+
* from the captured set is a `gap` (the surfaced suspicion); a captured path not
|
|
2537
|
+
* in the declared set is `extra` (commonly the workspace view, which is a
|
|
2538
|
+
* capture source but not itself a project repo). With no declared roster, there
|
|
2539
|
+
* are no gaps (nothing to check against) and every captured path is `extra`.
|
|
2355
2540
|
*/
|
|
2356
|
-
declare
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2541
|
+
declare function summarizeRosterDrift(input: {
|
|
2542
|
+
repos?: RepoEntry[];
|
|
2543
|
+
sourceRoots?: string[];
|
|
2544
|
+
}): RosterDriftSummary;
|
|
2545
|
+
type SourceRootsReconcile = {
|
|
2546
|
+
/**
|
|
2547
|
+
* The reconciled `source_roots`: the existing entries verbatim, then every
|
|
2548
|
+
* declared repo path that was missing (normalized, in roster order). Existing
|
|
2549
|
+
* order and form are preserved so the manifest diff is minimal and reversible.
|
|
2550
|
+
*/
|
|
2551
|
+
next: string[];
|
|
2552
|
+
/** Declared repo paths (normalized) that were appended because `source_roots` did not cover them. */
|
|
2553
|
+
added: string[];
|
|
2554
|
+
/** True when `source_roots` already covers every declared repo (`next` equals the current list). */
|
|
2555
|
+
unchanged: boolean;
|
|
2556
|
+
};
|
|
2367
2557
|
/**
|
|
2368
|
-
*
|
|
2369
|
-
*
|
|
2558
|
+
* Derive the `source_roots` a project's declared repo roster requires. The
|
|
2559
|
+
* roster (`repos`) is the single source of truth for which repos belong to the
|
|
2560
|
+
* project; this is the actuator behind `basou project sync`, computing the
|
|
2561
|
+
* additive reconciliation so every declared repo is captured.
|
|
2370
2562
|
*
|
|
2371
|
-
*
|
|
2372
|
-
*
|
|
2373
|
-
*
|
|
2374
|
-
*
|
|
2375
|
-
*
|
|
2376
|
-
*
|
|
2377
|
-
* wall-clock ranges (so cross-session totals can de-duplicate overlapping
|
|
2378
|
-
* work by interval union); `active_time_ms` is their summed duration;
|
|
2379
|
-
* `active_gap_cap_ms` and `active_time_method` lock the methodology so the
|
|
2380
|
-
* stored numbers stay interpretable if the method changes later. When a
|
|
2381
|
-
* source records explicit per-turn intervals (Codex), `active_time_method` is
|
|
2382
|
-
* `turn-intervals` and the in-turn time is the log's real wall-clock span
|
|
2383
|
-
* rather than a gap-capped approximation; the active semantics are unchanged.
|
|
2384
|
-
* - `machine_active_time_ms`: model compute time — the summed duration of the
|
|
2385
|
-
* source's per-turn spans (Codex `task_complete.duration_ms`), a SUBSET of a
|
|
2386
|
-
* single session's engaged active time. Unlike `active_intervals` it is a
|
|
2387
|
-
* plain sum, NOT wall-clock-deduplicated, so two concurrent sessions can sum
|
|
2388
|
-
* past their billable (union) active wall-clock — that is intended (two models
|
|
2389
|
-
* working at once did two machine-hours in one wall-clock hour). Captured only
|
|
2390
|
-
* for sources that record per-turn duration (Codex); absent otherwise.
|
|
2563
|
+
* ADDITIVE ONLY: it appends declared paths that are missing and never removes
|
|
2564
|
+
* an existing entry. A captured-but-undeclared path (commonly the generated
|
|
2565
|
+
* workspace view — a legitimate capture source that is not itself a project
|
|
2566
|
+
* repo) is preserved; pruning strays is deferred to the slice that generates
|
|
2567
|
+
* the view (so basou knows which extras it owns). Existing entries are kept
|
|
2568
|
+
* byte-identical; only appended paths are normalized.
|
|
2391
2569
|
*
|
|
2392
|
-
*
|
|
2393
|
-
*
|
|
2394
|
-
*
|
|
2570
|
+
* Pure: no filesystem or git I/O. Paths are compared in the same normalized
|
|
2571
|
+
* form as {@link summarizeRosterDrift}, so a trailing-slash variant of an
|
|
2572
|
+
* already-captured repo is not re-appended.
|
|
2395
2573
|
*/
|
|
2396
|
-
declare
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2401
|
-
active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2402
|
-
active_intervals: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2403
|
-
start: z.ZodString;
|
|
2404
|
-
end: z.ZodString;
|
|
2405
|
-
}, z.core.$loose>>>;
|
|
2406
|
-
active_gap_cap_ms: z.ZodOptional<z.ZodNumber>;
|
|
2407
|
-
active_time_method: z.ZodOptional<z.ZodString>;
|
|
2408
|
-
machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2409
|
-
}, z.core.$loose>;
|
|
2410
|
-
/** Inferred runtime type for {@link SessionMetricsSchema}. */
|
|
2411
|
-
type SessionMetrics = z.infer<typeof SessionMetricsSchema>;
|
|
2574
|
+
declare function reconcileSourceRoots(input: {
|
|
2575
|
+
repos?: RepoEntry[];
|
|
2576
|
+
sourceRoots?: string[];
|
|
2577
|
+
}): SourceRootsReconcile;
|
|
2412
2578
|
/**
|
|
2413
|
-
*
|
|
2414
|
-
*
|
|
2415
|
-
*
|
|
2416
|
-
*
|
|
2417
|
-
* (`exec` / `run` / ad-hoc), by the finalize once it reaches a terminal status.
|
|
2418
|
-
* Absent on a still-live session (the anchor is stamped at finalize) and on a
|
|
2419
|
-
* pre-feature unchained session. Additive optional => no schema_version bump.
|
|
2420
|
-
* `.strict()` because the writers fully own the shape.
|
|
2579
|
+
* On-disk classification of a source-root candidate during adoption: a git repo
|
|
2580
|
+
* root (→ becomes a roster entry), a resolved-but-non-repo directory (the
|
|
2581
|
+
* generated workspace view, `/tmp`, a scratch dir → excluded), or a path that
|
|
2582
|
+
* could not be resolved on disk (→ excluded).
|
|
2421
2583
|
*/
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
/**
|
|
2427
|
-
|
|
2584
|
+
type AdoptCandidateKind = "repo" | "non-repo" | "unresolved";
|
|
2585
|
+
type AdoptCandidate = {
|
|
2586
|
+
/** Source-root path as declared (relative to the manifest root). */
|
|
2587
|
+
path: string;
|
|
2588
|
+
/** On-disk classification; the filesystem probing that produces it is the caller's job. */
|
|
2589
|
+
kind: AdoptCandidateKind;
|
|
2590
|
+
};
|
|
2591
|
+
type RosterAdoptionPlan = {
|
|
2592
|
+
/** Proposed `repos` entries: the candidates that are git repos (visibility left unset for the operator). */
|
|
2593
|
+
repos: RepoEntry[];
|
|
2594
|
+
/** Candidates excluded from the roster, with why (a non-repo directory, or an unresolvable path). */
|
|
2595
|
+
excluded: {
|
|
2596
|
+
path: string;
|
|
2597
|
+
kind: Exclude<AdoptCandidateKind, "repo">;
|
|
2598
|
+
}[];
|
|
2599
|
+
};
|
|
2428
2600
|
/**
|
|
2429
|
-
*
|
|
2430
|
-
*
|
|
2431
|
-
* `
|
|
2601
|
+
* Plan a `repos` roster from classified source-root candidates (the actuator
|
|
2602
|
+
* behind `basou project adopt`). Pure: it partitions already-classified
|
|
2603
|
+
* candidates — the realpath / `.git` filesystem probing that produces each
|
|
2604
|
+
* `kind` is the caller's job, so this stays testable without disk I/O.
|
|
2605
|
+
*
|
|
2606
|
+
* A git repo becomes a roster entry (path only; visibility is left unset because
|
|
2607
|
+
* it is a human judgment, kept independent of the other axes). A non-repo
|
|
2608
|
+
* (commonly the generated workspace view) or an unresolvable path is excluded and
|
|
2609
|
+
* reported, so the operator sees what was dropped and why before editing. Repo
|
|
2610
|
+
* paths are deduped by normalized form, preserving the first declared form and
|
|
2611
|
+
* order.
|
|
2432
2612
|
*/
|
|
2433
|
-
declare
|
|
2434
|
-
schema_version: z.ZodString;
|
|
2435
|
-
session: z.ZodObject<{
|
|
2436
|
-
id: z.ZodString & z.ZodType<`ses_${string}`, string, z.core.$ZodTypeInternals<`ses_${string}`, string>>;
|
|
2437
|
-
label: z.ZodOptional<z.ZodString>;
|
|
2438
|
-
task_id: z.ZodOptional<z.ZodNullable<z.ZodString & z.ZodType<`task_${string}`, string, z.core.$ZodTypeInternals<`task_${string}`, string>>>>;
|
|
2439
|
-
workspace_id: z.ZodString & z.ZodType<`ws_${string}`, string, z.core.$ZodTypeInternals<`ws_${string}`, string>>;
|
|
2440
|
-
source: z.ZodObject<{
|
|
2441
|
-
kind: z.ZodEnum<{
|
|
2442
|
-
"claude-code-adapter": "claude-code-adapter";
|
|
2443
|
-
import: "import";
|
|
2444
|
-
"claude-code-import": "claude-code-import";
|
|
2445
|
-
"codex-adapter": "codex-adapter";
|
|
2446
|
-
"codex-import": "codex-import";
|
|
2447
|
-
human: "human";
|
|
2448
|
-
terminal: "terminal";
|
|
2449
|
-
}>;
|
|
2450
|
-
version: z.ZodLiteral<"0.1.0">;
|
|
2451
|
-
external_id: z.ZodOptional<z.ZodString>;
|
|
2452
|
-
source_size_bytes: z.ZodOptional<z.ZodNumber>;
|
|
2453
|
-
}, z.core.$loose>;
|
|
2454
|
-
started_at: z.ZodString;
|
|
2455
|
-
ended_at: z.ZodOptional<z.ZodString>;
|
|
2456
|
-
status: z.ZodEnum<{
|
|
2457
|
-
initialized: "initialized";
|
|
2458
|
-
running: "running";
|
|
2459
|
-
waiting_approval: "waiting_approval";
|
|
2460
|
-
completed: "completed";
|
|
2461
|
-
failed: "failed";
|
|
2462
|
-
interrupted: "interrupted";
|
|
2463
|
-
imported: "imported";
|
|
2464
|
-
archived: "archived";
|
|
2465
|
-
}>;
|
|
2466
|
-
working_directory: z.ZodString;
|
|
2467
|
-
invocation: z.ZodObject<{
|
|
2468
|
-
command: z.ZodString;
|
|
2469
|
-
args: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2470
|
-
exit_code: z.ZodNullable<z.ZodNumber>;
|
|
2471
|
-
}, z.core.$loose>;
|
|
2472
|
-
related_files: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
2473
|
-
events_log: z.ZodDefault<z.ZodString>;
|
|
2474
|
-
summary: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2475
|
-
metrics: z.ZodOptional<z.ZodObject<{
|
|
2476
|
-
output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2477
|
-
input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2478
|
-
cached_input_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2479
|
-
reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
|
|
2480
|
-
active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2481
|
-
active_intervals: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2482
|
-
start: z.ZodString;
|
|
2483
|
-
end: z.ZodString;
|
|
2484
|
-
}, z.core.$loose>>>;
|
|
2485
|
-
active_gap_cap_ms: z.ZodOptional<z.ZodNumber>;
|
|
2486
|
-
active_time_method: z.ZodOptional<z.ZodString>;
|
|
2487
|
-
machine_active_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
2488
|
-
}, z.core.$loose>>;
|
|
2489
|
-
integrity: z.ZodOptional<z.ZodObject<{
|
|
2490
|
-
head_hash: z.ZodString;
|
|
2491
|
-
event_count: z.ZodNumber;
|
|
2492
|
-
}, z.core.$strict>>;
|
|
2493
|
-
}, z.core.$loose>;
|
|
2494
|
-
}, z.core.$loose>;
|
|
2495
|
-
/** Inferred runtime type for {@link SessionSchema}. */
|
|
2496
|
-
type Session = z.infer<typeof SessionSchema>;
|
|
2613
|
+
declare function planRosterAdoption(candidates: AdoptCandidate[]): RosterAdoptionPlan;
|
|
2497
2614
|
|
|
2498
2615
|
/**
|
|
2499
|
-
*
|
|
2500
|
-
*
|
|
2616
|
+
* The language of the GENERATED-VIEW chrome (headings, labels, verdict prose)
|
|
2617
|
+
* in handoff.md / orientation.md / decisions.md / report output.
|
|
2501
2618
|
*
|
|
2502
|
-
*
|
|
2503
|
-
*
|
|
2504
|
-
*
|
|
2619
|
+
* This is deliberately narrower than the manifest's repo `language` axis
|
|
2620
|
+
* (`en | ja | en+ja`): a generated view has exactly one chrome language, so
|
|
2621
|
+
* `en+ja` resolves to `en`. User data (decision titles, notes, labels, file
|
|
2622
|
+
* paths) always passes through verbatim — only the tool-generated strings are
|
|
2623
|
+
* localized, which is exactly the split this type exists to keep honest.
|
|
2505
2624
|
*/
|
|
2506
|
-
|
|
2507
|
-
type SuspectReason = "events_say_ended_but_yaml_running" | "running_no_end_event";
|
|
2508
|
-
type SessionEntry = {
|
|
2509
|
-
sessionId: string;
|
|
2510
|
-
session: Session;
|
|
2511
|
-
suspect: boolean;
|
|
2512
|
-
suspectReason: SuspectReason | null;
|
|
2513
|
-
/**
|
|
2514
|
-
* The trail store this entry was read from. Its `sessions` directory locates
|
|
2515
|
-
* the session's `events.jsonl`, so a federated caller can replay events from
|
|
2516
|
-
* the store the session actually lives in (not the local store). For a plain
|
|
2517
|
-
* local load this is the `paths` passed to {@link loadSessionEntries}.
|
|
2518
|
-
*/
|
|
2519
|
-
sourceRoot: BasouPaths;
|
|
2520
|
-
/**
|
|
2521
|
-
* Federation host label from the registry (`~/.basou/hosts.yaml`), or `null`
|
|
2522
|
-
* for the local store. Surfaced by orientation so a merged, multi-host view
|
|
2523
|
-
* can attribute the latest session / decision / next-step to its host.
|
|
2524
|
-
*/
|
|
2525
|
-
host: string | null;
|
|
2526
|
-
};
|
|
2625
|
+
type ViewLanguage = "en" | "ja";
|
|
2527
2626
|
/**
|
|
2528
|
-
*
|
|
2627
|
+
* Resolve the generated-view language from a manifest: the workspace speaks
|
|
2628
|
+
* the language of its ANCHOR repo (the `repos[]` entry whose path is `.`).
|
|
2529
2629
|
*
|
|
2530
|
-
*
|
|
2531
|
-
*
|
|
2532
|
-
* - `
|
|
2533
|
-
*
|
|
2534
|
-
*
|
|
2535
|
-
*
|
|
2630
|
+
* Rules (fixed by design):
|
|
2631
|
+
* - anchor declares `ja` -> `ja`
|
|
2632
|
+
* - anchor declares `en` / `en+ja` -> `en` (a bilingual surface renders one
|
|
2633
|
+
* chrome; en is the shared floor)
|
|
2634
|
+
* - no roster / no anchor entry / no declared language -> `en` (the default
|
|
2635
|
+
* for basou's English-first OSS surface)
|
|
2636
|
+
*
|
|
2637
|
+
* Binding the view to the anchor's language is a deliberate, documented
|
|
2638
|
+
* coupling: the anchor is the planning/trail home the views live in, so its
|
|
2639
|
+
* declared audience is the views' audience. Other repos' languages do not
|
|
2640
|
+
* participate.
|
|
2536
2641
|
*/
|
|
2537
|
-
|
|
2538
|
-
type LoadSessionEntriesOptions = {
|
|
2539
|
-
/**
|
|
2540
|
-
* Single `now` shared across every {@link classifySuspect} call so that
|
|
2541
|
-
* sessions classified back-to-back observe the same instant. Avoids
|
|
2542
|
-
* boundary races where a session at age ≈ 24h would flip between calls.
|
|
2543
|
-
*/
|
|
2544
|
-
now: Date;
|
|
2545
|
-
onWarning?: (warning: ReplayWarning, sessionId: string) => void;
|
|
2546
|
-
onSkip?: (sessionId: string, reason: SessionSkipReason) => void;
|
|
2547
|
-
};
|
|
2642
|
+
declare function resolveViewLanguage(manifest: Pick<Manifest, "repos"> | null): ViewLanguage;
|
|
2548
2643
|
/**
|
|
2549
|
-
*
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2552
|
-
*
|
|
2553
|
-
* basou itself never performs any network I/O to obtain it.
|
|
2644
|
+
* Manifest-reading convenience for the renderers: resolve the view language
|
|
2645
|
+
* for a workspace, defaulting to `en` when the manifest is missing or
|
|
2646
|
+
* unreadable (mirrors the orientation renderer's tolerant source_roots read —
|
|
2647
|
+
* a broken manifest must never break a view render).
|
|
2554
2648
|
*/
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2649
|
+
declare function resolveViewLanguageFromPaths(paths: BasouPaths): Promise<ViewLanguage>;
|
|
2650
|
+
/**
|
|
2651
|
+
* Every localized string the four view renderers emit, grouped per renderer
|
|
2652
|
+
* with a small `common` set for lines that are byte-identical across views.
|
|
2653
|
+
* Parameterized lines are functions so the two languages can order their
|
|
2654
|
+
* parts naturally.
|
|
2655
|
+
*
|
|
2656
|
+
* This module is the SINGLE home for generated Japanese — the view chrome here
|
|
2657
|
+
* and the instruction-file content in {@link PresetStrings} (the E-5
|
|
2658
|
+
* language-lint allowlist points here, not at the renderers/generators), so
|
|
2659
|
+
* "user data language" and "tool-generated content language" can never blur
|
|
2660
|
+
* together again.
|
|
2661
|
+
*/
|
|
2662
|
+
type ViewStrings = {
|
|
2663
|
+
/** Localized relative age for prose lines, e.g. "3日4時間前" / "3d 4h ago". */
|
|
2664
|
+
relativeAge: (startedAt: string | null, now: Date) => string;
|
|
2665
|
+
common: {
|
|
2666
|
+
/** "最終 session" — the latest live session pointer. */
|
|
2667
|
+
lastSessionLabel: string;
|
|
2668
|
+
/** "直近の判断" — the latest recorded decision pointer. */
|
|
2669
|
+
latestDecisionLabel: string;
|
|
2670
|
+
/** "直近の変更ファイル" — the latest session's related files. */
|
|
2671
|
+
recentFilesLabel: string;
|
|
2672
|
+
/** "理由" — a track's rationale label. */
|
|
2673
|
+
trackWhyLabel: string;
|
|
2674
|
+
/** Note that the latest decision comes from a different session. */
|
|
2675
|
+
decisionOtherSessionNote: (shortSessionId: string) => string;
|
|
2676
|
+
};
|
|
2677
|
+
orientation: {
|
|
2678
|
+
headingWhere: string;
|
|
2679
|
+
headingRecent: (sessionCount: number) => string;
|
|
2680
|
+
headingInFlight: string;
|
|
2681
|
+
headingForward: string;
|
|
2682
|
+
headingCurrency: string;
|
|
2683
|
+
inFlightTasksHeading: (n: number) => string;
|
|
2684
|
+
/**
|
|
2685
|
+
* Body line under the in-flight-tasks heading when NO task was ever
|
|
2686
|
+
* recorded here. "(none)" states that nothing is pending — a claim about
|
|
2687
|
+
* the work. This one claims only what it can see: that the record is
|
|
2688
|
+
* empty. It says nothing about whether the workspace should use tasks,
|
|
2689
|
+
* and names no command: the renderers report position, and a nudge that
|
|
2690
|
+
* cannot be silenced is noise (see `trackNudge`, which is gated).
|
|
2691
|
+
*/
|
|
2692
|
+
noTasksRecorded: string;
|
|
2693
|
+
/**
|
|
2694
|
+
* Body line under the in-flight-tasks heading when tasks ARE on record
|
|
2695
|
+
* here and every one of them parsed, with none open. A bare "(none)" is
|
|
2696
|
+
* literally true and still misread: it answers "is anything in flight?"
|
|
2697
|
+
* with a word that sounds like "nothing is happening". Work can be under
|
|
2698
|
+
* way and simply not filed as a task. This line leads with what the
|
|
2699
|
+
* record does hold, so it cannot be skimmed as its sibling below, and it
|
|
2700
|
+
* claims nothing about the work.
|
|
2701
|
+
*/
|
|
2702
|
+
noTasksInFlight: string;
|
|
2703
|
+
/**
|
|
2704
|
+
* Same heading, but a task file could not be read on THIS pass, so its
|
|
2705
|
+
* status is unknown and "none in flight" would be an assertion the
|
|
2706
|
+
* renderer cannot support. Says what it can see and stops. Reading the
|
|
2707
|
+
* tasks directory can rebuild the index without the unreadable file, in
|
|
2708
|
+
* which case a later render does not attempt it and this line gives way
|
|
2709
|
+
* to its sibling -- the line reports a pass, not a standing condition.
|
|
2710
|
+
*/
|
|
2711
|
+
tasksUnreadable: string;
|
|
2712
|
+
pendingApprovalsHeading: (n: number) => string;
|
|
2713
|
+
suspectSessionsHeading: (n: number) => string;
|
|
2714
|
+
openTracksHeading: (n: number) => string;
|
|
2715
|
+
/** Stale-decision honesty note under 直近の判断. */
|
|
2716
|
+
decisionStaleNote: (activityAge: string) => string;
|
|
2717
|
+
outOfRootWarning: (count: number, files: string) => string;
|
|
2718
|
+
recentEmpty: string;
|
|
2719
|
+
recentDecisionsLabel: string;
|
|
2720
|
+
recentNextStepLabel: string;
|
|
2721
|
+
recentChangedLabel: string;
|
|
2722
|
+
/** Trails the recent-files line when scratch paths were left out of it. */
|
|
2723
|
+
scratchOmitted: (count: number) => string;
|
|
2724
|
+
trackCloseInstruction: string;
|
|
2725
|
+
/** Forward-section pointer to `basou decision gaps`; omitted when the count is 0. */
|
|
2726
|
+
decisionGapsLine: (n: number) => string;
|
|
2727
|
+
nextStepRecordedLabel: (age: string) => string;
|
|
2728
|
+
noteStaleNote: (activityAge: string) => string;
|
|
2729
|
+
fallbackStaleDirection: string;
|
|
2730
|
+
fallbackStaleReferenceLabel: string;
|
|
2731
|
+
trackNudge: string;
|
|
2732
|
+
federatedFreshnessNote: string;
|
|
2733
|
+
bannerUnverifiable: (n: number) => string;
|
|
2734
|
+
bannerStale: (parts: string) => string;
|
|
2735
|
+
partNew: (n: number) => string;
|
|
2736
|
+
partUpdated: (n: number) => string;
|
|
2737
|
+
partsJoiner: string;
|
|
2738
|
+
verdictUnverifiable: (n: number) => [string, string];
|
|
2739
|
+
verdictStale: (parts: string) => [string, string];
|
|
2740
|
+
verdictUpdatedOnly: (n: number) => [string, string];
|
|
2741
|
+
verdictSuspectsAlso: (n: number) => string;
|
|
2742
|
+
verdictEmpty: [string, string];
|
|
2743
|
+
verdictUnprobed: (rel: string, tool: string) => [string, string];
|
|
2744
|
+
verdictCurrent: (rel: string, tool: string, hasHosts: boolean) => string;
|
|
2745
|
+
verdictSuspectsCaveat: (n: number) => string;
|
|
2746
|
+
verdictScopeDisclaimer: string;
|
|
2747
|
+
toolTerminal: string;
|
|
2748
|
+
toolHuman: string;
|
|
2749
|
+
toolImport: string;
|
|
2750
|
+
toolUnknown: string;
|
|
2751
|
+
};
|
|
2752
|
+
handoff: {
|
|
2753
|
+
headingCurrentState: string;
|
|
2754
|
+
headingRecentFiles: string;
|
|
2755
|
+
headingLatestDecision: string;
|
|
2756
|
+
headingOpenTracks: string;
|
|
2757
|
+
headingUnresolved: string;
|
|
2758
|
+
headingReadNext: string;
|
|
2759
|
+
headingNextWork: string;
|
|
2760
|
+
headingSessions: string;
|
|
2761
|
+
lastTaskLabel: string;
|
|
2762
|
+
/** "Work to do next" placeholder: tasks exist, none are open. */
|
|
2763
|
+
noPendingTasks: string;
|
|
2764
|
+
/** "Work to do next" placeholder: no task was ever recorded. */
|
|
2765
|
+
noTasksRecorded: string;
|
|
2766
|
+
decisionStaleNote: string;
|
|
2767
|
+
trackCloseInstruction: string;
|
|
2768
|
+
};
|
|
2769
|
+
decisions: {
|
|
2770
|
+
dateLabel: string;
|
|
2771
|
+
trackKindLine: string;
|
|
2772
|
+
decisionLabel: string;
|
|
2773
|
+
};
|
|
2774
|
+
report: {
|
|
2775
|
+
headingSummary: string;
|
|
2776
|
+
headingVolume: string;
|
|
2777
|
+
headingDecisions: string;
|
|
2778
|
+
headingApprovals: string;
|
|
2779
|
+
headingTasks: string;
|
|
2780
|
+
headingChangedFiles: string;
|
|
2781
|
+
headingSessions: string;
|
|
2782
|
+
headingIntegrity: string;
|
|
2783
|
+
};
|
|
2569
2784
|
};
|
|
2785
|
+
/** Look up the string table for a resolved view language. */
|
|
2786
|
+
declare function viewStrings(language: ViewLanguage): ViewStrings;
|
|
2570
2787
|
/**
|
|
2571
|
-
*
|
|
2572
|
-
*
|
|
2573
|
-
*
|
|
2574
|
-
*
|
|
2575
|
-
* -
|
|
2576
|
-
*
|
|
2577
|
-
*
|
|
2578
|
-
* Sort order is `Array.prototype.sort()` default (Unicode code-point
|
|
2579
|
-
* compare). ULIDs are Crockford base32 in uppercase, so the natural sort
|
|
2580
|
-
* is also chronological session-start order.
|
|
2581
|
-
*/
|
|
2582
|
-
declare function enumerateSessionDirs(paths: BasouPaths): Promise<string[]>;
|
|
2583
|
-
/**
|
|
2584
|
-
* Read and validate `<paths.sessions>/<sessionId>/session.yaml`.
|
|
2585
|
-
*
|
|
2586
|
-
* - Re-throws the yaml-store fixed-message `"YAML file not found"` for
|
|
2587
|
-
* ENOENT so the caller can branch on it.
|
|
2588
|
-
* - Throws `Error("Failed to read session.yaml", { cause })` for parse
|
|
2589
|
-
* failures and schema violations (cause is either the YAML parser error
|
|
2590
|
-
* or the zod error).
|
|
2591
|
-
*/
|
|
2592
|
-
declare function readSessionYaml(paths: BasouPaths, sessionId: string): Promise<Session>;
|
|
2593
|
-
/**
|
|
2594
|
-
* Apply a terminal-status mutation to a live session's `session.yaml` AND, in
|
|
2595
|
-
* the same locked write, stamp the tamper-evidence head anchor derived from the
|
|
2596
|
-
* on-disk `events.jsonl` tail. Used by the `exec` / `run` orchestrators for
|
|
2597
|
-
* BOTH terminal writers (the normal end-of-run finalize and the spawn-failure
|
|
2598
|
-
* `failed` finalize).
|
|
2599
|
-
*
|
|
2600
|
-
* Why locked + anchor-from-tail: live appends chain the LOG only and leave the
|
|
2601
|
-
* anchor for finalize. Reading the final tail under the session lock means a
|
|
2602
|
-
* foreign line appended just before finalize (e.g. a `decision record` attached
|
|
2603
|
-
* to a still-running session) is included in the anchor, and a foreign attach
|
|
2604
|
-
* that arrives after the terminal status is set is rejected by the attach gate
|
|
2605
|
-
* — so the anchor can never disagree with the at-rest log. The whole-document
|
|
2606
|
-
* read-modify-write also preserves any field a foreign locked writer set (e.g.
|
|
2607
|
-
* a task attach's `task_id`).
|
|
2608
|
-
*
|
|
2609
|
-
* The anchor is written only when the log is actually chained with at least one
|
|
2610
|
-
* line; a legacy unchained session (and an empty log) is left with no
|
|
2611
|
-
* `integrity` anchor, matching the import writers. The mutator receives the
|
|
2612
|
-
* full {@link Session} document and typically sets
|
|
2613
|
-
* `session.session.status` / `ended_at` / `invocation.exit_code` /
|
|
2614
|
-
* `related_files`.
|
|
2615
|
-
*
|
|
2616
|
-
* Throws the {@link inspectChainTail} errors (torn / mixed log), the
|
|
2617
|
-
* {@link readSessionYaml} errors, a zod error if the mutation produces an
|
|
2618
|
-
* invalid document, or `Error("Failed to overwrite YAML file")` on a disk
|
|
2619
|
-
* failure.
|
|
2788
|
+
* Resolve a GENERATED INSTRUCTION-FILE's content language from the target
|
|
2789
|
+
* repo's declared `language`. Unlike the views (workspace-level artifacts that
|
|
2790
|
+
* follow the anchor), a preset block lives inside one repo's instruction file,
|
|
2791
|
+
* so its audience is that repo's declared audience: `ja` renders Japanese
|
|
2792
|
+
* (byte-identical to the pre-i18n output), `en` / `en+ja` / undeclared render
|
|
2793
|
+
* English (one content language per generated block; en is the shared floor).
|
|
2620
2794
|
*/
|
|
2621
|
-
declare function
|
|
2795
|
+
declare function resolveRepoContentLanguage(language: RepoLanguage | undefined): ViewLanguage;
|
|
2622
2796
|
/**
|
|
2623
|
-
*
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2626
|
-
*
|
|
2627
|
-
*
|
|
2628
|
-
*
|
|
2629
|
-
* - Rule B (`running_no_end_event`): no `session_ended` event and the last
|
|
2630
|
-
* event is older than {@link STUCK_THRESHOLD_MS}. The process likely
|
|
2631
|
-
* crashed or was killed.
|
|
2632
|
-
*
|
|
2633
|
-
* Sessions that are not `running` are never suspect.
|
|
2797
|
+
* Resolve the content language of a WORKSPACE-LEVEL instruction artifact (the
|
|
2798
|
+
* view's AGENTS.md block, the anchor's starter) from an already-gathered
|
|
2799
|
+
* roster: the entry flagged `anchor` speaks for the workspace, mirroring the
|
|
2800
|
+
* views' anchor-language rule. No anchor entry (or no declared language)
|
|
2801
|
+
* resolves to English. When more than one entry carries the flag, the first
|
|
2802
|
+
* wins (declared order).
|
|
2634
2803
|
*
|
|
2635
|
-
*
|
|
2636
|
-
*
|
|
2637
|
-
*
|
|
2804
|
+
* Note the anchor is identified by the CALLER-SET flag, not by this module:
|
|
2805
|
+
* {@link resolveViewLanguage} keys on the manifest path being `.`, while the
|
|
2806
|
+
* instruction-file callers flag the anchor by resolved-path identity. For a
|
|
2807
|
+
* conventional manifest (anchor declared as `.`) the two agree; a roster that
|
|
2808
|
+
* reaches the anchor only through an aliased path is where they can diverge,
|
|
2809
|
+
* and the caller's flag is authoritative for the instruction files.
|
|
2638
2810
|
*/
|
|
2639
|
-
declare function
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
}
|
|
2643
|
-
declare function loadSessionEntries(paths: BasouPaths, options: LoadSessionEntriesOptions): Promise<SessionEntry[]>;
|
|
2811
|
+
declare function resolveAnchorContentLanguage(repos: ReadonlyArray<{
|
|
2812
|
+
anchor?: boolean | undefined;
|
|
2813
|
+
language?: RepoLanguage | undefined;
|
|
2814
|
+
}>): ViewLanguage;
|
|
2644
2815
|
/**
|
|
2645
|
-
*
|
|
2646
|
-
*
|
|
2647
|
-
*
|
|
2648
|
-
*
|
|
2649
|
-
*
|
|
2650
|
-
*
|
|
2651
|
-
* cannot be enumerated is reported via `onRootUnavailable` and skipped; the
|
|
2652
|
-
* local root's errors propagate, matching {@link loadSessionEntries}.
|
|
2816
|
+
* Every localized string the instruction-file generators emit: the per-repo
|
|
2817
|
+
* preset block, the workspace view's block, and the anchor's starter. Lives in
|
|
2818
|
+
* this module for the same reason as {@link ViewStrings}: it is the SINGLE
|
|
2819
|
+
* home for generated Japanese, so the language-lint E-5 allowlist stays one
|
|
2820
|
+
* file and "generated content language" is always a declaration-driven table
|
|
2821
|
+
* lookup, never a hardcode.
|
|
2653
2822
|
*/
|
|
2654
|
-
|
|
2823
|
+
type PresetStrings = {
|
|
2824
|
+
repoBlock: {
|
|
2825
|
+
heading: string;
|
|
2826
|
+
intro: string;
|
|
2827
|
+
/** Source git-visibility, rendered with the consequence the agent must respect. */
|
|
2828
|
+
visibilityLabel: (v: RepoVisibility | undefined) => string;
|
|
2829
|
+
/**
|
|
2830
|
+
* Source language (commits/comments/code), rendered with the audience it
|
|
2831
|
+
* serves. Invariant note: the table itself is SELECTED by this same field
|
|
2832
|
+
* (ja -> JA table, everything else -> EN), so the JA table's en / en+ja /
|
|
2833
|
+
* unset branches and the EN table's ja branch are unreachable from
|
|
2834
|
+
* renderPresetBlock — they exist for table completeness (and the
|
|
2835
|
+
* both-language sweep test), not because a render can emit them.
|
|
2836
|
+
*/
|
|
2837
|
+
sourceLanguageLabel: (l: RepoLanguage | undefined) => string;
|
|
2838
|
+
/** Published-surface kind. */
|
|
2839
|
+
publishKindLabel: (k: PublishTarget["kind"]) => string;
|
|
2840
|
+
/** A published surface's visibility (independent of the source repo's). */
|
|
2841
|
+
publishVisibilityLabel: (v: RepoVisibility | undefined) => string;
|
|
2842
|
+
/** A published surface's content language (read by end users; may differ from source). */
|
|
2843
|
+
contentLanguageLabel: (l: RepoLanguage | undefined) => string;
|
|
2844
|
+
/** "ソース可視性" — the source-visibility line label. */
|
|
2845
|
+
sourceVisibilityLabel: string;
|
|
2846
|
+
/** "ソース言語" — the source-language line label. */
|
|
2847
|
+
sourceLanguageLineLabel: string;
|
|
2848
|
+
/** "- 配信物: なし" — no published surfaces. */
|
|
2849
|
+
publishesNone: string;
|
|
2850
|
+
/** "- 配信物:" — the published-surfaces list header. */
|
|
2851
|
+
publishesHeader: string;
|
|
2852
|
+
};
|
|
2853
|
+
viewBlock: {
|
|
2854
|
+
heading: string;
|
|
2855
|
+
intro: string;
|
|
2856
|
+
selfNote: (viewName: string) => string;
|
|
2857
|
+
aggregates: (repoCount: number) => string;
|
|
2858
|
+
reposHeading: string;
|
|
2859
|
+
tableHeader: string;
|
|
2860
|
+
/** Instruction-file ownership labels: who writes the repo's AGENTS.md. */
|
|
2861
|
+
instructionsAnchor: string;
|
|
2862
|
+
instructionsSelf: string;
|
|
2863
|
+
instructionsHub: string;
|
|
2864
|
+
/** "未設定" — the short table cell for an undeclared visibility / language. */
|
|
2865
|
+
unsetShort: string;
|
|
2866
|
+
commitHeading: string;
|
|
2867
|
+
commitBody: string;
|
|
2868
|
+
conventionsHeading: string;
|
|
2869
|
+
conventionsBody: string;
|
|
2870
|
+
/** Heading for {@link handoffPointer}. Its own, so the pointer is not filed
|
|
2871
|
+
* under "Required reading" while telling the reader not to read it through. */
|
|
2872
|
+
handoffHeading: string;
|
|
2873
|
+
/**
|
|
2874
|
+
* Where the session roster lives. One line, because the adjudication that
|
|
2875
|
+
* chose this destination capped session-start injection: the roster itself
|
|
2876
|
+
* must never be injected, only its address.
|
|
2877
|
+
*/
|
|
2878
|
+
handoffPointer: string;
|
|
2879
|
+
principlesHeading: string;
|
|
2880
|
+
principleStateless: string;
|
|
2881
|
+
principleNoFiles: string;
|
|
2882
|
+
};
|
|
2883
|
+
anchorStarter: {
|
|
2884
|
+
identityLine: (title: string) => string;
|
|
2885
|
+
starterNote: string;
|
|
2886
|
+
basicsHeading: string;
|
|
2887
|
+
basicsTodo: string;
|
|
2888
|
+
commitHeading: string;
|
|
2889
|
+
commitPlanning: string;
|
|
2890
|
+
commitImplementation: string;
|
|
2891
|
+
commitView: string;
|
|
2892
|
+
conventionsHeading: string;
|
|
2893
|
+
conventionsBody: string;
|
|
2894
|
+
viewPointerLine: (viewName: string) => string;
|
|
2895
|
+
/** Same route as the view block's, for the anchor — which is where `.basou/` lives. */
|
|
2896
|
+
handoffHeading: string;
|
|
2897
|
+
handoffPointer: string;
|
|
2898
|
+
policyHeading: string;
|
|
2899
|
+
policyTodo: string[];
|
|
2900
|
+
};
|
|
2901
|
+
};
|
|
2902
|
+
/** Look up the instruction-file string table for a resolved content language. */
|
|
2903
|
+
declare function presetStrings(language: ViewLanguage): PresetStrings;
|
|
2655
2904
|
|
|
2656
2905
|
type DecisionsRendererInput = {
|
|
2657
2906
|
paths: BasouPaths;
|
|
@@ -3198,6 +3447,19 @@ declare function prefixedUlid<P extends IdPrefix>(prefix: P): PrefixedId<P>;
|
|
|
3198
3447
|
*/
|
|
3199
3448
|
declare function isValidPrefixedId(value: string): boolean;
|
|
3200
3449
|
|
|
3450
|
+
/**
|
|
3451
|
+
* `schema_version` stamped on NEWLY WRITTEN `.basou/tasks/<id>.md` front matter.
|
|
3452
|
+
*
|
|
3453
|
+
* 0.2.0 requires seconds in every timestamp. That NARROWS the field's domain,
|
|
3454
|
+
* which §7.3 forbids except under the vacuous-narrowing rule the same section
|
|
3455
|
+
* states: no value basou has ever written omits seconds, so the set of
|
|
3456
|
+
* documents this refuses is empty. See `docs/spec/schemas.md` for the read
|
|
3457
|
+
* rule and the measurement. The narrowing is shared with the event format, so
|
|
3458
|
+
* every durable document bumps together.
|
|
3459
|
+
*
|
|
3460
|
+
* Note: basou writes this document.
|
|
3461
|
+
*/
|
|
3462
|
+
declare const TASK_SCHEMA_VERSION: "0.2.0";
|
|
3201
3463
|
/**
|
|
3202
3464
|
* Task lifecycle states.
|
|
3203
3465
|
*
|
|
@@ -3214,8 +3476,8 @@ declare function isValidPrefixedId(value: string): boolean;
|
|
|
3214
3476
|
* Self-edges are rejected so the audit trail stays monotonic.
|
|
3215
3477
|
*/
|
|
3216
3478
|
declare const TaskStatusSchema: z.ZodEnum<{
|
|
3217
|
-
in_progress: "in_progress";
|
|
3218
3479
|
planned: "planned";
|
|
3480
|
+
in_progress: "in_progress";
|
|
3219
3481
|
done: "done";
|
|
3220
3482
|
cancelled: "cancelled";
|
|
3221
3483
|
}>;
|
|
@@ -3235,8 +3497,8 @@ declare const TaskSchema: z.ZodObject<{
|
|
|
3235
3497
|
title: z.ZodString;
|
|
3236
3498
|
label: z.ZodOptional<z.ZodString>;
|
|
3237
3499
|
status: z.ZodEnum<{
|
|
3238
|
-
in_progress: "in_progress";
|
|
3239
3500
|
planned: "planned";
|
|
3501
|
+
in_progress: "in_progress";
|
|
3240
3502
|
done: "done";
|
|
3241
3503
|
cancelled: "cancelled";
|
|
3242
3504
|
}>;
|
|
@@ -3973,6 +4235,35 @@ type HandoffRendererResult = {
|
|
|
3973
4235
|
*/
|
|
3974
4236
|
declare function renderHandoff(input: HandoffRendererInput): Promise<HandoffRendererResult>;
|
|
3975
4237
|
|
|
4238
|
+
/** What a build knows about itself. `commit` is `"unknown"` outside a checkout. */
|
|
4239
|
+
type BuildStamp = {
|
|
4240
|
+
readonly version: string;
|
|
4241
|
+
readonly commit: string;
|
|
4242
|
+
readonly committedAt: string;
|
|
4243
|
+
};
|
|
4244
|
+
/**
|
|
4245
|
+
* Parse an injected stamp. Separate from the constant below so it is reachable
|
|
4246
|
+
* from a test: under vitest the module loads from SOURCE, where the injected
|
|
4247
|
+
* identifier does not exist, so every line of the parse would otherwise be
|
|
4248
|
+
* unreachable -- a guarantee with no test behind it, which is the shape of
|
|
4249
|
+
* omission this whole feature exists to correct.
|
|
4250
|
+
*
|
|
4251
|
+
* Anything unparseable yields `undefined` rather than throwing: a malformed
|
|
4252
|
+
* stamp must not stop the CLI from starting.
|
|
4253
|
+
*/
|
|
4254
|
+
declare function parseBuildStamp(raw: string | undefined): BuildStamp | undefined;
|
|
4255
|
+
/**
|
|
4256
|
+
* Core's own build identity.
|
|
4257
|
+
*
|
|
4258
|
+
* Core is stamped separately from the CLI because the CLI does not bundle it:
|
|
4259
|
+
* `cli/dist` and `core/dist` are distinct artifacts that a partial build can
|
|
4260
|
+
* leave at different commits. A fresh CLI in front of a stale core is the
|
|
4261
|
+
* dangerous half of that pair -- core is where the renderers and importers
|
|
4262
|
+
* live, so the behaviour would be the old one while the CLI reported the new
|
|
4263
|
+
* version.
|
|
4264
|
+
*/
|
|
4265
|
+
declare const BASOU_CORE_BUILD: BuildStamp | undefined;
|
|
4266
|
+
|
|
3976
4267
|
/**
|
|
3977
4268
|
* Parse a unit-suffixed duration string (e.g. `30s`, `5m`, `1h`, `100ms`)
|
|
3978
4269
|
* into milliseconds.
|
|
@@ -4355,6 +4646,13 @@ type OrientationSummary = {
|
|
|
4355
4646
|
* does not sink into the flat decision list. Empty when none are open.
|
|
4356
4647
|
*/
|
|
4357
4648
|
openTracks: TrackRecord[];
|
|
4649
|
+
/**
|
|
4650
|
+
* Decisions recorded by `basou decision capture` that are still open and that
|
|
4651
|
+
* no task carries — the count `basou decision gaps` lists. Surfaced here as a
|
|
4652
|
+
* single number because a ratified plan that became no task is invisible
|
|
4653
|
+
* otherwise, and a command nobody is told to run does not fix that.
|
|
4654
|
+
*/
|
|
4655
|
+
openDecisionGaps: number;
|
|
4358
4656
|
/**
|
|
4359
4657
|
* Most recent `note_added` over non-archived sessions — the recorded next
|
|
4360
4658
|
* step / handoff ("next step") surfaced in the forward section; null when none.
|
|
@@ -4391,6 +4689,15 @@ type OrientationSummary = {
|
|
|
4391
4689
|
* zero in-flight count distinguish "all closed" from "never used here".
|
|
4392
4690
|
* See {@link anyTaskEverRecorded}: a live count is NOT this. */
|
|
4393
4691
|
anyTaskEverRecorded: boolean;
|
|
4692
|
+
/** Task files THIS pass tried and failed to read, so their status is
|
|
4693
|
+
* unknown. A zero in-flight count is only a claim about the files that
|
|
4694
|
+
* parsed: with one of these present, "none in flight" is not something the
|
|
4695
|
+
* renderer can say. Reported to the caller through `onTaskSkip` as well,
|
|
4696
|
+
* but that goes to stderr and the body travels on its own (hooks ship the
|
|
4697
|
+
* body alone). Not a standing count: enumerating tasks can rebuild the
|
|
4698
|
+
* index without the unreadable file, after which later passes do not
|
|
4699
|
+
* attempt it and this reads zero while the file is still on disk. */
|
|
4700
|
+
unreadableTaskCount: number;
|
|
4394
4701
|
/** Tasks whose status is `planned` ("where am I heading"). */
|
|
4395
4702
|
plannedTasks: PlannedTask[];
|
|
4396
4703
|
pendingApprovals: PendingApproval[];
|
|
@@ -4736,8 +5043,9 @@ type ViewPresetInput = {
|
|
|
4736
5043
|
* operator-specific string is embedded), so re-running on an unchanged manifest
|
|
4737
5044
|
* produces byte-identical output. The view is a workspace-level artifact, so
|
|
4738
5045
|
* its content language follows the ANCHOR entry's declared language (mirroring
|
|
4739
|
-
* the generated views' rule)
|
|
4740
|
-
*
|
|
5046
|
+
* the generated views' rule). It no longer reproduces the pre-i18n output: the
|
|
5047
|
+
* block gained a line naming where the session roster lives, which that output
|
|
5048
|
+
* predates. The repos are listed in the order supplied. An empty roster
|
|
4741
5049
|
* still renders cleanly (a header-only table, empty lists). Returns the block
|
|
4742
5050
|
* WITHOUT a trailing newline; the marker writer adds the surrounding structure.
|
|
4743
5051
|
*/
|
|
@@ -5662,14 +5970,14 @@ declare function planWorkspaceView(facts: ViewRepoFact[], existing?: ExistingVie
|
|
|
5662
5970
|
* changed without the envelope's own format changing.
|
|
5663
5971
|
*/
|
|
5664
5972
|
declare const JSON_SCHEMA_VERSIONS: {
|
|
5665
|
-
readonly manifest: "0.
|
|
5666
|
-
readonly session: "0.
|
|
5667
|
-
readonly event: "0.
|
|
5668
|
-
readonly task: "0.
|
|
5669
|
-
readonly approval: "0.
|
|
5973
|
+
readonly manifest: "0.2.0";
|
|
5974
|
+
readonly session: "0.2.0";
|
|
5975
|
+
readonly event: "0.3.0";
|
|
5976
|
+
readonly task: "0.2.0";
|
|
5977
|
+
readonly approval: "0.2.0";
|
|
5670
5978
|
readonly status: "0.1.0";
|
|
5671
5979
|
readonly "task-index": "0.1.0";
|
|
5672
|
-
readonly "session-import": "0.
|
|
5980
|
+
readonly "session-import": "0.2.0";
|
|
5673
5981
|
};
|
|
5674
5982
|
/** One emitted JSON Schema artifact. */
|
|
5675
5983
|
type JsonSchemaArtifact = {
|
|
@@ -5809,14 +6117,21 @@ declare const SchemaVersionSchema: z.ZodString;
|
|
|
5809
6117
|
* and would need the pattern written a second time, which is a second place to
|
|
5810
6118
|
* forget. {@link SchemaVersionSchema} takes the same form for the same reason.
|
|
5811
6119
|
*
|
|
5812
|
-
* It deliberately does NOT declare `format: "date-time"`.
|
|
5813
|
-
*
|
|
5814
|
-
*
|
|
5815
|
-
*
|
|
5816
|
-
*
|
|
5817
|
-
*
|
|
5818
|
-
*
|
|
5819
|
-
*
|
|
6120
|
+
* It deliberately does NOT declare `format: "date-time"`. The sets used to
|
|
6121
|
+
* CROSS — basou took a timestamp without seconds, which RFC 3339 does not —
|
|
6122
|
+
* and declaring the format made one artifact answer two ways from the same
|
|
6123
|
+
* bytes: a validator asserting it rejected `2026-09-16T01:23Z`, one treating
|
|
6124
|
+
* it as an annotation (the JSON Schema 2020-12 default) accepted it.
|
|
6125
|
+
*
|
|
6126
|
+
* Requiring seconds ended the crossing: this set is now a strict SUBSET of
|
|
6127
|
+
* RFC 3339 `date-time`, since uppercase-only and no-leap-second are
|
|
6128
|
+
* restrictions on it. So the format could be declared truthfully again. It is
|
|
6129
|
+
* still not declared, for a different reason than before — the `pattern` is
|
|
6130
|
+
* the whole contract and the format names a strictly larger set, so declaring
|
|
6131
|
+
* it would say less than the artifact already says while reintroducing a
|
|
6132
|
+
* keyword whose enforcement varies by validator. Reinstating it is a decision
|
|
6133
|
+
* about what the artifact should assert, not a correction; `description` is
|
|
6134
|
+
* what states this set, because no format name does.
|
|
5820
6135
|
*/
|
|
5821
6136
|
declare const IsoTimestampSchema: z.ZodString;
|
|
5822
6137
|
/** Workspace ID schema: validates `ws_<26-char ULID>`. */
|
|
@@ -5849,6 +6164,18 @@ type RiskLevel = z.infer<typeof RiskLevelSchema>;
|
|
|
5849
6164
|
* non-empty string in v0.1; a stricter enum may be introduced post-v0.1.
|
|
5850
6165
|
*/
|
|
5851
6166
|
declare const EventSourceSchema: z.ZodString;
|
|
6167
|
+
/**
|
|
6168
|
+
* The `source` basou stamps on an event it wrote itself, in response to a
|
|
6169
|
+
* `basou` command the operator (or an agent acting for them) ran — as opposed
|
|
6170
|
+
* to an event an importer derived from a vendor transcript.
|
|
6171
|
+
*
|
|
6172
|
+
* It is a named constant because a reader distinguishes the two: `plan-gaps`
|
|
6173
|
+
* admits a decision to its population only when this source recorded it, so a
|
|
6174
|
+
* writer drifting from this literal would silently shrink that population
|
|
6175
|
+
* rather than fail. Every local writer imports this rather than repeating the
|
|
6176
|
+
* string, so the reader's predicate and the writers have one origin.
|
|
6177
|
+
*/
|
|
6178
|
+
declare const LOCAL_CLI_EVENT_SOURCE = "local-cli";
|
|
5852
6179
|
|
|
5853
6180
|
/**
|
|
5854
6181
|
* Schema for `.basou/status.json` — a forward-incompat cache of the current
|
|
@@ -6993,7 +7320,7 @@ type ImportSessionResult = {
|
|
|
6993
7320
|
/**
|
|
6994
7321
|
* Import a round-trip JSON payload into `.basou/sessions/<new>/`. The caller
|
|
6995
7322
|
* MUST validate the payload against {@link SessionImportPayloadSchema} first
|
|
6996
|
-
* and gate the `schema_version ===
|
|
7323
|
+
* and gate the `schema_version === SESSION_IMPORT_SCHEMA_VERSION` check externally; this
|
|
6997
7324
|
* function trusts both invariants.
|
|
6998
7325
|
*
|
|
6999
7326
|
* On success a fresh session ID is minted and a complete
|
|
@@ -7181,4 +7508,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
|
|
|
7181
7508
|
*/
|
|
7182
7509
|
declare const BASOU_CORE_VERSION = "0.1.0";
|
|
7183
7510
|
|
|
7184
|
-
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 CodexHooksFile, 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, 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, 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 PresetStrings, 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 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_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, 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, chainEvents, chainRawJsonLines, classifyFilesBySourceRoot, classifyRetrofit, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexAdapterMetadata, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, evaluateStopHook, finalizeSessionYaml, findBasouSessionStartHook, findBasouStopHookCommand, findErrorCode, findReviewGaps, findUnbindableRepos, formatDurationMs, genesisHash, getDiff, getSnapshot, hasRetiredZeroDuration, importSessionFromJson, inspectChainTail, instructionMode, isBasouSessionStartHookCommand, 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, presetStrings, readAllEvents, readManifest, readMarkdownFile, readObservedDuration, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeSessionStartHook, removeStopHook, renderAnchorStarter, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, 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, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, upsertSessionStartHook, upsertStopHook, verifyEventsChain, viewStrings, writeEventsBulk, writeManifest, writeMarkdownFile, writeObservedDuration, writeStatus, writeTaskFile, writeYamlFile };
|
|
7511
|
+
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, type PrefixedId, type PresetAction, type PresetCollision, type PresetMarkerConflict, type PresetMarkerKind, type PresetPlanSummary, type PresetRepo, type PresetStrings, 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 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, 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, isRenderable, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadFederatedSessionEntries, loadSessionEntries, loadTaskEntries, normalizeRepoKey, normalizeRepoPath, overwriteYamlFile, parseBuildStamp, parseDuration, parseMarkers, parseReviewRecordInput, pathBasename, planArchive, planGitignore, planRename, planRosterAdoption, planWorkspaceView, prefixedUlid, presetStrings, readAllEvents, readManifest, readMarkdownFile, readObservedDuration, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileSourceRoots, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, removeMarkerSection, removeSessionStartHook, removeStopHook, renderAnchorStarter, renderDecisions, renderHandoff, renderOrientation, renderPresetBlock, 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, tryRemoteUrl, ulid, unknownManifestKeys, updateTaskStatusWithEvent, upsertSessionStartHook, upsertStopHook, verifyEventsChain, viewStrings, writeEventsBulk, writeManifest, writeMarkdownFile, writeObservedDuration, writeStatus, writeTaskFile, writeYamlFile };
|