@basou/core 0.10.0 → 0.12.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 +431 -110
- package/dist/index.js +1131 -412
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -678,6 +678,7 @@ type BasouPaths = {
|
|
|
678
678
|
readonly status: string;
|
|
679
679
|
readonly handoff: string;
|
|
680
680
|
readonly decisions: string;
|
|
681
|
+
readonly orientation: string;
|
|
681
682
|
};
|
|
682
683
|
};
|
|
683
684
|
/**
|
|
@@ -2031,6 +2032,29 @@ type GitSnapshot = Omit<GitSnapshotEvent, "schema_version" | "id" | "session_id"
|
|
|
2031
2032
|
* path; native errors are kept on `error.cause` for verbose surfacing.
|
|
2032
2033
|
*/
|
|
2033
2034
|
declare function resolveRepositoryRoot(cwd: string): Promise<string>;
|
|
2035
|
+
/**
|
|
2036
|
+
* Resolve the repository root that owns the `.basou/` store for `cwd`, with a
|
|
2037
|
+
* fallback for agents-workspace "view" directories. A workspace view (e.g.
|
|
2038
|
+
* `~/projects/foo-workspace`) is intentionally OUTSIDE git and holds no `.basou/`
|
|
2039
|
+
* of its own; it aggregates sibling repos through symlinks (`foo-planning ->
|
|
2040
|
+
* ../foo-planning`). Running `basou orient` / `refresh` from there would
|
|
2041
|
+
* otherwise die with "Not a git repository" even though the view IS the
|
|
2042
|
+
* operator's daily cwd.
|
|
2043
|
+
*
|
|
2044
|
+
* Resolution:
|
|
2045
|
+
* 1. If `cwd` is inside a git repo, return its toplevel (unchanged behavior).
|
|
2046
|
+
* 2. Otherwise inspect `cwd`'s direct symlinks; if exactly one points at a
|
|
2047
|
+
* directory that has a `.basou/` store, redirect to that repo (firing
|
|
2048
|
+
* `onRedirect`). Zero candidates re-throws the original "Not a git
|
|
2049
|
+
* repository"; two or more throws an ambiguity error naming them so the
|
|
2050
|
+
* operator can `cd` into the right one.
|
|
2051
|
+
*/
|
|
2052
|
+
declare function resolveBasouRepositoryRoot(cwd: string, opts?: {
|
|
2053
|
+
onRedirect?: (info: {
|
|
2054
|
+
via: string;
|
|
2055
|
+
root: string;
|
|
2056
|
+
}) => void;
|
|
2057
|
+
}): Promise<string>;
|
|
2034
2058
|
/**
|
|
2035
2059
|
* Read `remote.origin.url` from the local repository config. Returns
|
|
2036
2060
|
* `undefined` if the remote is unset, the value is empty, or the lookup
|
|
@@ -2908,6 +2932,13 @@ declare function renderHandoff(input: HandoffRendererInput): Promise<HandoffRend
|
|
|
2908
2932
|
*/
|
|
2909
2933
|
declare function parseDuration(input: string): number;
|
|
2910
2934
|
|
|
2935
|
+
/**
|
|
2936
|
+
* Coarse human duration from milliseconds: "3h 05m" / "12m 30s" / "8s".
|
|
2937
|
+
* Shared by the work-stats surfaces (`basou stats`, `basou session show`) and
|
|
2938
|
+
* the report renderer so they format identically.
|
|
2939
|
+
*/
|
|
2940
|
+
declare function formatDurationMs(ms: number): string;
|
|
2941
|
+
|
|
2911
2942
|
/**
|
|
2912
2943
|
* Resolve a possibly-truncated session id prefix to a full session id by
|
|
2913
2944
|
* scanning `<paths.sessions>/`. Existing message contract (carried over
|
|
@@ -3019,121 +3050,155 @@ type SanitizeRelatedFilesResult = {
|
|
|
3019
3050
|
*/
|
|
3020
3051
|
declare function sanitizeRelatedFiles(paths: ReadonlyArray<string>, opts: SanitizePathOptions): SanitizeRelatedFilesResult;
|
|
3021
3052
|
|
|
3022
|
-
/**
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
* adapter surface. Adapters do not import or instantiate it directly;
|
|
3033
|
-
* CLI / Core orchestration owns construction and invocation.
|
|
3034
|
-
*/
|
|
3035
|
-
/**
|
|
3036
|
-
* Output capture mode.
|
|
3037
|
-
*
|
|
3038
|
-
* - `"buffer"` (default): pipe stdout/stderr to the runner and accumulate
|
|
3039
|
-
* the full UTF-8 string into {@link RunResult}.
|
|
3040
|
-
* - `"none"`: inherit the parent's stdio. The child writes directly to the
|
|
3041
|
-
* parent terminal in real time and {@link RunResult.stdout} /
|
|
3042
|
-
* {@link RunResult.stderr} are empty strings. `stdin` cannot be combined
|
|
3043
|
-
* with `"none"` because the child has no writable stdin pipe.
|
|
3044
|
-
*/
|
|
3045
|
-
type CaptureMode = "buffer" | "none";
|
|
3046
|
-
type RunOptions = {
|
|
3047
|
-
/**
|
|
3048
|
-
* Working directory for the child process. Required: callers resolve
|
|
3049
|
-
* the workspace root themselves; the runner does not validate cwd
|
|
3050
|
-
* existence and surfaces native spawn errors via classification.
|
|
3051
|
-
*/
|
|
3052
|
-
readonly cwd: string;
|
|
3053
|
-
/**
|
|
3054
|
-
* Environment variables for the child. When omitted, the parent's
|
|
3055
|
-
* `process.env` is inherited verbatim. Callers wanting a sanitized
|
|
3056
|
-
* environment must build it explicitly.
|
|
3057
|
-
*/
|
|
3058
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
3059
|
-
/**
|
|
3060
|
-
* External cancellation. Aborting the signal triggers a two-stage
|
|
3061
|
-
* kill (SIGTERM, then SIGKILL after a short grace period).
|
|
3062
|
-
*/
|
|
3063
|
-
readonly signal?: AbortSignal;
|
|
3064
|
-
/**
|
|
3065
|
-
* Internal timeout in milliseconds. Must be a positive finite number.
|
|
3066
|
-
* Triggers the same two-stage kill as `signal`.
|
|
3067
|
-
*/
|
|
3068
|
-
readonly timeout_ms?: number;
|
|
3069
|
-
/**
|
|
3070
|
-
* Optional input written to the child's stdin. The pipe is closed
|
|
3071
|
-
* after the value is written. Incompatible with `capture: "none"`.
|
|
3072
|
-
*/
|
|
3073
|
-
readonly stdin?: string | Buffer;
|
|
3053
|
+
/** Input contract for {@link renderOrientation} and {@link summarizeOrientation}. */
|
|
3054
|
+
type OrientationRendererInput = {
|
|
3055
|
+
paths: BasouPaths;
|
|
3056
|
+
/** ISO timestamp embedded in the header AND used as "now" for freshness + suspect classification. */
|
|
3057
|
+
nowIso: string;
|
|
3058
|
+
onWarning?: (warning: ReplayWarning, sessionId: string) => void;
|
|
3059
|
+
onSessionSkip?: (sessionId: string, reason: SessionSkipReason) => void;
|
|
3060
|
+
onTaskSkip?: (taskId: string, reason: TaskSkipReason) => void;
|
|
3061
|
+
/** Maximum related_files entries to display before `... +N more`. Default 10. */
|
|
3062
|
+
relatedFilesLimit?: number;
|
|
3074
3063
|
/**
|
|
3075
|
-
*
|
|
3064
|
+
* Result of a read-only dry-run staleness probe (sessions a `basou refresh`
|
|
3065
|
+
* would add or update), computed by the CLI which holds the import context.
|
|
3066
|
+
* Drives the plain "これは最新か" verdict. `null` / omitted = not probed, so
|
|
3067
|
+
* the verdict says it cannot confirm freshness rather than claiming current.
|
|
3076
3068
|
*/
|
|
3077
|
-
|
|
3069
|
+
staleness?: {
|
|
3070
|
+
newSessions: number;
|
|
3071
|
+
updatedSessions: number;
|
|
3072
|
+
unverifiableSessions?: number;
|
|
3073
|
+
} | null;
|
|
3078
3074
|
/**
|
|
3079
|
-
*
|
|
3080
|
-
*
|
|
3081
|
-
*
|
|
3082
|
-
* the child if the parent is forcibly terminated). The runner takes no
|
|
3083
|
-
* action if the callback throws.
|
|
3075
|
+
* Append the raw freshness telemetry (ISO timestamp, per-source counts, source
|
|
3076
|
+
* roots, suspect count) under the plain verdict. Off by default so the section
|
|
3077
|
+
* reads as a verdict for a supervisor, not developer diagnostics.
|
|
3084
3078
|
*/
|
|
3085
|
-
|
|
3079
|
+
verbose?: boolean;
|
|
3086
3080
|
};
|
|
3087
|
-
type
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
/** ISO 8601 timestamp captured before spawn. */
|
|
3097
|
-
readonly started_at: string;
|
|
3098
|
-
/** ISO 8601 timestamp captured on the `close` event. */
|
|
3099
|
-
readonly ended_at: string;
|
|
3100
|
-
readonly duration_ms: number;
|
|
3101
|
-
readonly pid: number | null;
|
|
3081
|
+
type OrientationRendererResult = {
|
|
3082
|
+
/** Generated body. orientation.md is overwritten whole (no markers, gitignored). */
|
|
3083
|
+
body: string;
|
|
3084
|
+
sessionCount: number;
|
|
3085
|
+
pendingApprovalsCount: number;
|
|
3086
|
+
suspectCount: number;
|
|
3087
|
+
/** Tasks whose status is `planned` or `in_progress`. */
|
|
3088
|
+
inFlightTaskCount: number;
|
|
3089
|
+
decisionCount: number;
|
|
3102
3090
|
};
|
|
3103
|
-
type
|
|
3104
|
-
|
|
3091
|
+
type DecisionRecord = {
|
|
3092
|
+
decisionId: string;
|
|
3093
|
+
title: string;
|
|
3094
|
+
occurredAt: string;
|
|
3095
|
+
};
|
|
3096
|
+
type PendingApproval = {
|
|
3097
|
+
id: string;
|
|
3098
|
+
risk: string;
|
|
3099
|
+
kind: string;
|
|
3100
|
+
reason: string;
|
|
3101
|
+
sessionId: string;
|
|
3102
|
+
createdAt: string;
|
|
3103
|
+
expired: boolean;
|
|
3104
|
+
};
|
|
3105
|
+
type InFlightTask = {
|
|
3106
|
+
id: string;
|
|
3107
|
+
title: string;
|
|
3108
|
+
status: string;
|
|
3109
|
+
linkedSessions: number;
|
|
3110
|
+
};
|
|
3111
|
+
type PlannedTask = {
|
|
3112
|
+
id: string;
|
|
3113
|
+
title: string;
|
|
3114
|
+
};
|
|
3115
|
+
type SuspectSession = {
|
|
3116
|
+
sessionId: string;
|
|
3117
|
+
status: string;
|
|
3118
|
+
reason: SuspectReason | null;
|
|
3119
|
+
};
|
|
3120
|
+
type LatestSession = {
|
|
3121
|
+
sessionId: string;
|
|
3122
|
+
label: string | null;
|
|
3123
|
+
status: string;
|
|
3124
|
+
};
|
|
3125
|
+
type SourceCount = {
|
|
3126
|
+
kind: string;
|
|
3127
|
+
count: number;
|
|
3105
3128
|
};
|
|
3106
|
-
|
|
3107
3129
|
/**
|
|
3108
|
-
*
|
|
3130
|
+
* The vendor-neutral, serializable structured summary behind orientation. This
|
|
3131
|
+
* is the single source of the four orientation questions (where am I now / what
|
|
3132
|
+
* is in flight / where am I heading / is this current). {@link renderOrientation}
|
|
3133
|
+
* formats it into markdown; programmatic consumers (e.g. a multi-workspace
|
|
3134
|
+
* portfolio view) read it directly without parsing prose.
|
|
3109
3135
|
*
|
|
3110
|
-
*
|
|
3111
|
-
*
|
|
3112
|
-
*
|
|
3113
|
-
*
|
|
3114
|
-
*
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3136
|
+
* It carries STRUCTURED FACTS only — the pending-approval list with risk/reason,
|
|
3137
|
+
* suspect sessions, in-flight task linkage, capture freshness/coverage, the
|
|
3138
|
+
* latest decision. It deliberately holds NO work-stats (volume / active time /
|
|
3139
|
+
* tokens) and NO per-agent scorecards, productivity, or utilization metrics:
|
|
3140
|
+
* orientation shows product state, not surveillance of the fleet.
|
|
3141
|
+
*/
|
|
3142
|
+
type OrientationSummary = {
|
|
3143
|
+
/** ISO "now"; the header timestamp and the basis for freshness/suspect classification. */
|
|
3144
|
+
generatedAt: string;
|
|
3145
|
+
/** All captured sessions (archived included), matching the count line. */
|
|
3146
|
+
sessionCount: number;
|
|
3147
|
+
/** Newest non-archived, non-import session ("where am I now"); null when none. */
|
|
3148
|
+
latestSession: LatestSession | null;
|
|
3149
|
+
/** Most recent `decision_recorded` across all sessions; null when none. */
|
|
3150
|
+
latestDecision: DecisionRecord | null;
|
|
3151
|
+
decisionCount: number;
|
|
3152
|
+
/** related_files of the latest session, deduped + sorted + capped at the display limit. */
|
|
3153
|
+
relatedFiles: {
|
|
3154
|
+
displayed: string[];
|
|
3155
|
+
overflow: number;
|
|
3156
|
+
};
|
|
3157
|
+
/** Tasks whose status is `planned` or `in_progress`. */
|
|
3158
|
+
inFlightTasks: InFlightTask[];
|
|
3159
|
+
/** Tasks whose status is `planned` ("where am I heading"). */
|
|
3160
|
+
plannedTasks: PlannedTask[];
|
|
3161
|
+
pendingApprovals: PendingApproval[];
|
|
3162
|
+
suspects: SuspectSession[];
|
|
3163
|
+
freshness: {
|
|
3164
|
+
/** started_at of the newest non-archived session, or null when none captured. */
|
|
3165
|
+
newestStartedAt: string | null;
|
|
3166
|
+
/** source.kind of the newest non-archived session, or null when none captured. */
|
|
3167
|
+
newestSource: string | null;
|
|
3168
|
+
/** Session counts per source kind, sorted by kind. Counts only — never volume/time. */
|
|
3169
|
+
bySource: SourceCount[];
|
|
3170
|
+
/** manifest `import.source_roots`, or null when single-root / unreadable. */
|
|
3171
|
+
sourceRoots: string[] | null;
|
|
3172
|
+
};
|
|
3173
|
+
};
|
|
3174
|
+
/**
|
|
3175
|
+
* Gather the structured orientation facts for a workspace. Read-only and runs
|
|
3176
|
+
* NO imports: freshness reflects already-captured state, so a stale capture is
|
|
3177
|
+
* visible rather than silently refreshed (run `basou refresh` to re-import).
|
|
3128
3178
|
*
|
|
3129
|
-
*
|
|
3130
|
-
*
|
|
3131
|
-
* preserved on `Error.cause`, allowing callers to classify with
|
|
3132
|
-
* `findErrorCode` when needed.
|
|
3179
|
+
* Returns a fully serializable {@link OrientationSummary}. See its docstring for
|
|
3180
|
+
* the positioning constraint (no work-stats, no surveillance metrics).
|
|
3133
3181
|
*/
|
|
3134
|
-
declare
|
|
3135
|
-
|
|
3136
|
-
|
|
3182
|
+
declare function summarizeOrientation(input: OrientationRendererInput): Promise<OrientationSummary>;
|
|
3183
|
+
/**
|
|
3184
|
+
* Render `.basou/orientation.md`: a point-in-time "current position" view for a
|
|
3185
|
+
* supervisor who delegated execution to AI agents. Unlike `handoff.md` (a
|
|
3186
|
+
* session-resume narrative) this answers four orientation questions —
|
|
3187
|
+
* where am I now / what is in flight / where am I heading / is this current —
|
|
3188
|
+
* and deliberately leads with STRUCTURED FACTS an LLM cannot reliably derive
|
|
3189
|
+
* from raw transcripts (the
|
|
3190
|
+
* pending-approval list with risk/reason, suspect sessions, in-flight task
|
|
3191
|
+
* linkage, capture freshness/coverage) rather than prose synthesis.
|
|
3192
|
+
*
|
|
3193
|
+
* The renderer is read-only and runs NO imports: the freshness section reflects
|
|
3194
|
+
* already-captured state, so a stale capture is visible rather than silently
|
|
3195
|
+
* refreshed (use `basou refresh` to re-import). It must never emit per-agent
|
|
3196
|
+
* scorecards, productivity, or utilization metrics — orientation shows product
|
|
3197
|
+
* state, not surveillance of the fleet.
|
|
3198
|
+
*
|
|
3199
|
+
* Formatting only: the facts come from {@link summarizeOrientation}.
|
|
3200
|
+
*/
|
|
3201
|
+
declare function renderOrientation(input: OrientationRendererInput): Promise<OrientationRendererResult>;
|
|
3137
3202
|
|
|
3138
3203
|
/**
|
|
3139
3204
|
* Schema version of the on-disk Basou v0.1 formats these JSON Schemas describe.
|
|
@@ -3472,10 +3537,262 @@ declare function computeWorkStats(input: WorkStatsInput): Promise<WorkStatsResul
|
|
|
3472
3537
|
*/
|
|
3473
3538
|
declare function sessionWorkStatsFromEvents(sessionId: string, inner: Session["session"], events: ReadonlyArray<Event>, now: Date, eventsUnreadable?: boolean): SessionWorkStats;
|
|
3474
3539
|
|
|
3540
|
+
type ReportRendererInput = {
|
|
3541
|
+
paths: BasouPaths;
|
|
3542
|
+
/** ISO timestamp stamped into the report header and used as the clock. */
|
|
3543
|
+
nowIso: string;
|
|
3544
|
+
/** Optional subject line surfaced in the report title. */
|
|
3545
|
+
title?: string;
|
|
3546
|
+
/**
|
|
3547
|
+
* IANA timezone passed through to {@link computeWorkStats} (it labels the
|
|
3548
|
+
* time figures with the zone). The CLI omits this (host default); tests and
|
|
3549
|
+
* the SDK pass a fixed value for deterministic output. [Codex #5]
|
|
3550
|
+
*/
|
|
3551
|
+
timeZone?: string;
|
|
3552
|
+
onWarning?: (warning: ReplayWarning, sessionId: string) => void;
|
|
3553
|
+
onSessionSkip?: (sessionId: string, reason: SessionSkipReason) => void;
|
|
3554
|
+
onTaskSkip?: (taskId: string, reason: TaskSkipReason) => void;
|
|
3555
|
+
};
|
|
3556
|
+
type ReportSessionItem = {
|
|
3557
|
+
id: string;
|
|
3558
|
+
label: string | null;
|
|
3559
|
+
status: SessionStatus;
|
|
3560
|
+
source: SessionSourceKind;
|
|
3561
|
+
startedAt: string;
|
|
3562
|
+
activeMs: number;
|
|
3563
|
+
outputTokens: number;
|
|
3564
|
+
};
|
|
3565
|
+
type ReportDecisionItem = {
|
|
3566
|
+
id: string;
|
|
3567
|
+
title: string;
|
|
3568
|
+
occurredAt: string;
|
|
3569
|
+
};
|
|
3570
|
+
type ReportTaskItem = {
|
|
3571
|
+
id: string;
|
|
3572
|
+
title: string;
|
|
3573
|
+
status: TaskStatus;
|
|
3574
|
+
};
|
|
3575
|
+
type ReportApprovalItem = {
|
|
3576
|
+
id: string;
|
|
3577
|
+
reason: string;
|
|
3578
|
+
status: ApprovalStatus;
|
|
3579
|
+
riskLevel: RiskLevel;
|
|
3580
|
+
};
|
|
3581
|
+
type TaskStatusCount = {
|
|
3582
|
+
status: TaskStatus;
|
|
3583
|
+
count: number;
|
|
3584
|
+
};
|
|
3585
|
+
/**
|
|
3586
|
+
* Curated, purpose-built structured shape behind `basou report generate
|
|
3587
|
+
* --json`. Deliberately NOT the full {@link WorkStatsResult} — report's JSON
|
|
3588
|
+
* stays a stable contract decoupled from the stats schema. Field names avoid
|
|
3589
|
+
* the word "billable": a report is a neutral work-explanation export, not a
|
|
3590
|
+
* billing artifact. [Codex #2]
|
|
3591
|
+
*/
|
|
3592
|
+
type ReportData = {
|
|
3593
|
+
generatedAt: string;
|
|
3594
|
+
title?: string;
|
|
3595
|
+
/** Earliest session start .. latest session end (or `now` for open sessions). */
|
|
3596
|
+
period: {
|
|
3597
|
+
from: string | null;
|
|
3598
|
+
to: string | null;
|
|
3599
|
+
};
|
|
3600
|
+
sessions: {
|
|
3601
|
+
total: number;
|
|
3602
|
+
byStatus: StatusCount[];
|
|
3603
|
+
items: ReportSessionItem[];
|
|
3604
|
+
};
|
|
3605
|
+
volume: {
|
|
3606
|
+
outputTokens: number;
|
|
3607
|
+
reasoningTokens: number;
|
|
3608
|
+
commandCount: number;
|
|
3609
|
+
fileChangedCount: number;
|
|
3610
|
+
decisionCount: number;
|
|
3611
|
+
tokensAvailable: boolean;
|
|
3612
|
+
};
|
|
3613
|
+
time: {
|
|
3614
|
+
activeMs: number;
|
|
3615
|
+
machineActiveMs: number;
|
|
3616
|
+
machineAvailable: boolean;
|
|
3617
|
+
spanMs: number;
|
|
3618
|
+
commandTimeMs: number;
|
|
3619
|
+
timeZone: string;
|
|
3620
|
+
};
|
|
3621
|
+
decisions: {
|
|
3622
|
+
count: number;
|
|
3623
|
+
items: ReportDecisionItem[];
|
|
3624
|
+
};
|
|
3625
|
+
approvals: {
|
|
3626
|
+
pending: number;
|
|
3627
|
+
approved: number;
|
|
3628
|
+
rejected: number;
|
|
3629
|
+
expired: number;
|
|
3630
|
+
items: ReportApprovalItem[];
|
|
3631
|
+
};
|
|
3632
|
+
tasks: {
|
|
3633
|
+
total: number;
|
|
3634
|
+
byStatus: TaskStatusCount[];
|
|
3635
|
+
items: ReportTaskItem[];
|
|
3636
|
+
};
|
|
3637
|
+
/** Union of related files across non-`import` sessions (full; markdown truncates). */
|
|
3638
|
+
changedFiles: string[];
|
|
3639
|
+
integrity: {
|
|
3640
|
+
total: number;
|
|
3641
|
+
verified: number;
|
|
3642
|
+
unchained: number;
|
|
3643
|
+
empty: number;
|
|
3644
|
+
incomplete: number;
|
|
3645
|
+
in_progress: number;
|
|
3646
|
+
tampered: number;
|
|
3647
|
+
/** Session ids whose chain is `tampered`, surfaced for follow-up. */
|
|
3648
|
+
tamperedSessions: string[];
|
|
3649
|
+
};
|
|
3650
|
+
};
|
|
3651
|
+
type ReportRendererResult = {
|
|
3652
|
+
body: string;
|
|
3653
|
+
data: ReportData;
|
|
3654
|
+
};
|
|
3655
|
+
/**
|
|
3656
|
+
* Render a neutral "work report" — a point-in-time export that explains the
|
|
3657
|
+
* work captured in a workspace: how much, what was decided / approved /
|
|
3658
|
+
* undertaken, which files changed, and whether the local provenance is
|
|
3659
|
+
* internally consistent. It composes existing read primitives only and writes
|
|
3660
|
+
* nothing; the caller chooses where `body` goes (stdout / a file) and whether
|
|
3661
|
+
* to emit the structured `data` as JSON.
|
|
3662
|
+
*
|
|
3663
|
+
* Warning surfaces mirror the sibling renderers: `loadSessionEntries` (suspect
|
|
3664
|
+
* classification) and the decision-aggregation replay (with the same
|
|
3665
|
+
* unreadable-skip wrapper as `decisions-renderer.ts`) report through the
|
|
3666
|
+
* callbacks. {@link computeWorkStats} runs SILENTLY here — it re-reads the same
|
|
3667
|
+
* sessions/events, so surfacing its warnings too would double-emit. [Codex #6]
|
|
3668
|
+
*/
|
|
3669
|
+
declare function renderReport(input: ReportRendererInput): Promise<ReportRendererResult>;
|
|
3670
|
+
|
|
3671
|
+
/**
|
|
3672
|
+
* Internal abstraction over child-process execution.
|
|
3673
|
+
*
|
|
3674
|
+
* The v0.1 implementation is intentionally minimal:
|
|
3675
|
+
* - Optional UTF-8 stdout/stderr capture (`capture: "buffer"`, default) or
|
|
3676
|
+
* pass-through to the parent's stdio (`capture: "none"`).
|
|
3677
|
+
* - No stream callbacks for partial chunks.
|
|
3678
|
+
* - No event emission. Callers wire any event flow separately.
|
|
3679
|
+
*
|
|
3680
|
+
* The boundary is internal: ProcessRunner is not part of the public
|
|
3681
|
+
* adapter surface. Adapters do not import or instantiate it directly;
|
|
3682
|
+
* CLI / Core orchestration owns construction and invocation.
|
|
3683
|
+
*/
|
|
3684
|
+
/**
|
|
3685
|
+
* Output capture mode.
|
|
3686
|
+
*
|
|
3687
|
+
* - `"buffer"` (default): pipe stdout/stderr to the runner and accumulate
|
|
3688
|
+
* the full UTF-8 string into {@link RunResult}.
|
|
3689
|
+
* - `"none"`: inherit the parent's stdio. The child writes directly to the
|
|
3690
|
+
* parent terminal in real time and {@link RunResult.stdout} /
|
|
3691
|
+
* {@link RunResult.stderr} are empty strings. `stdin` cannot be combined
|
|
3692
|
+
* with `"none"` because the child has no writable stdin pipe.
|
|
3693
|
+
*/
|
|
3694
|
+
type CaptureMode = "buffer" | "none";
|
|
3695
|
+
type RunOptions = {
|
|
3696
|
+
/**
|
|
3697
|
+
* Working directory for the child process. Required: callers resolve
|
|
3698
|
+
* the workspace root themselves; the runner does not validate cwd
|
|
3699
|
+
* existence and surfaces native spawn errors via classification.
|
|
3700
|
+
*/
|
|
3701
|
+
readonly cwd: string;
|
|
3702
|
+
/**
|
|
3703
|
+
* Environment variables for the child. When omitted, the parent's
|
|
3704
|
+
* `process.env` is inherited verbatim. Callers wanting a sanitized
|
|
3705
|
+
* environment must build it explicitly.
|
|
3706
|
+
*/
|
|
3707
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
3708
|
+
/**
|
|
3709
|
+
* External cancellation. Aborting the signal triggers a two-stage
|
|
3710
|
+
* kill (SIGTERM, then SIGKILL after a short grace period).
|
|
3711
|
+
*/
|
|
3712
|
+
readonly signal?: AbortSignal;
|
|
3713
|
+
/**
|
|
3714
|
+
* Internal timeout in milliseconds. Must be a positive finite number.
|
|
3715
|
+
* Triggers the same two-stage kill as `signal`.
|
|
3716
|
+
*/
|
|
3717
|
+
readonly timeout_ms?: number;
|
|
3718
|
+
/**
|
|
3719
|
+
* Optional input written to the child's stdin. The pipe is closed
|
|
3720
|
+
* after the value is written. Incompatible with `capture: "none"`.
|
|
3721
|
+
*/
|
|
3722
|
+
readonly stdin?: string | Buffer;
|
|
3723
|
+
/**
|
|
3724
|
+
* Output capture mode. Defaults to `"buffer"`. See {@link CaptureMode}.
|
|
3725
|
+
*/
|
|
3726
|
+
readonly capture?: CaptureMode;
|
|
3727
|
+
/**
|
|
3728
|
+
* Invoked synchronously immediately after the child has been spawned,
|
|
3729
|
+
* before the runner waits for completion. Callers use this to retain a
|
|
3730
|
+
* reference for parent-side cleanup (e.g. an `exit` hook that SIGKILLs
|
|
3731
|
+
* the child if the parent is forcibly terminated). The runner takes no
|
|
3732
|
+
* action if the callback throws.
|
|
3733
|
+
*/
|
|
3734
|
+
readonly onSpawn?: (child: ChildProcess) => void;
|
|
3735
|
+
};
|
|
3736
|
+
type RunResult = {
|
|
3737
|
+
readonly command: string;
|
|
3738
|
+
readonly args: readonly string[];
|
|
3739
|
+
readonly cwd: string;
|
|
3740
|
+
/** `null` when the process was killed by a signal. */
|
|
3741
|
+
readonly exit_code: number | null;
|
|
3742
|
+
readonly signal: NodeJS.Signals | null;
|
|
3743
|
+
readonly stdout: string;
|
|
3744
|
+
readonly stderr: string;
|
|
3745
|
+
/** ISO 8601 timestamp captured before spawn. */
|
|
3746
|
+
readonly started_at: string;
|
|
3747
|
+
/** ISO 8601 timestamp captured on the `close` event. */
|
|
3748
|
+
readonly ended_at: string;
|
|
3749
|
+
readonly duration_ms: number;
|
|
3750
|
+
readonly pid: number | null;
|
|
3751
|
+
};
|
|
3752
|
+
type ProcessRunner = {
|
|
3753
|
+
run(command: string, args: readonly string[], options: RunOptions): Promise<RunResult>;
|
|
3754
|
+
};
|
|
3755
|
+
|
|
3756
|
+
/**
|
|
3757
|
+
* Spawn-based ProcessRunner implementation.
|
|
3758
|
+
*
|
|
3759
|
+
* Behavior:
|
|
3760
|
+
* - `shell: false` and `detached: false`. The process group is not
|
|
3761
|
+
* detached, but the OS does not guarantee the child is reaped when
|
|
3762
|
+
* the parent terminates abruptly; callers handle SIGINT/SIGTERM/exit
|
|
3763
|
+
* hooks themselves.
|
|
3764
|
+
* - `capture: "buffer"` (default): `stdio: ['pipe', 'pipe', 'pipe']`,
|
|
3765
|
+
* stdout / stderr are decoded as UTF-8 and accumulated as full
|
|
3766
|
+
* strings (no streaming callbacks).
|
|
3767
|
+
* - `capture: "none"`: `stdio: ['inherit', 'inherit', 'inherit']`, the
|
|
3768
|
+
* child writes directly to the parent terminal in real time and
|
|
3769
|
+
* `RunResult.stdout` / `stderr` are empty strings. `stdin` is
|
|
3770
|
+
* incompatible with this mode (the child has no writable stdin pipe)
|
|
3771
|
+
* and the combination is rejected before spawn.
|
|
3772
|
+
* - `timeout_ms` and `AbortSignal` both trigger a two-stage kill:
|
|
3773
|
+
* `SIGTERM`, then `SIGKILL` after `DEFAULT_KILL_GRACE_MS` (5_000 ms).
|
|
3774
|
+
* - A non-zero `exit_code` does not throw; it is returned via
|
|
3775
|
+
* `RunResult`. Spawn-time errors throw with a pathless message and
|
|
3776
|
+
* the original error attached as `cause`.
|
|
3777
|
+
*
|
|
3778
|
+
* Error message contract: messages never include `cwd` or absolute
|
|
3779
|
+
* command paths. The original errno (and any nested wrapping) is
|
|
3780
|
+
* preserved on `Error.cause`, allowing callers to classify with
|
|
3781
|
+
* `findErrorCode` when needed.
|
|
3782
|
+
*/
|
|
3783
|
+
declare class ChildProcessRunner implements ProcessRunner {
|
|
3784
|
+
run(command: string, args: readonly string[], options: RunOptions): Promise<RunResult>;
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3475
3787
|
type AppendBasouGitignoreResult = {
|
|
3476
3788
|
/** True if the block was appended (or the file was newly created). */
|
|
3477
3789
|
readonly appended: boolean;
|
|
3478
3790
|
};
|
|
3791
|
+
/** Options for {@link appendBasouGitignore}. */
|
|
3792
|
+
type AppendBasouGitignoreOptions = {
|
|
3793
|
+
/** Write a `.basou/` full-exclude block instead of the default ignore+commit block. */
|
|
3794
|
+
readonly localOnly?: boolean;
|
|
3795
|
+
};
|
|
3479
3796
|
/**
|
|
3480
3797
|
* Append Basou's default `.gitignore` block to `repositoryRoot/.gitignore`.
|
|
3481
3798
|
*
|
|
@@ -3483,11 +3800,15 @@ type AppendBasouGitignoreResult = {
|
|
|
3483
3800
|
* standard ignore + commit recommendations). Callers must pass an absolute
|
|
3484
3801
|
* path to a Git repository root.
|
|
3485
3802
|
*
|
|
3803
|
+
* With `options.localOnly`, a `.basou/` full-exclude block is written instead
|
|
3804
|
+
* of the default ignore+commit block (the trail is kept out of version
|
|
3805
|
+
* control). The default (no options) is unchanged.
|
|
3806
|
+
*
|
|
3486
3807
|
* Behavior:
|
|
3487
|
-
* - If `.gitignore` does not exist, it is created with the Basou block.
|
|
3488
|
-
* - If a
|
|
3489
|
-
* the file is left untouched and `appended: false`
|
|
3490
|
-
* (idempotent).
|
|
3808
|
+
* - If `.gitignore` does not exist, it is created with the chosen Basou block.
|
|
3809
|
+
* - If a `# Basou - default ignore` marker OR a standalone `.basou/` exclude
|
|
3810
|
+
* line is already present, the file is left untouched and `appended: false`
|
|
3811
|
+
* is returned (idempotent across both modes).
|
|
3491
3812
|
* - If `.gitignore` is a symlink, the link is followed and the target file
|
|
3492
3813
|
* is updated. Symlinks are not rejected.
|
|
3493
3814
|
*
|
|
@@ -3495,7 +3816,7 @@ type AppendBasouGitignoreResult = {
|
|
|
3495
3816
|
* (`Failed to read .gitignore` / `Failed to write .gitignore`) and the
|
|
3496
3817
|
* original native error attached as `cause`.
|
|
3497
3818
|
*/
|
|
3498
|
-
declare function appendBasouGitignore(repositoryRoot: string): Promise<AppendBasouGitignoreResult>;
|
|
3819
|
+
declare function appendBasouGitignore(repositoryRoot: string, options?: AppendBasouGitignoreOptions): Promise<AppendBasouGitignoreResult>;
|
|
3499
3820
|
|
|
3500
3821
|
/**
|
|
3501
3822
|
* The two lock scopes basou uses. `task` guards the read-modify-write window
|
|
@@ -3884,4 +4205,4 @@ declare function overwriteYamlFile(filePath: string, value: unknown): Promise<vo
|
|
|
3884
4205
|
*/
|
|
3885
4206
|
declare const BASOU_CORE_VERSION = "0.1.0";
|
|
3886
4207
|
|
|
3887
|
-
export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, type AppendBasouGitignoreResult, type AppendEventToExistingInput, type AppendEventToExistingResult, type Approval, type ApprovalApprovedEvent, type ApprovalExpiredEvent, ApprovalIdSchema, type ApprovalLocation, type ApprovalRejectedEvent, type ApprovalRequestedEvent, ApprovalSchema, type ApprovalStatus, ApprovalStatusSchema, type ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type PrefixedId, type ProcessRunner, 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 ReplayOptions, type ReplayWarning, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, chainEvents, chainRawJsonLines, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, finalizeSessionYaml, findErrorCode, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, isImportDerivedSource, isLazyExpired, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, renderDecisions, renderHandoff, renderWithMarkers, replayEvents, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, tryRemoteUrl, ulid, updateTaskStatusWithEvent, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|
|
4208
|
+
export { ACTIVE_GAP_CAP_MS, type ActiveTimeBasis, type AdapterOutputEvent, 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 ArchiveTaskInput, type ArchiveTaskResult, type AttachTaskInput, type AttachUpdateTaskStatusInput, type AttachableStatus, BASOU_CORE_VERSION, type BasouPaths, type BulkChainResult, CLAUDE_IMPORT_SOURCE, CODEX_IMPORT_SOURCE, type CaptureMode, type ChainBreakReason, type ChainTailState, type ChainVerdict, type ChainVerdictStatus, type ChainedEvents, ChildProcessRunner, type ClaudeTranscriptRecord, type ClaudeTranscriptToPayloadOptions, type CodexRolloutRecord, type CodexRolloutToPayloadOptions, type CommandExecutedEvent, type CommandLookup, type CreateAdHocSessionInput, type CreateAdHocSessionResult, type CreateAdHocTaskInput, type CreateManifestInput, type CreateTaskInput, type CreateTaskResult, type DayWorkStats, DecisionIdSchema, type DecisionRecordedEvent, type DecisionsRendererInput, type DecisionsRendererResult, type DeleteTaskInput, type DeleteTaskResult, type DiffResult, type EditTaskInput, type EditTaskResult, type Event, EventIdSchema, EventSchema, EventSourceSchema, FailedToFinalizeError, type FileChange, type FileChangeStatus, type FileChangedEvent, GENERATED_END, GENERATED_START, type GitSnapshot, type GitSnapshotEvent, type HandoffRendererInput, type HandoffRendererResult, ID_PREFIXES, type IdPrefix, type ImportSessionOptions, type ImportSessionResult, IsoTimestampSchema, JSON_SCHEMA_VERSION, type JsonSchemaArtifact, type LoadSessionEntriesOptions, type LoadTaskEntriesOptions, type LoadedApproval, type LockHandle, type LockScope, type Manifest, ManifestSchema, type MarkerSection, type MeasureAvailability, type NoteAddedEvent, type OrientationRendererInput, type OrientationRendererResult, type OrientationSummary, type PrefixedId, type ProcessRunner, 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 ReplayOptions, type ReplayWarning, type ReportApprovalItem, type ReportData, type ReportDecisionItem, type ReportRendererInput, type ReportRendererResult, type ReportSessionItem, type ReportTaskItem, type RiskLevel, RiskLevelSchema, type RunOptions, type RunResult, STUCK_THRESHOLD_MS, type SanitizePathOptions, type SanitizeRelatedFilesResult, SchemaVersionSchema, type Session, type SessionEndedEvent, type SessionEntry, SessionIdSchema, type SessionImportPayload, SessionImportPayloadSchema, type SessionInnerImportInput, SessionInnerImportSchema, type SessionIntegrity, SessionIntegritySchema, type SessionMetrics, SessionMetricsSchema, SessionSchema, type SessionSkipReason, type SessionSourceKind, SessionSourceKindSchema, type SessionStartedEvent, type SessionStatus, type SessionStatusChangedEvent, SessionStatusSchema, type SessionWorkStats, type SourceWorkStats, type StatusCount, StatusSchema, type StatusSnapshot, type SuspectReason, type Task, type TaskArchivedEvent, type TaskCreatedEvent, type TaskDeletedEvent, type TaskDocument, TaskIdSchema, type TaskLinkageRefreshedEvent, type TaskReconciledEvent, TaskSchema, type TaskSkipReason, type TaskStatus, type TaskStatusChangedEvent, type TaskStatusCount, TaskStatusSchema, TaskWriteAfterEventError, type TaskWriteAfterEventPhase, type TokenTotals, type UpdateAdHocTaskStatusInput, type UpdateTaskStatusInput, type UpdateTaskStatusResult, type WorkStatsInput, type WorkStatsResult, type WorkStatsTotals, WorkspaceIdSchema, type WriteEventsBulkOptions, type WriteTaskFileMode, acquireLock, appendBasouGitignore, appendChainedEvent, appendChainedEventLocked, appendEvent, appendEventToExistingSession, archiveTask, assertBasouRootSafe, basouPaths, buildJsonSchemas, buildStatusSnapshot, chainEvents, chainRawJsonLines, classifySuspect, claudeCodeAdapterMetadata, claudeTranscriptToImportPayload, codexRolloutToImportPayload, computeWorkStats, createAdHocSessionWithEvent, createManifest, createTaskWithEvent, deleteTask, editTask, ensureBasouDirectory, enumerateApprovals, enumerateArchivedTaskIds, enumerateSessionDirs, enumerateTaskIds, finalizeSessionYaml, findErrorCode, formatDurationMs, genesisHash, getDiff, getSnapshot, importSessionFromJson, inspectChainTail, isImportDerivedSource, isLazyExpired, isValidPrefixedId, lineHash, linkYamlFile, loadApproval, loadSessionEntries, loadTaskEntries, overwriteYamlFile, parseDuration, parseMarkers, prefixedUlid, readAllEvents, readManifest, readMarkdownFile, readSessionYaml, readStatus, readTaskFile, readTaskFileWithArchiveFallback, readYamlFile, rechainSessionInPlace, reconcileAllTasks, reconcileTask, refreshTaskLinkedSessions, reimportPreservingId, renderDecisions, renderHandoff, renderOrientation, renderReport, renderWithMarkers, replayEvents, resolveBasouRepositoryRoot, resolveClaudeCodeCommand, resolveRepositoryRoot, resolveSessionId, resolveTaskId, sanitizePath, sanitizeRelatedFiles, sanitizeWorkingDirectory, serializeEventLine, serializeJsonSchema, sessionWorkStatsFromEvents, summarizeAdapterOutput, summarizeOrientation, tryRemoteUrl, ulid, updateTaskStatusWithEvent, verifyEventsChain, writeEventsBulk, writeManifest, writeMarkdownFile, writeStatus, writeTaskFile, writeYamlFile };
|