@attentionform/astra 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSE +206 -0
  2. package/NOTICE +12 -0
  3. package/README.md +211 -2
  4. package/dist/cli.js +43821 -0
  5. package/dist/packages/cli/src/cli/baseline-gate.d.ts +25 -0
  6. package/dist/packages/cli/src/cli/batch-cmd.d.ts +177 -0
  7. package/dist/packages/cli/src/cli/create-cmd.d.ts +10 -0
  8. package/dist/packages/cli/src/cli/errors.d.ts +86 -0
  9. package/dist/packages/cli/src/cli/export-cmd.d.ts +2 -0
  10. package/dist/packages/cli/src/cli/history-cmd.d.ts +5 -0
  11. package/dist/packages/cli/src/cli/history-support.d.ts +38 -0
  12. package/dist/packages/cli/src/cli/import-cmd.d.ts +2 -0
  13. package/dist/packages/cli/src/cli/inspect-cmd.d.ts +3 -0
  14. package/dist/packages/cli/src/cli/io.d.ts +70 -0
  15. package/dist/packages/cli/src/cli/normalize-cmd.d.ts +9 -0
  16. package/dist/packages/cli/src/cli/output.d.ts +98 -0
  17. package/dist/packages/cli/src/cli/run.d.ts +6 -0
  18. package/dist/packages/cli/src/cli/sanitize-cmd.d.ts +26 -0
  19. package/dist/packages/cli/src/cli/search-cmd.d.ts +2 -0
  20. package/dist/packages/cli/src/cli/stats-cmd.d.ts +2 -0
  21. package/dist/packages/cli/src/cli/usage.d.ts +8 -0
  22. package/dist/packages/cli/src/cli/validate-cmd.d.ts +2 -0
  23. package/dist/packages/cli/src/cli/visual-cmd.d.ts +34 -0
  24. package/dist/packages/cli/src/cli.d.ts +44 -0
  25. package/dist/packages/cli/src/export.d.ts +24 -0
  26. package/dist/packages/ooxml-validator/src/index.d.ts +33 -0
  27. package/dist/packages/ooxml-validator/src/one-shot.d.ts +2 -0
  28. package/dist/packages/ooxml-validator/src/protocol.d.ts +30 -0
  29. package/dist/packages/ooxml-validator/src/resolve-binary.d.ts +5 -0
  30. package/dist/packages/ooxml-validator/src/types.d.ts +65 -0
  31. package/dist/packages/ooxml-validator/src/worker-client.d.ts +38 -0
  32. package/package.json +70 -4
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The CLI side of the baseline-aware validation gate. A file that already has validator errors can be
3
+ * written when an edit adds none; `--strict` refuses every error as before.
4
+ */
5
+ import { BASELINE_MAX_ERRORS, type BaselineVerdict, type ValidationResult } from '@attentionform/astra-engine';
6
+ export { BASELINE_MAX_ERRORS };
7
+ export type ToleratedVerdict = Extract<BaselineVerdict, {
8
+ kind: 'tolerated';
9
+ }>;
10
+ export type IntroducedVerdict = Extract<BaselineVerdict, {
11
+ kind: 'introduced';
12
+ }>;
13
+ /**
14
+ * Judges the result of a gate. A valid result is clean. Otherwise, unless `strict`, the errors are
15
+ * compared with those of the original bytes, which are validated only now and only when needed.
16
+ */
17
+ export declare function judgeGate(result: ValidationResult, strict: boolean, original: () => Buffer): Promise<BaselineVerdict>;
18
+ /** True when the gate must refuse the write. */
19
+ export declare function refuses(verdict: BaselineVerdict): boolean;
20
+ /** Wording of a refusal for an edit that adds errors to a file that already had some. */
21
+ export declare function introducedText(verdict: IntroducedVerdict, description: string): string;
22
+ /** Fields added to the JSON output when errors the file already had were tolerated. */
23
+ export declare function toleratedFields(verdict: ToleratedVerdict | undefined): Record<string, unknown>;
24
+ /** The line written to stderr when errors the file already had were tolerated. */
25
+ export declare function toleratedNote(verdict: ToleratedVerdict): string;
@@ -0,0 +1,177 @@
1
+ import { type DryRunPreview, type StyleGuideConfig } from '@attentionform/astra-engine';
2
+ import { type GlobalOpts } from './output';
3
+ import { type ZipCeilingOverrides } from './io';
4
+ /** Canonical per-action ops examples (`batch --schema`). */
5
+ export declare function batchSchemaPayload(): Record<string, unknown>;
6
+ export interface OpsFile {
7
+ operations: unknown[];
8
+ sequential?: boolean;
9
+ rollbackOnError?: boolean;
10
+ maxSteps?: number;
11
+ maxRatio?: number;
12
+ maxUncompressedBytes?: number;
13
+ }
14
+ export declare function parseOpsFile(raw: string): OpsFile;
15
+ export declare function printBatchSchema(out: GlobalOpts): number;
16
+ /**
17
+ * Expand CLI-level op extensions before the engine schema gate:
18
+ * - `insert type:heading level:1..3` -> `insert type:xml` carrying a
19
+ * Heading1..3 paragraph (the engine insert schema has no heading type, and
20
+ * this CLI must not grow engine-side edges — the rewrite keeps one op, one
21
+ * anchor, no extra ids).
22
+ * - `{action:'clearDoc'}` (alias `clear-doc`) -> counted separately; the body
23
+ * reset itself runs via clearDocumentBody() before the remaining ops.
24
+ */
25
+ export declare function expandCliOps(operations: unknown[]): {
26
+ ops: unknown[];
27
+ clearCount: number;
28
+ };
29
+ export interface BackupState {
30
+ /** Resolved backup path, or undefined when --backup was not given or this is a dry run. */
31
+ path: string | undefined;
32
+ done: boolean;
33
+ }
34
+ export interface BatchJob {
35
+ opsFile: OpsFile;
36
+ target: string;
37
+ rowLabel: string | undefined;
38
+ }
39
+ export interface RunBatchJobCtx {
40
+ file: string;
41
+ docx: Buffer;
42
+ opsFile: OpsFile;
43
+ target: string;
44
+ sequential: boolean | undefined;
45
+ skipValidate: boolean;
46
+ /** --strict: refuse every validator error, including errors the file already had. */
47
+ strict: boolean;
48
+ /** --no-history: do not record a history revision, even when the document has a history repository. */
49
+ noHistory?: boolean;
50
+ flagCeilings: ZipCeilingOverrides;
51
+ dryRun: boolean;
52
+ backupState: BackupState;
53
+ rowLabel: string | undefined;
54
+ reproducible: boolean | undefined;
55
+ macroOpts: {
56
+ allowMacros: true;
57
+ } | {
58
+ stripMacros: true;
59
+ } | undefined;
60
+ allowedDir?: string | undefined;
61
+ /** Resolved --style-guide config (omitted = built-in defaults, byte-identical). */
62
+ styleGuide?: StyleGuideConfig | undefined;
63
+ /** Parser diagnostics of the resolved --style-guide (ride JSON styleWarnings). */
64
+ styleGuideWarnings?: string[] | undefined;
65
+ }
66
+ export declare function resolveBackupPath(file: string, raw: string | undefined): string;
67
+ /**
68
+ * Snapshot the pre-batch input bytes before the first write. Returns an
69
+ * exit code when the backup itself fails closed (target left untouched),
70
+ * or undefined when the backup is done (or not requested / already done).
71
+ */
72
+ export declare function ensureBackupCopy(out: GlobalOpts, file: string, docx: Buffer, target: string, backupState: BackupState): Promise<number | undefined>;
73
+ /** Split one CSV line (double-quote escaping, "" = literal quote). */
74
+ export declare function splitCsvLine(line: string, source: string): string[];
75
+ /**
76
+ * Minimal CSV reader for --matrix: first non-blank line is the header,
77
+ * every later non-blank line is one data row (one row = one --out).
78
+ */
79
+ export declare function parseMatrixCsv(raw: string, source: string): {
80
+ headers: string[];
81
+ rows: Array<Record<string, string>>;
82
+ };
83
+ /**
84
+ * Literal {{var}} substitution: header names only, single pass over the
85
+ * original string (values are never re-scanned), no expressions,
86
+ * conditionals, loops, or filters. Unknown names fail closed.
87
+ */
88
+ export declare const MATRIX_VAR_RE: RegExp;
89
+ export declare function substituteMatrixString(template: string, row: Record<string, string>, ctx: string): string;
90
+ export declare function substituteMatrixVars(value: unknown, row: Record<string, string>, ctx: string): unknown;
91
+ export declare function truncLine(text: string, max: number): string;
92
+ /** Unified diff of the affected nodes (changed nodes only). */
93
+ export declare function renderUnifiedDiff(preview: DryRunPreview[]): string;
94
+ /** Human + --json report for a successful dry run (writes nothing). */
95
+ export declare function reportDryRun(out: GlobalOpts, args: {
96
+ file: string;
97
+ target: string;
98
+ appliedCount: number;
99
+ cleared: number;
100
+ preview: DryRunPreview[];
101
+ normalized: string[];
102
+ rowLabel: string | undefined;
103
+ possiblyStaleBodyRefs?: {
104
+ nodeId: string;
105
+ preview: string;
106
+ }[];
107
+ }): void;
108
+ export declare function cmdBatch(out: GlobalOpts, args: string[]): Promise<number>;
109
+ export declare function runBatchJob(out: GlobalOpts, ctx: RunBatchJobCtx): Promise<number>;
110
+ export type StreamOnError = 'abort' | 'continue';
111
+ export declare const STREAM_DEFAULT_ON_ERROR: StreamOnError;
112
+ export declare const STREAM_DEFAULT_MAX_ERRORS = 10;
113
+ export interface StreamCmdArgs {
114
+ file: string | undefined;
115
+ opsPath: string | undefined;
116
+ outPath: string | undefined;
117
+ sequential: boolean | undefined;
118
+ skipValidate: boolean;
119
+ strict: boolean;
120
+ noHistory: boolean;
121
+ flagCeilings: ZipCeilingOverrides;
122
+ dryRun: boolean;
123
+ backupGiven: boolean;
124
+ backupRaw: string | undefined;
125
+ matrixRaw: string | undefined;
126
+ targetTextRaw: string | undefined;
127
+ appendRaw: string | undefined;
128
+ onErrorRaw: string | undefined;
129
+ maxErrorsRaw: string | undefined;
130
+ force: boolean;
131
+ reproducible: boolean | undefined;
132
+ macroOpts: {
133
+ allowMacros: true;
134
+ } | {
135
+ stripMacros: true;
136
+ } | undefined;
137
+ allowedDir?: string | undefined;
138
+ /** Resolved --style-guide config (one guide for the invocation; streams apply it wholesale). */
139
+ styleGuide?: StyleGuideConfig | undefined;
140
+ /** Parser diagnostics of the resolved --style-guide (ride the stream eof summary). */
141
+ styleGuideWarnings?: string[] | undefined;
142
+ }
143
+ export interface StreamSessionOpts {
144
+ file: string;
145
+ target: string;
146
+ sequential: boolean | undefined;
147
+ skipValidate: boolean;
148
+ strict?: boolean;
149
+ noHistory?: boolean;
150
+ flagCeilings: ZipCeilingOverrides;
151
+ backupState: BackupState;
152
+ backupSource: Buffer;
153
+ reproducible: boolean | undefined;
154
+ macroOpts: {
155
+ allowMacros: true;
156
+ } | {
157
+ stripMacros: true;
158
+ } | undefined;
159
+ onError: StreamOnError;
160
+ maxErrors: number;
161
+ allowedDir?: string | undefined;
162
+ /** Resolved --style-guide config (one guide for the whole stream). */
163
+ styleGuide?: StyleGuideConfig | undefined;
164
+ /** Parser diagnostics of the resolved --style-guide (ride the stream eof summary). */
165
+ styleGuideWarnings?: string[] | undefined;
166
+ }
167
+ /**
168
+ * Flag/arg validation for --stream plus session wiring. Pre-session failures
169
+ * use the standard fail path (nothing streamed yet, so no acks are owed).
170
+ */
171
+ export declare function cmdBatchStream(out: GlobalOpts, args: StreamCmdArgs): Promise<number>;
172
+ /**
173
+ * Resident stream session over an explicit line source. Emits exactly one ack
174
+ * per non-blank line plus one closing summary, then returns the exit code.
175
+ * Exported so tests can drive it with array lines (no stdin mocking).
176
+ */
177
+ export declare function runStreamSession(out: GlobalOpts, docx: Buffer, opts: StreamSessionOpts, lines: Iterable<string> | AsyncIterable<string>, emit: (ack: Record<string, unknown>) => void): Promise<number>;
@@ -0,0 +1,10 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare const CREATE_TEMPLATES: readonly ["report", "memo", "blank"];
3
+ export type CreateTemplate = (typeof CREATE_TEMPLATES)[number];
4
+ /**
5
+ * A note for a template that comes with text of its own, or undefined for `blank`. `report` holds a whole sample
6
+ * report with invented figures, and `memo` holds a heading and a placeholder line.
7
+ * When Markdown is composed via --from-md or import, the pristine template seed is cleanly replaced.
8
+ */
9
+ export declare function templateSampleNote(template: string, composed: boolean): string | undefined;
10
+ export declare function cmdCreate(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,86 @@
1
+ import { type EngineErrorCode } from '@attentionform/astra-engine';
2
+ import { type GlobalOpts } from './output';
3
+ export declare const KNOWN_CLI_CODES: readonly EngineErrorCode[];
4
+ export type KnownCliCode = EngineErrorCode;
5
+ /** Collapse to one line and strip V8 frames / absolute paths. */
6
+ export declare function cleanCliMessage(raw: string): string;
7
+ /** Rewrite engine/MCP-surface remedy names to CLI-correct ones. */
8
+ export declare function rewriteMcpRemedies(message: string): string;
9
+ /**
10
+ * Sanitize a verbose stack for stderr: same hygiene as the one-liner
11
+ * (relative paths, no emoji, no absolute paths) but multi-line so `at`
12
+ * frames survive. Used only when `--verbose` is set; default output is
13
+ * untouched (exactly one line, never frames).
14
+ */
15
+ export declare function sanitizeVerboseDetail(raw: string): string;
16
+ /** Classify an operational failure into { code, message, remedy }. */
17
+ export declare function toCliError(err: unknown, opts?: {
18
+ file?: string;
19
+ fallbackCode?: KnownCliCode;
20
+ fallbackRemedy?: string;
21
+ }): {
22
+ code: KnownCliCode;
23
+ message: string;
24
+ remedy: string;
25
+ verboseDetail?: string;
26
+ };
27
+ /** Emit the canonical one-line human error (+ optional --json) and return EXIT_FAIL. */
28
+ export declare function failHuman(out: GlobalOpts, err: unknown, opts?: {
29
+ file?: string;
30
+ fallbackCode?: KnownCliCode;
31
+ fallbackRemedy?: string;
32
+ extra?: Record<string, unknown>;
33
+ }): number;
34
+ export declare function fail(out: GlobalOpts, message: string, extra?: Record<string, unknown>): number;
35
+ /**
36
+ * Gate engine-side console chatter (console.error/console.warn) during an
37
+ * engine call. The engine logs raw diagnostics (stacks, absolute paths) that
38
+ * would break CLI error hygiene; the CLI's own one-line [CODE] error carries
39
+ * the failure instead. Both default and `--verbose` gate the raw output so
40
+ * the canonical one-liner stays first; `--verbose` re-adds sanitized frames
41
+ * after it via failHuman/failWithCode (relative paths, no emoji).
42
+ */
43
+ export declare function withGatedEngineOutput<T>(_out: GlobalOpts, fn: () => Promise<T>): Promise<T>;
44
+ export type CliErrorCode = EngineErrorCode;
45
+ /** Extract the engine code from an error (`.code` prop or message prefix). */
46
+ export declare function extractCliErrorCode(err: unknown): CliErrorCode | undefined;
47
+ /** Extract with fallback (strict: callers always name the expected code). */
48
+ export declare function resolveCliErrorCode(err: unknown, fallback: CliErrorCode): CliErrorCode;
49
+ /** Ensure a human message carries its `[CODE]` prefix plus remedy. */
50
+ export declare function ensureCliErrorCodePrefix(message: string, code: CliErrorCode, remedy?: string): string;
51
+ export declare function failWithCode(out: GlobalOpts, message: string, code: KnownCliCode, extra?: Record<string, unknown>, remedy?: string, verboseDetail?: unknown): number;
52
+ export declare function inferBatchCode(err: unknown, fallback?: CliErrorCode): CliErrorCode;
53
+ export interface FileReadClassification {
54
+ code: KnownCliCode;
55
+ message: string;
56
+ remedy: string;
57
+ }
58
+ /**
59
+ * Normalize a file-read failure to the single missing/corrupt shape the
60
+ * human one-liner uses (same regexes, messages, and remedies as
61
+ * toCliError above). Batch read sites bypass toCliError via failWithCode
62
+ * with the raw message, so they classify here first: without this the raw
63
+ * ENOENT/ADM-ZIP/EISDIR text leaks into the one-liner with the wrong
64
+ * remedy. Returns undefined when the error is not a read failure and the
65
+ * caller should keep its existing code/remedy path.
66
+ */
67
+ export declare function classifyFileReadError(err: unknown, file: string): FileReadClassification | undefined;
68
+ /**
69
+ * Location-aware remedy for a post-batch OOXML gate failure. Mirrors the
70
+ * wording and branch logic of the MCP save path
71
+ * (packages/mcp-server/src/lib/mcp/diff.ts remedyForValidationError) with
72
+ * CLI verbs (`astra inspect` / `astra batch` / retry instead of TOON /
73
+ * execute_batch / save_document). The fallback keeps the long-standing
74
+ * generic values hint byte-identical for shapes no branch names.
75
+ */
76
+ export declare function remedyForPostBatchValidation(xPath: unknown, description: unknown): string;
77
+ /** Remedy text without a leading `Remedy:` label or trailing punctuation. */
78
+ export declare function normalizeRemedyText(raw: unknown): string | undefined;
79
+ /** Pull an engine `Remedy: ...` out of a raw error message, if present. */
80
+ export declare function extractEngineRemedy(rawMsg: string): string | undefined;
81
+ /**
82
+ * Read an engine `.remedy` prop (tmp/sandbox throws carry the remedy ONLY on
83
+ * the prop — e.g. `$ASTRA_TMPDIR` symlink refusals — with no `Remedy:` text
84
+ * in the message, so message-only extraction loses it).
85
+ */
86
+ export declare function readErrRemedyProp(err: unknown): string | undefined;
@@ -0,0 +1,2 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdExport(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,5 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdHistory(out: GlobalOpts, args: string[]): Promise<number>;
3
+ export declare function cmdPreviewRevert(out: GlobalOpts, args: string[]): Promise<number>;
4
+ export declare function cmdRevert(out: GlobalOpts, args: string[]): Promise<number>;
5
+ export declare function cmdRedo(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,38 @@
1
+ import { DocxParser } from '@attentionform/astra-engine';
2
+ export declare function capCommitMessage(message: string): string;
3
+ /** Sidecar `.git` state: a real repo directory, a stray non-directory entry, or absent. */
4
+ export type SidecarGitState = 'repo' | 'stray' | 'absent';
5
+ /**
6
+ * Classify the sidecar's `.git` entry. `stray` is a refusal state: a `.git`
7
+ * FILE (e.g. a leftover `gitdir:` link) redirects the repository elsewhere;
8
+ * isomorphic-git follows it, so writes would land outside the sidecar and
9
+ * reads would loop back to the "no sidecar" gate — never treat it as absent.
10
+ * Symlinks are followed like isomorphic-git does: a link to a real directory
11
+ * is a usable repo; a link to a file or a broken link is stray.
12
+ */
13
+ export declare function sidecarGitState(file: string): SidecarGitState;
14
+ /** Is a valid sidecar chain present for this document? */
15
+ export declare function hasHistorySidecar(file: string): boolean;
16
+ /** Tracked package files (everything but document.xml) from a live snapshot. */
17
+ export declare function trackedExtras(snapshot: Map<string, Buffer>): Map<string, Buffer>;
18
+ export declare function extrasRecord(extras: Map<string, Buffer>): Record<string, Buffer>;
19
+ export type BatchRevisionResult = {
20
+ recorded: true;
21
+ commit: string;
22
+ } | {
23
+ recorded: false;
24
+ reason: string;
25
+ } | null;
26
+ /**
27
+ * Records the document just written by a command as a history revision, but only when the document
28
+ * already has a history repository and the command wrote the document itself (not an `--out` copy).
29
+ * Returns null when nothing was due. A failure is reported on stderr and in the result; the command
30
+ * keeps its exit code, because the file was written.
31
+ */
32
+ export declare function recordBatchRevision(args: {
33
+ file: string;
34
+ target: string;
35
+ parser: DocxParser;
36
+ message: string;
37
+ noHistory: boolean;
38
+ }): Promise<BatchRevisionResult>;
@@ -0,0 +1,2 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdImport(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,3 @@
1
+ import { type Fidelity, type GlobalOpts } from './output';
2
+ export declare function parseFidelity(raw: string | undefined): Fidelity | undefined;
3
+ export declare function cmdInspect(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,70 @@
1
+ export declare function readDocx(file: string): Promise<Buffer>;
2
+ /**
3
+ * R-44: read piped stdin fully as UTF-8 (for `batch <docx> -`).
4
+ * Callers check `process.stdin.isTTY` first and reject a terminal with a
5
+ * usage error, so this never blocks on interactive input. A closed pipe
6
+ * with no data (`< /dev/null`) resolves to '' and the caller rejects that
7
+ * as a usage error too — empty check, not a timeout, so a slow-but-live
8
+ * pipe still completes while empty stdin fails fast with exit 2.
9
+ */
10
+ export declare function readStdinText(): Promise<string>;
11
+ export interface ZipCeilingOverrides {
12
+ maxRatio?: number;
13
+ maxUncompressedBytes?: number;
14
+ }
15
+ /** Validate a `--max-ratio <n>` value: positive finite number (cap guards typos). */
16
+ export declare function parseMaxRatioFlag(raw: string | undefined): number;
17
+ /** Validate a `--max-uncompressed-bytes <n>` value: positive integer bytes. */
18
+ export declare function parseMaxUncompressedBytesFlag(raw: string | undefined): number;
19
+ export interface MacroFlagChoice {
20
+ allowMacros: boolean;
21
+ stripMacros: boolean;
22
+ }
23
+ export declare function macroOptsFromFlags(f: MacroFlagChoice): {
24
+ allowMacros: true;
25
+ } | {
26
+ stripMacros: true;
27
+ } | undefined;
28
+ export declare function macroFlagsUsageError(): string;
29
+ /**
30
+ * A package that still holds macro parts has to be saved as .docm or .dotm; Word refuses a .docx that has them.
31
+ * Returns the refusal text when the output name does not fit the parts that stay in the file, else null.
32
+ */
33
+ export declare function macroOutputRefusal(command: string, output: string, macroParts: readonly string[], stripped: boolean): string | null;
34
+ /**
35
+ * `--strip-macros` leaves a plain document, so it cannot be written under a macro-enabled name (.docm, .dotm):
36
+ * Word would refuse the file. Returns the refusal text for such a target, else null.
37
+ */
38
+ export declare function macroStripNameRefusal(command: string, target: string, remedy: string): string | null;
39
+ /**
40
+ * Scope ceiling overrides around a DocxParser load. The engine resolves
41
+ * ceilings from env at check time (pre-read + central-directory gates), so
42
+ * temporarily setting the env is the non-invasive plumb for CLI flags.
43
+ * Restores prior values (including unset) afterwards.
44
+ */
45
+ export declare function withZipCeilingEnv<T>(ceilings: ZipCeilingOverrides, fn: () => T | Promise<T>): Promise<T>;
46
+ /**
47
+ * Reproducible scoping: explicit --no-reproducible sets ASTRA_NO_REPRODUCIBLE=1
48
+ * around engine + save so revision/comment/cover dates see wall-clock;
49
+ * explicit --reproducible clears the opt-out and pins ASTRA_REPRODUCIBLE=1;
50
+ * undefined leaves env untouched (default deterministic unless env opts out).
51
+ */
52
+ export declare function withReproducibleEnv<T>(reproducible: boolean | undefined, fn: () => T | Promise<T>): Promise<T>;
53
+ /**
54
+ * Author scoping: --author <name> sets ASTRA_AUTHOR around the engine run, so the document's
55
+ * default author (used by every tracked change and comment that does not name one) is the
56
+ * caller's. undefined leaves the environment untouched.
57
+ */
58
+ export declare function withAuthorEnv<T>(author: string | undefined, fn: () => T | Promise<T>): Promise<T>;
59
+ export { computeDocStats, tableCellTextSpaced } from '@attentionform/astra-engine';
60
+ export type { DocStats } from '@attentionform/astra-engine';
61
+ export declare function escapeXmlText(text: string): string;
62
+ export declare function buildSnippet(text: string, query: string, radius?: number, maxLen?: number): string;
63
+ /**
64
+ * Reset the document body to a single empty paragraph, keeping styles,
65
+ * numbering, settings and all package props byte-identical. CLI-level only:
66
+ * the engine schema has no clear op, so `batch` expands `{action:'clearDoc'}`
67
+ * through this function before the remaining ops run.
68
+ */
69
+ export declare function clearDocumentBody(buf: Buffer): Buffer;
70
+ export declare function writeDocx(file: string, buf: Buffer): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import { type GlobalOpts } from './output';
2
+ /**
3
+ * Repair-as-action entry for legacy files: runs the engine allowlist
4
+ * normalizer (display-only against the core API — see the surface block at
5
+ * the top of this file), then the strict validation gate, then writes.
6
+ * Chosen over a `validate --fix` alias: `validate` is pinned read-only
7
+ * fail-closed by scripts, so a mutating alias would break its contract.
8
+ */
9
+ export declare function cmdNormalize(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,98 @@
1
+ export declare const CLI_NAME = "astra";
2
+ export declare const CLI_VERSION: string;
3
+ export declare const EXIT_OK = 0;
4
+ export declare const EXIT_FAIL = 1;
5
+ export declare const EXIT_USAGE = 2;
6
+ /** Fallback terminal width when --wrap cannot detect one (piped stdout). */
7
+ export declare const INSPECT_DEFAULT_WRAP_COLUMNS = 80;
8
+ /**
9
+ * Resolve the human-presentation wrap width for inspect: an explicit
10
+ * --width wins; --wrap auto-detects the terminal width (fallback 80 when
11
+ * piped or unknown); neither means no wrapping (machine 1-line-per-node
12
+ * default stays). `columns` is injectable for tests; callers omit it to
13
+ * read process.stdout.columns.
14
+ */
15
+ export declare function resolveInspectWidth(opts: {
16
+ width?: number;
17
+ wrap?: boolean;
18
+ columns?: number | undefined;
19
+ }): number | undefined;
20
+ export type NormalizedRewrite = string;
21
+ /** Display-only read of the core's own normalizer log (defensive: [] when absent). */
22
+ export declare function readParserNormalizations(parser: unknown): NormalizedRewrite[];
23
+ /** Display-only read of an engine result's `normalized` report (defensive: [] when absent). */
24
+ export declare function readEngineNormalized(res: unknown): NormalizedRewrite[];
25
+ /**
26
+ * Display-only would-be rewrites for dry-run: parse + rezip a copy through
27
+ * the core and report its log, discarding the bytes. No repair logic here —
28
+ * the copy is thrown away, nothing is written. Parse failures propagate to
29
+ * the caller so a corrupt input fails closed instead of reporting empty.
30
+ */
31
+ export declare function previewNormalizedForDisplay(buf: Buffer, macroOpts?: {
32
+ allowMacros?: boolean;
33
+ stripMacros?: boolean;
34
+ }): NormalizedRewrite[];
35
+ /** Display-only repair entry: core parse + rezip (the hook heals), or passthrough on failure. */
36
+ export declare function applyNormalizerForDisplay(buf: Buffer, macroOpts?: {
37
+ allowMacros?: boolean;
38
+ stripMacros?: boolean;
39
+ }): {
40
+ buffer: Buffer;
41
+ normalized: NormalizedRewrite[];
42
+ };
43
+ /** Inline `normalized=N [...]` fragment for result lines (bounded to 5 shown). */
44
+ export declare function formatNormalizedInline(list: readonly string[]): string;
45
+ /**
46
+ * Merge core logs across the rezips one save performs (gate rezip + save
47
+ * rezip), dropping exact duplicates. The gate's internal rezip already heals
48
+ * and logs, so reading only the final rezip would report a dishonest zero —
49
+ * capture both, report every rewrite once.
50
+ */
51
+ export declare function mergeNormalized(...lists: string[][]): string[];
52
+ /**
53
+ * T-13: ANSI escape sequence regex — CSI (with `;` and `:` sub-params for
54
+ * colon truecolor `38:2::r:g:b` / `4:3`), OSC hyperlinks/titles (`ESC ] … BEL/ST`),
55
+ * charset designators (`ESC ( B`), and residual single-char ESC sequences.
56
+ * Alternation order matters: OSC first so `ESC ] …` is consumed whole instead
57
+ * of partially matching the CSI branch.
58
+ */
59
+ export declare const ANSI_REGEX: RegExp;
60
+ /**
61
+ * T-13: Strip ANSI escape sequences from text.
62
+ */
63
+ export declare function stripAnsi(text: string): string;
64
+ /**
65
+ * T-13: Check if color stripping is required (!process.stdout.isTTY or
66
+ * NO_COLOR present with a non-empty value, per https://no-color.org:
67
+ * empty-string NO_COLOR must NOT strip).
68
+ */
69
+ export declare function shouldStripColor(stream?: 'stdout' | 'stderr' | {
70
+ isTTY?: boolean;
71
+ }): boolean;
72
+ /**
73
+ * T-13: Format message respecting TTY and NO_COLOR.
74
+ */
75
+ export declare function formatCliOutput(message: string, stream?: 'stdout' | 'stderr' | {
76
+ isTTY?: boolean;
77
+ }): string;
78
+ /**
79
+ * T-13: Serialize a --json payload, stripping ANSI when color is disabled
80
+ * (non-TTY stdout or non-empty NO_COLOR). ANSI inside JSON string values
81
+ * must not leak raw escapes into piped JSON consumers.
82
+ */
83
+ /**
84
+ * Recursively strip ANSI from JSON string values (arrays + plain objects).
85
+ * JSON.stringify escapes raw ESC as `\\u001b` text, so stripping must happen
86
+ * BEFORE serialization — a post-serialization regex would miss the escaped
87
+ * form. Non-plain objects pass through untouched.
88
+ */
89
+ export declare function stripAnsiDeep(value: unknown): unknown;
90
+ export declare function stringifyJsonPayload(payload: unknown, space?: string | number): string;
91
+ export type Fidelity = 'compact' | 'standard' | 'full';
92
+ export interface GlobalOpts {
93
+ json: boolean;
94
+ verbose: boolean;
95
+ }
96
+ export declare function print(out: GlobalOpts, message: string): void;
97
+ export declare function printStderr(message: string): void;
98
+ export declare function printJson(out: GlobalOpts, payload: unknown): void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Testable entrypoint: returns the process exit code instead of exiting.
3
+ * Never throws for expected failures (fail-closed codes); unexpected throws
4
+ * are caught and mapped to EXIT_FAIL.
5
+ */
6
+ export declare function run(argv: string[]): Promise<number>;
@@ -0,0 +1,26 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function isSanitizeBodyPartName(name: string): boolean;
3
+ export declare function isSanitizeCommentFamilyName(name: string): boolean;
4
+ export declare function isSanitizeStyleFamilyName(name: string): boolean;
5
+ export declare function isSanitizeGenericTextName(name: string): boolean;
6
+ /**
7
+ * Count revision/comment markup surviving in a sanitized package (count-only,
8
+ * never echoes values). Revisions cover w:ins/w:del/move + cell markers +
9
+ * range markers + *Change wrappers; comments cover range/reference elements
10
+ * plus comment definitions in comment parts. Used to gate the partial-flag
11
+ * WARNING so a clean file stays quiet.
12
+ */
13
+ export declare function countSanitizeSurvivors(docxBuf: Buffer): {
14
+ revisions: number;
15
+ comments: number;
16
+ };
17
+ /**
18
+ * Structural locations of body PII that sanitize will redact (count-only,
19
+ * never echoes values). One entry per redaction hit (`part#p<idx>` for
20
+ * body/comment parts, `part#text` for generic text carriers). Bounded at
21
+ * 1000 entries. Falls back to part-level markers when paragraph slicing
22
+ * finds nothing but the whole-part count is non-zero, so a non-zero
23
+ * bodyRedactions count never prints with an empty location list.
24
+ */
25
+ export declare function collectBodyPiiLocations(inputBuf: Buffer): string[];
26
+ export declare function cmdSanitize(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,2 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdSearch(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,2 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdStats(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,8 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function printUsage(out: GlobalOpts): number;
3
+ export declare const USAGE_CODE = "E_USAGE";
4
+ export declare const USAGE_REMEDY = "check arguments with `astra --help` (or `astra <command> --help`), then retry";
5
+ export declare function usage(out: GlobalOpts, message?: string): number;
6
+ export declare function commandHelpText(cmd: string): string | undefined;
7
+ export declare function printCommandHelp(out: GlobalOpts, cmd: string): number;
8
+ export declare function hasHelpFlag(args: string[]): boolean;
@@ -0,0 +1,2 @@
1
+ import { type GlobalOpts } from './output';
2
+ export declare function cmdValidate(out: GlobalOpts, args: string[]): Promise<number>;
@@ -0,0 +1,34 @@
1
+ import { renderDocxToImages, type DocumentAST, type VisualImageFormat, type VisualTelemetry } from '@attentionform/astra-engine';
2
+ import { type GlobalOpts } from './output';
3
+ /**
4
+ * Single CLI visual-telemetry builder (two entry points: `visual` below and
5
+ * `inspect --visual` in inspect-cmd.ts — both call this, never the engine
6
+ * directly, so the wireframe/warnings stay identical across surfaces).
7
+ * `renderTotalPages` is the renderer's (LibreOffice) actual page count: the
8
+ * single source of truth for the `[PAGE n OF m]` marker whenever it differs
9
+ * from the word-layout map embedded in the structural summary.
10
+ */
11
+ export declare function buildCliVisualTelemetry(ast: DocumentAST, summary: unknown, page?: number, renderTotalPages?: number): VisualTelemetry;
12
+ /**
13
+ * Single CLI visual-render path (two entry points: `visual --out` below and
14
+ * `inspect --visual` in inspect-cmd.ts — both call this, never
15
+ * `renderDocxToImages` directly, so DPI/quality/page-selection stay
16
+ * identical: same `pages: [page]` + `format` args on every invocation).
17
+ */
18
+ export declare function buildCliVisualRenderArgs(page: number, format: VisualImageFormat): {
19
+ pages: [number];
20
+ format: VisualImageFormat;
21
+ };
22
+ export declare function renderCliVisualPage(buf: Buffer, page: number, format: VisualImageFormat): Promise<Awaited<ReturnType<typeof renderDocxToImages>>>;
23
+ /**
24
+ * Single CLI visual-telemetry printer (both entry points call this, so the
25
+ * wireframe/warnings/tokens lines stay identical across surfaces).
26
+ * Callers pass the EFFECTIVE page (the renderer's clamped pick, not the raw
27
+ * request) so the `[PAGE n OF m]` marker always describes the image shown,
28
+ * and the renderer's actual page count as `renderTotalPages` so `OF m` is
29
+ * the renderer's count — the image came from the renderer, the marker must
30
+ * name it. Divergence from the word-layout page map and any --page beyond
31
+ * that map warn on stderr (never silent; stdout stays JSON-clean).
32
+ */
33
+ export declare function printCliVisualTelemetry(out: GlobalOpts, ast: DocumentAST, summary: unknown, page: number, renderTotalPages?: number): VisualTelemetry;
34
+ export declare function cmdVisual(out: GlobalOpts, args: string[]): Promise<number>;