@paths.design/caws-cli 11.1.6 → 11.1.8
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/README.md +1 -1
- package/dist/index.js +55 -58
- package/dist/init/hook-packs/manifest-claude-code.d.ts +1 -1
- package/dist/init/hook-packs/manifest-claude-code.d.ts.map +1 -1
- package/dist/init/hook-packs/manifest-claude-code.js +317 -6
- package/dist/init/hook-packs/manifest-claude-code.js.map +1 -1
- package/dist/init/hook-packs/types.js +1 -1
- package/dist/init/hook-packs/types.js.map +1 -1
- package/dist/shell/binding/resolve-binding.d.ts.map +1 -1
- package/dist/shell/binding/resolve-binding.js +105 -1
- package/dist/shell/binding/resolve-binding.js.map +1 -1
- package/dist/shell/binding/types.d.ts +47 -3
- package/dist/shell/binding/types.d.ts.map +1 -1
- package/dist/shell/command-metadata.d.ts +93 -0
- package/dist/shell/command-metadata.d.ts.map +1 -0
- package/dist/shell/command-metadata.js +687 -0
- package/dist/shell/command-metadata.js.map +1 -0
- package/dist/shell/commands/agents.d.ts +48 -0
- package/dist/shell/commands/agents.d.ts.map +1 -0
- package/dist/shell/commands/agents.js +577 -0
- package/dist/shell/commands/agents.js.map +1 -0
- package/dist/shell/commands/claim.d.ts +16 -0
- package/dist/shell/commands/claim.d.ts.map +1 -1
- package/dist/shell/commands/claim.js +88 -30
- package/dist/shell/commands/claim.js.map +1 -1
- package/dist/shell/commands/events.d.ts +106 -0
- package/dist/shell/commands/events.d.ts.map +1 -0
- package/dist/shell/commands/events.js +510 -0
- package/dist/shell/commands/events.js.map +1 -0
- package/dist/shell/commands/gates.d.ts +2 -2
- package/dist/shell/commands/gates.d.ts.map +1 -1
- package/dist/shell/commands/gates.js +106 -25
- package/dist/shell/commands/gates.js.map +1 -1
- package/dist/shell/commands/init.d.ts.map +1 -1
- package/dist/shell/commands/init.js +26 -0
- package/dist/shell/commands/init.js.map +1 -1
- package/dist/shell/commands/prepush.d.ts +26 -0
- package/dist/shell/commands/prepush.d.ts.map +1 -0
- package/dist/shell/commands/prepush.js +373 -0
- package/dist/shell/commands/prepush.js.map +1 -0
- package/dist/shell/commands/scope.d.ts.map +1 -1
- package/dist/shell/commands/scope.js +31 -1
- package/dist/shell/commands/scope.js.map +1 -1
- package/dist/shell/commands/specs.d.ts +44 -3
- package/dist/shell/commands/specs.d.ts.map +1 -1
- package/dist/shell/commands/specs.js +411 -15
- package/dist/shell/commands/specs.js.map +1 -1
- package/dist/shell/commands/status.d.ts +12 -0
- package/dist/shell/commands/status.d.ts.map +1 -1
- package/dist/shell/commands/status.js +236 -21
- package/dist/shell/commands/status.js.map +1 -1
- package/dist/shell/commands/worktree.d.ts +9 -0
- package/dist/shell/commands/worktree.d.ts.map +1 -1
- package/dist/shell/commands/worktree.js +353 -1
- package/dist/shell/commands/worktree.js.map +1 -1
- package/dist/shell/gates/disposition.d.ts.map +1 -1
- package/dist/shell/gates/disposition.js +43 -2
- package/dist/shell/gates/disposition.js.map +1 -1
- package/dist/shell/index.d.ts +14 -6
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +32 -1
- package/dist/shell/index.js.map +1 -1
- package/dist/shell/legacy-command-map.js +832 -0
- package/dist/shell/push-range/classify-range.d.ts +99 -0
- package/dist/shell/push-range/classify-range.d.ts.map +1 -0
- package/dist/shell/push-range/classify-range.js +155 -0
- package/dist/shell/push-range/classify-range.js.map +1 -0
- package/dist/shell/push-range/scope-match.d.ts +13 -0
- package/dist/shell/push-range/scope-match.d.ts.map +1 -0
- package/dist/shell/push-range/scope-match.js +53 -0
- package/dist/shell/push-range/scope-match.js.map +1 -0
- package/dist/shell/register.d.ts.map +1 -1
- package/dist/shell/register.js +350 -165
- package/dist/shell/register.js.map +1 -1
- package/dist/shell/registered-command-groups.js +48 -0
- package/dist/shell/render/status.d.ts +7 -1
- package/dist/shell/render/status.d.ts.map +1 -1
- package/dist/shell/render/status.js +72 -0
- package/dist/shell/render/status.js.map +1 -1
- package/dist/shell/rules.d.ts +19 -0
- package/dist/shell/rules.d.ts.map +1 -1
- package/dist/shell/rules.js +27 -0
- package/dist/shell/rules.js.map +1 -1
- package/dist/shell/session/resolve-session.d.ts +29 -1
- package/dist/shell/session/resolve-session.d.ts.map +1 -1
- package/dist/shell/session/resolve-session.js +817 -11
- package/dist/shell/session/resolve-session.js.map +1 -1
- package/dist/shell/session/types.d.ts +127 -1
- package/dist/shell/session/types.d.ts.map +1 -1
- package/dist/shell/session/types.js +10 -4
- package/dist/shell/session/types.js.map +1 -1
- package/dist/store/agents-store.d.ts.map +1 -1
- package/dist/store/agents-store.js +9 -0
- package/dist/store/agents-store.js.map +1 -1
- package/dist/store/apply-patch.d.ts.map +1 -1
- package/dist/store/apply-patch.js +15 -0
- package/dist/store/apply-patch.js.map +1 -1
- package/dist/store/doctor-snapshot.d.ts.map +1 -1
- package/dist/store/doctor-snapshot.js +169 -3
- package/dist/store/doctor-snapshot.js.map +1 -1
- package/dist/store/events-migration.d.ts +207 -0
- package/dist/store/events-migration.d.ts.map +1 -0
- package/dist/store/events-migration.js +358 -0
- package/dist/store/events-migration.js.map +1 -0
- package/dist/store/events-store.d.ts +47 -1
- package/dist/store/events-store.d.ts.map +1 -1
- package/dist/store/events-store.js +278 -0
- package/dist/store/events-store.js.map +1 -1
- package/dist/store/git-autocommit.d.ts +46 -0
- package/dist/store/git-autocommit.d.ts.map +1 -0
- package/dist/store/git-autocommit.js +198 -0
- package/dist/store/git-autocommit.js.map +1 -0
- package/dist/store/git-sparse-checkout.d.ts +25 -0
- package/dist/store/git-sparse-checkout.d.ts.map +1 -0
- package/dist/store/git-sparse-checkout.js +101 -0
- package/dist/store/git-sparse-checkout.js.map +1 -0
- package/dist/store/index.d.ts +6 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +16 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/leases-store.d.ts +89 -0
- package/dist/store/leases-store.d.ts.map +1 -0
- package/dist/store/leases-store.js +427 -0
- package/dist/store/leases-store.js.map +1 -0
- package/dist/store/lifecycle-transaction.d.ts.map +1 -1
- package/dist/store/lifecycle-transaction.js +34 -1
- package/dist/store/lifecycle-transaction.js.map +1 -1
- package/dist/store/rules.d.ts +74 -1
- package/dist/store/rules.d.ts.map +1 -1
- package/dist/store/rules.js +76 -0
- package/dist/store/rules.js.map +1 -1
- package/dist/store/specs-migration.d.ts +128 -0
- package/dist/store/specs-migration.d.ts.map +1 -0
- package/dist/store/specs-migration.js +481 -0
- package/dist/store/specs-migration.js.map +1 -0
- package/dist/store/specs-store.d.ts.map +1 -1
- package/dist/store/specs-store.js +14 -2
- package/dist/store/specs-store.js.map +1 -1
- package/dist/store/specs-writer.d.ts +130 -3
- package/dist/store/specs-writer.d.ts.map +1 -1
- package/dist/store/specs-writer.js +941 -102
- package/dist/store/specs-writer.js.map +1 -1
- package/dist/store/types.d.ts +31 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/waivers-store.d.ts.map +1 -1
- package/dist/store/waivers-store.js +8 -1
- package/dist/store/waivers-store.js.map +1 -1
- package/dist/store/worktrees-migration.d.ts +141 -0
- package/dist/store/worktrees-migration.d.ts.map +1 -0
- package/dist/store/worktrees-migration.js +356 -0
- package/dist/store/worktrees-migration.js.map +1 -0
- package/dist/store/worktrees-writer.d.ts +28 -0
- package/dist/store/worktrees-writer.d.ts.map +1 -1
- package/dist/store/worktrees-writer.js +147 -13
- package/dist/store/worktrees-writer.js.map +1 -1
- package/package.json +5 -2
- package/templates/hook-packs/claude-code/CLAUDE.md +11 -5
- package/templates/hook-packs/claude-code/agent-heartbeat.sh +131 -0
- package/templates/hook-packs/claude-code/agent-register.sh +62 -0
- package/templates/hook-packs/claude-code/agent-stop.sh +51 -0
- package/templates/hook-packs/claude-code/audit.sh +1 -1
- package/templates/hook-packs/claude-code/block-dangerous.sh +1 -1
- package/templates/hook-packs/claude-code/classify_command.py +1 -1
- package/templates/hook-packs/claude-code/cwd-guard.sh +30 -0
- package/templates/hook-packs/claude-code/dispatch/post_tool_use.sh +15 -4
- package/templates/hook-packs/claude-code/dispatch/pre_tool_use.sh +19 -2
- package/templates/hook-packs/claude-code/dispatch/session_start.sh +6 -2
- package/templates/hook-packs/claude-code/dispatch/stop.sh +7 -2
- package/templates/hook-packs/claude-code/duplicate-export-check.sh +156 -0
- package/templates/hook-packs/claude-code/god-object-check.sh +102 -0
- package/templates/hook-packs/claude-code/guard-strikes.sh +1 -1
- package/templates/hook-packs/claude-code/lib/parse-input.sh +115 -1
- package/templates/hook-packs/claude-code/lib/run-handlers.sh +1 -1
- package/templates/hook-packs/claude-code/loc-delta-check.sh +91 -0
- package/templates/hook-packs/claude-code/naming-check.sh +128 -0
- package/templates/hook-packs/claude-code/plan-transcript-finalize.sh +59 -0
- package/templates/hook-packs/claude-code/plan-transcript-snapshot.sh +86 -0
- package/templates/hook-packs/claude-code/protected-paths.sh +59 -0
- package/templates/hook-packs/claude-code/quiet-merge.sh +68 -0
- package/templates/hook-packs/claude-code/reset-danger-latch.sh +1 -1
- package/templates/hook-packs/claude-code/reset-strikes.sh +1 -1
- package/templates/hook-packs/claude-code/runtime-paths.sh +1 -1
- package/templates/hook-packs/claude-code/scan-secrets.sh +98 -0
- package/templates/hook-packs/claude-code/scope-guard.sh +47 -65
- package/templates/hook-packs/claude-code/session-caws-status.sh +7 -1
- package/templates/hook-packs/claude-code/session-log.sh +1 -1
- package/templates/hook-packs/claude-code/session_log_renderer.py +956 -0
- package/templates/hook-packs/claude-code/shortcut-language-check.sh +147 -0
- package/templates/hook-packs/claude-code/worktree-guard.sh +130 -4
- package/templates/hook-packs/claude-code/worktree-write-guard.sh +133 -18
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { type Diagnostic, type Result } from '@paths.design/caws-kernel';
|
|
2
|
+
export declare const MIGRATION_RULES: {
|
|
3
|
+
/** events.jsonl could not be JSON-parsed at all; every line failed. */
|
|
4
|
+
readonly UNPARSEABLE_INPUT: "store.events.migration.unparseable_input";
|
|
5
|
+
/** events.jsonl is empty; there is nothing to migrate or rotate. */
|
|
6
|
+
readonly EMPTY_INPUT: "store.events.migration.empty_input";
|
|
7
|
+
/** A v10-shape spec YAML was detected during half-upgrade scan. */
|
|
8
|
+
readonly V10_SPEC_DETECTED: "store.events.migration.v10_spec_detected";
|
|
9
|
+
/** events.jsonl has SOME unparseable lines alongside parseable ones.
|
|
10
|
+
* The chain_rotated payload's prior_chain_status enum has no honest
|
|
11
|
+
* label for this case (parseable_unverified implies every line
|
|
12
|
+
* parsed; unparseable implies none did), so the planner refuses.
|
|
13
|
+
* Mirrors STORE_RULES.EVENTS_ROTATE_PARTIAL_CORRUPTION in rotateEvents
|
|
14
|
+
* so dry-run and apply paths agree. */
|
|
15
|
+
readonly PARTIAL_CORRUPTION_REFUSED: "store.events.migration.partial_corruption_refused";
|
|
16
|
+
/** The shell could not scan .caws/specs/ for v10-shape YAMLs (directory
|
|
17
|
+
* missing, unreadable, or sparse-checkout-excluded). The half-upgrade
|
|
18
|
+
* refusal CANNOT be enforced without a complete scan, so the migration
|
|
19
|
+
* command refuses by default rather than silently bypass the guard.
|
|
20
|
+
* No friction-flag escape in v11.2 scope. */
|
|
21
|
+
readonly SPEC_SCAN_UNAVAILABLE: "store.events.migration.spec_scan_unavailable";
|
|
22
|
+
/** Bug-class assertion: dry-run reported an archive name X and the
|
|
23
|
+
* apply path (rotateEvents) returned a different archive name Y.
|
|
24
|
+
* This indicates the dry-run's now-clock and the apply's now-clock
|
|
25
|
+
* drifted, or windowsSafeIso diverged between events-migration.ts
|
|
26
|
+
* and events-store.ts. Either way it is a programmer error, not an
|
|
27
|
+
* operator error; the shell surfaces it as an internal failure. */
|
|
28
|
+
readonly INTERNAL_DRYRUN_APPLY_MISMATCH: "store.events.migration.internal_dryrun_apply_mismatch";
|
|
29
|
+
/** events migrate refused because the underlying log is fully
|
|
30
|
+
* unparseable. Migration cannot claim it found a v10 chain. The
|
|
31
|
+
* lower-level `caws events rotate` may still archive a fully
|
|
32
|
+
* unparseable log under the honest 'unparseable' status as evidence
|
|
33
|
+
* quarantine — that semantic is intentional and distinct from
|
|
34
|
+
* migration. */
|
|
35
|
+
readonly MIGRATE_UNPARSEABLE_REFUSED: "store.events.migration.unparseable_refused";
|
|
36
|
+
/** verify-archive: events.jsonl exists but contains no chain_rotated
|
|
37
|
+
* event. There is nothing to verify against. */
|
|
38
|
+
readonly VERIFY_NO_ROTATION_EVENT: "store.events.verify_archive.no_rotation_event";
|
|
39
|
+
/** verify-archive: the archive file named by the most recent
|
|
40
|
+
* chain_rotated event does not exist on disk. */
|
|
41
|
+
readonly VERIFY_ARCHIVE_MISSING: "store.events.verify_archive.archive_missing";
|
|
42
|
+
/** verify-archive: the current events.jsonl could not be loaded
|
|
43
|
+
* (e.g., malformed JSON line, invalid chain). The shell cannot
|
|
44
|
+
* determine the most recent chain_rotated event. */
|
|
45
|
+
readonly VERIFY_CURRENT_CHAIN_INVALID: "store.events.verify_archive.current_chain_invalid";
|
|
46
|
+
};
|
|
47
|
+
export type MigrationRule = (typeof MIGRATION_RULES)[keyof typeof MIGRATION_RULES];
|
|
48
|
+
export interface ActorShapeStats {
|
|
49
|
+
readonly v10_string_actor: number;
|
|
50
|
+
readonly v11_object_actor: number;
|
|
51
|
+
readonly unparseable: number;
|
|
52
|
+
}
|
|
53
|
+
export type EventsLogKind =
|
|
54
|
+
/** Every parseable line has a string actor (v10 envelope). */
|
|
55
|
+
'all_v10'
|
|
56
|
+
/** Every parseable line has a structured actor (v11 envelope). */
|
|
57
|
+
| 'all_v11'
|
|
58
|
+
/** Lines exist with both shapes. */
|
|
59
|
+
| 'mixed_v10_v11'
|
|
60
|
+
/** The file has zero non-empty lines. */
|
|
61
|
+
| 'empty'
|
|
62
|
+
/** No line could be JSON-parsed. */
|
|
63
|
+
| 'unparseable_only';
|
|
64
|
+
export interface EventsLogShape {
|
|
65
|
+
readonly kind: EventsLogKind;
|
|
66
|
+
readonly stats: ActorShapeStats;
|
|
67
|
+
/** Total non-empty lines (parseable + unparseable). */
|
|
68
|
+
readonly lineCount: number;
|
|
69
|
+
/** Tail event_hash if the last non-empty line parsed and carried one. */
|
|
70
|
+
readonly tailHash: string | null;
|
|
71
|
+
/** Tail seq if the last non-empty line parsed and carried a valid integer. */
|
|
72
|
+
readonly tailSeq: number | null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Classify the actor-shape of every non-empty line in a raw events.jsonl
|
|
76
|
+
* payload. Pure: takes the file contents as a string, returns the
|
|
77
|
+
* detection result. No filesystem access.
|
|
78
|
+
*
|
|
79
|
+
* Errors:
|
|
80
|
+
* - returns Err for an empty input. The shell treats this as "nothing
|
|
81
|
+
* to do" rather than a hard error — the same condition rotateEvents
|
|
82
|
+
* refuses on, so the migration command can short-circuit before
|
|
83
|
+
* calling into the store.
|
|
84
|
+
*
|
|
85
|
+
* The detector deliberately does NOT call validateChainedEvent: the
|
|
86
|
+
* whole point of this slice is to handle v10-shape lines that the
|
|
87
|
+
* strict validator rejects. JSON.parse + direct actor-shape inspection
|
|
88
|
+
* is the entire contract.
|
|
89
|
+
*/
|
|
90
|
+
export declare function detectEventsLogShape(raw: string): Result<EventsLogShape>;
|
|
91
|
+
export interface SpecYamlInput {
|
|
92
|
+
/** Relative or absolute path; used in the report to point at the file. */
|
|
93
|
+
readonly path: string;
|
|
94
|
+
/** Raw YAML contents. */
|
|
95
|
+
readonly raw: string;
|
|
96
|
+
}
|
|
97
|
+
export interface V10SpecsScanResult {
|
|
98
|
+
/** True iff at least one input file looks v10-shape. */
|
|
99
|
+
readonly detected: boolean;
|
|
100
|
+
/** Files classified as v10-shape, by path. */
|
|
101
|
+
readonly v10Paths: readonly string[];
|
|
102
|
+
/** Files classified as v11-shape, by path. */
|
|
103
|
+
readonly v11Paths: readonly string[];
|
|
104
|
+
/** Files that could not be classified (parse error or no signal). */
|
|
105
|
+
readonly unclassifiedPaths: readonly string[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Minimal v10-vs-v11 spec YAML scanner. Used by the events migrate
|
|
109
|
+
* command to enforce the half-upgrade refusal (A10): if v10-shape spec
|
|
110
|
+
* YAMLs exist alongside v10 events, the operator must either run the
|
|
111
|
+
* specs migration first or explicitly pass --allow-partial-upgrade.
|
|
112
|
+
*
|
|
113
|
+
* Classification heuristic (per the spec's A10 invariant — "the check
|
|
114
|
+
* is mechanical: scan .caws/specs/*.yaml for v10 top-level keys (type,
|
|
115
|
+
* status, acceptance_criteria) and refuse if any are found"):
|
|
116
|
+
*
|
|
117
|
+
* - v10: file contains any of the top-level keys `type:`, `status:`,
|
|
118
|
+
* or `acceptance_criteria:` at column 0.
|
|
119
|
+
* - v11: file contains any of the top-level keys `mode:`,
|
|
120
|
+
* `lifecycle_state:`, or `acceptance:` at column 0, AND none of
|
|
121
|
+
* the v10 keys.
|
|
122
|
+
* - unclassified: no signal in either direction (e.g., empty file,
|
|
123
|
+
* comment-only file, malformed YAML).
|
|
124
|
+
*
|
|
125
|
+
* This is a regex-level scan, not a full YAML parse. Deliverable 2
|
|
126
|
+
* (CAWS-MIGRATE-V10-SPECS-001) may replace it with detectSpecVersion
|
|
127
|
+
* from packages/caws-kernel/src/spec/migrate-v10.ts when that ships,
|
|
128
|
+
* but the refusal contract owned by this slice (A10) is named here.
|
|
129
|
+
*/
|
|
130
|
+
export declare function detectV10SpecsPresent(files: readonly SpecYamlInput[]): V10SpecsScanResult;
|
|
131
|
+
export interface PlanOptions {
|
|
132
|
+
/** Operator-supplied reason. Mirrors rotateEvents's reason field. */
|
|
133
|
+
readonly reason: string;
|
|
134
|
+
/** Pass-through to the rotateEvents allowClean friction flag. */
|
|
135
|
+
readonly allowClean?: boolean;
|
|
136
|
+
/** When true, ignores v10-spec presence and admits rotation anyway. */
|
|
137
|
+
readonly allowPartialUpgrade?: boolean;
|
|
138
|
+
/** Required for archive-name proposal. The shell injects new Date(). */
|
|
139
|
+
readonly now: Date;
|
|
140
|
+
/**
|
|
141
|
+
* Optional v10-spec scan result. When omitted, the planner does NOT
|
|
142
|
+
* fire the half-upgrade refusal — that requires the caller (the shell)
|
|
143
|
+
* to have scanned the specs directory. When present and detected:true
|
|
144
|
+
* AND allowPartialUpgrade !== true, the plan is a refusal.
|
|
145
|
+
*/
|
|
146
|
+
readonly v10Specs?: V10SpecsScanResult;
|
|
147
|
+
}
|
|
148
|
+
/** Why a plan refused, when kind === 'refuse'. */
|
|
149
|
+
export type PlanRefusalCause = 'empty' | 'unparseable_only' | 'partial_corruption' | 'clean_chain_requires_allow_clean' | 'v10_specs_require_allow_partial_upgrade';
|
|
150
|
+
/** Plan to rotate. The shell may invoke rotateEvents with these inputs. */
|
|
151
|
+
export interface RotatePlan {
|
|
152
|
+
readonly kind: 'rotate';
|
|
153
|
+
/** Pass-through to rotateEvents. */
|
|
154
|
+
readonly reason: string;
|
|
155
|
+
/** Pass-through to rotateEvents. */
|
|
156
|
+
readonly allowClean: boolean;
|
|
157
|
+
/** Pass-through to rotateEvents. */
|
|
158
|
+
readonly now: Date;
|
|
159
|
+
/** What the proposed archive will be named. Informational; rotateEvents
|
|
160
|
+
* computes the same name from its own `now` parameter. */
|
|
161
|
+
readonly proposedArchiveName: string;
|
|
162
|
+
/** The detected shape that justified the plan; included so dry-run can
|
|
163
|
+
* render the full classification next to the rotation summary. */
|
|
164
|
+
readonly detection: EventsLogShape;
|
|
165
|
+
/** v10-spec scan result if the caller provided one; informational. */
|
|
166
|
+
readonly v10Specs?: V10SpecsScanResult;
|
|
167
|
+
}
|
|
168
|
+
/** Plan to refuse, with a structured cause and the diagnostic the
|
|
169
|
+
* shell should emit. */
|
|
170
|
+
export interface RefusePlan {
|
|
171
|
+
readonly kind: 'refuse';
|
|
172
|
+
readonly cause: PlanRefusalCause;
|
|
173
|
+
readonly diagnostic: Diagnostic;
|
|
174
|
+
/** Detection result that informed the refusal, when applicable. */
|
|
175
|
+
readonly detection?: EventsLogShape;
|
|
176
|
+
/** v10-spec scan result, when the refusal was triggered by it. */
|
|
177
|
+
readonly v10Specs?: V10SpecsScanResult;
|
|
178
|
+
}
|
|
179
|
+
export type RotationPlan = RotatePlan | RefusePlan;
|
|
180
|
+
/**
|
|
181
|
+
* Compose a deterministic rotation plan from a previously-detected
|
|
182
|
+
* events-log shape plus operator policy. Pure: no I/O, no clock access
|
|
183
|
+
* (the caller supplies opts.now).
|
|
184
|
+
*
|
|
185
|
+
* The planner is structurally consistent with rotateEvents's refusal
|
|
186
|
+
* logic in events-store.ts — same conditions, same diagnostic rules
|
|
187
|
+
* (sourced from STORE_RULES not from MIGRATION_RULES, so a `rotate
|
|
188
|
+
* --apply` later that goes through rotateEvents will emit the same
|
|
189
|
+
* rule ids). The migration command can therefore present a dry-run
|
|
190
|
+
* plan that exactly mirrors what would happen at apply time.
|
|
191
|
+
*
|
|
192
|
+
* Order of refusal checks (highest precedence first):
|
|
193
|
+
* 1. unparseable_only — nothing to rotate; the log is corrupt
|
|
194
|
+
* and the operator must inspect before any archiving.
|
|
195
|
+
* 2. partial_corruption — some unparseable lines alongside
|
|
196
|
+
* parseable ones; chain_rotated payload cannot honestly label
|
|
197
|
+
* this case. Mirrors STORE_RULES.EVENTS_ROTATE_PARTIAL_CORRUPTION
|
|
198
|
+
* in rotateEvents. No friction-flag escape in v11.2 scope.
|
|
199
|
+
* 3. v10_specs_present — half-upgrade refusal; requires
|
|
200
|
+
* allowPartialUpgrade.
|
|
201
|
+
* 4. clean_chain (all_v11) — friction flag; requires allowClean.
|
|
202
|
+
*
|
|
203
|
+
* If all checks pass, returns RotatePlan with the proposed archive
|
|
204
|
+
* name and the inputs the shell will pass to rotateEvents.
|
|
205
|
+
*/
|
|
206
|
+
export declare function planEventsRotation(detection: EventsLogShape, opts: PlanOptions): RotationPlan;
|
|
207
|
+
//# sourceMappingURL=events-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-migration.d.ts","sourceRoot":"","sources":["../../src/store/events-migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Pure migration module for v10→v11 events.jsonl rotation
|
|
3
|
+
// (CAWS-MIGRATE-V10-EVENTS-001 A9).
|
|
4
|
+
//
|
|
5
|
+
// This module contains zero filesystem I/O and zero shell parsing. It
|
|
6
|
+
// classifies a raw events.jsonl payload, gathers actor-shape stats and
|
|
7
|
+
// tail metadata, and produces a deterministic rotation plan. The shell
|
|
8
|
+
// reads files, calls into this module, prints the plan, and (on --apply)
|
|
9
|
+
// invokes rotateEvents in events-store.ts. The shell is the only layer
|
|
10
|
+
// that touches `.caws/`.
|
|
11
|
+
//
|
|
12
|
+
// This mirrors the worktrees-migration.ts precedent: pure detector +
|
|
13
|
+
// pure planner + shell-does-IO. Refer to worktrees-migration.ts for the
|
|
14
|
+
// canonical pattern.
|
|
15
|
+
//
|
|
16
|
+
// Note on validation: detectEventsLogShape NEVER calls validateChainedEvent.
|
|
17
|
+
// Calling the strict validator on a v10 line is the exact failure mode
|
|
18
|
+
// this slice exists to repair (the v11 envelope shape rejects every line
|
|
19
|
+
// where actor is a string). The detector parses each line with JSON.parse
|
|
20
|
+
// defensively and classifies actor shape by direct type inspection. See
|
|
21
|
+
// docs/architecture/caws-vnext-command-surface.md invariant 14 and the
|
|
22
|
+
// rotateEvents tolerant-scan helper in events-store.ts.
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.MIGRATION_RULES = void 0;
|
|
25
|
+
exports.detectEventsLogShape = detectEventsLogShape;
|
|
26
|
+
exports.detectV10SpecsPresent = detectV10SpecsPresent;
|
|
27
|
+
exports.planEventsRotation = planEventsRotation;
|
|
28
|
+
const caws_kernel_1 = require("@paths.design/caws-kernel");
|
|
29
|
+
const caws_kernel_2 = require("@paths.design/caws-kernel");
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Migration-local rule constants
|
|
32
|
+
//
|
|
33
|
+
// These rules are local to the migration surface and named with the
|
|
34
|
+
// `store.events.migration.*` prefix. They are emitted only by this
|
|
35
|
+
// module and by the shell command that invokes it (A10).
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
exports.MIGRATION_RULES = {
|
|
38
|
+
/** events.jsonl could not be JSON-parsed at all; every line failed. */
|
|
39
|
+
UNPARSEABLE_INPUT: 'store.events.migration.unparseable_input',
|
|
40
|
+
/** events.jsonl is empty; there is nothing to migrate or rotate. */
|
|
41
|
+
EMPTY_INPUT: 'store.events.migration.empty_input',
|
|
42
|
+
/** A v10-shape spec YAML was detected during half-upgrade scan. */
|
|
43
|
+
V10_SPEC_DETECTED: 'store.events.migration.v10_spec_detected',
|
|
44
|
+
/** events.jsonl has SOME unparseable lines alongside parseable ones.
|
|
45
|
+
* The chain_rotated payload's prior_chain_status enum has no honest
|
|
46
|
+
* label for this case (parseable_unverified implies every line
|
|
47
|
+
* parsed; unparseable implies none did), so the planner refuses.
|
|
48
|
+
* Mirrors STORE_RULES.EVENTS_ROTATE_PARTIAL_CORRUPTION in rotateEvents
|
|
49
|
+
* so dry-run and apply paths agree. */
|
|
50
|
+
PARTIAL_CORRUPTION_REFUSED: 'store.events.migration.partial_corruption_refused',
|
|
51
|
+
/** The shell could not scan .caws/specs/ for v10-shape YAMLs (directory
|
|
52
|
+
* missing, unreadable, or sparse-checkout-excluded). The half-upgrade
|
|
53
|
+
* refusal CANNOT be enforced without a complete scan, so the migration
|
|
54
|
+
* command refuses by default rather than silently bypass the guard.
|
|
55
|
+
* No friction-flag escape in v11.2 scope. */
|
|
56
|
+
SPEC_SCAN_UNAVAILABLE: 'store.events.migration.spec_scan_unavailable',
|
|
57
|
+
/** Bug-class assertion: dry-run reported an archive name X and the
|
|
58
|
+
* apply path (rotateEvents) returned a different archive name Y.
|
|
59
|
+
* This indicates the dry-run's now-clock and the apply's now-clock
|
|
60
|
+
* drifted, or windowsSafeIso diverged between events-migration.ts
|
|
61
|
+
* and events-store.ts. Either way it is a programmer error, not an
|
|
62
|
+
* operator error; the shell surfaces it as an internal failure. */
|
|
63
|
+
INTERNAL_DRYRUN_APPLY_MISMATCH: 'store.events.migration.internal_dryrun_apply_mismatch',
|
|
64
|
+
/** events migrate refused because the underlying log is fully
|
|
65
|
+
* unparseable. Migration cannot claim it found a v10 chain. The
|
|
66
|
+
* lower-level `caws events rotate` may still archive a fully
|
|
67
|
+
* unparseable log under the honest 'unparseable' status as evidence
|
|
68
|
+
* quarantine — that semantic is intentional and distinct from
|
|
69
|
+
* migration. */
|
|
70
|
+
MIGRATE_UNPARSEABLE_REFUSED: 'store.events.migration.unparseable_refused',
|
|
71
|
+
/** verify-archive: events.jsonl exists but contains no chain_rotated
|
|
72
|
+
* event. There is nothing to verify against. */
|
|
73
|
+
VERIFY_NO_ROTATION_EVENT: 'store.events.verify_archive.no_rotation_event',
|
|
74
|
+
/** verify-archive: the archive file named by the most recent
|
|
75
|
+
* chain_rotated event does not exist on disk. */
|
|
76
|
+
VERIFY_ARCHIVE_MISSING: 'store.events.verify_archive.archive_missing',
|
|
77
|
+
/** verify-archive: the current events.jsonl could not be loaded
|
|
78
|
+
* (e.g., malformed JSON line, invalid chain). The shell cannot
|
|
79
|
+
* determine the most recent chain_rotated event. */
|
|
80
|
+
VERIFY_CURRENT_CHAIN_INVALID: 'store.events.verify_archive.current_chain_invalid',
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Classify the actor-shape of every non-empty line in a raw events.jsonl
|
|
84
|
+
* payload. Pure: takes the file contents as a string, returns the
|
|
85
|
+
* detection result. No filesystem access.
|
|
86
|
+
*
|
|
87
|
+
* Errors:
|
|
88
|
+
* - returns Err for an empty input. The shell treats this as "nothing
|
|
89
|
+
* to do" rather than a hard error — the same condition rotateEvents
|
|
90
|
+
* refuses on, so the migration command can short-circuit before
|
|
91
|
+
* calling into the store.
|
|
92
|
+
*
|
|
93
|
+
* The detector deliberately does NOT call validateChainedEvent: the
|
|
94
|
+
* whole point of this slice is to handle v10-shape lines that the
|
|
95
|
+
* strict validator rejects. JSON.parse + direct actor-shape inspection
|
|
96
|
+
* is the entire contract.
|
|
97
|
+
*/
|
|
98
|
+
function detectEventsLogShape(raw) {
|
|
99
|
+
const trailingNewline = raw.endsWith('\n');
|
|
100
|
+
const parts = raw.split('\n');
|
|
101
|
+
const lines = trailingNewline ? parts.slice(0, -1) : parts;
|
|
102
|
+
const nonEmpty = lines.filter((l) => l.length > 0);
|
|
103
|
+
if (nonEmpty.length === 0) {
|
|
104
|
+
return (0, caws_kernel_2.err)((0, caws_kernel_1.diagnostic)({
|
|
105
|
+
rule: exports.MIGRATION_RULES.EMPTY_INPUT,
|
|
106
|
+
authority: 'kernel/diagnostics',
|
|
107
|
+
message: 'events.jsonl is empty; nothing to migrate. rotateEvents refuses on the same condition (EVENTS_ROTATE_NOTHING_TO_ROTATE).',
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
let v10 = 0;
|
|
111
|
+
let v11 = 0;
|
|
112
|
+
let bad = 0;
|
|
113
|
+
let tailHash = null;
|
|
114
|
+
let tailSeq = null;
|
|
115
|
+
for (let i = 0; i < nonEmpty.length; i++) {
|
|
116
|
+
const line = nonEmpty[i];
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(line);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
bad += 1;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
126
|
+
bad += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const obj = parsed;
|
|
130
|
+
const actor = obj['actor'];
|
|
131
|
+
if (typeof actor === 'string') {
|
|
132
|
+
v10 += 1;
|
|
133
|
+
}
|
|
134
|
+
else if (actor !== null &&
|
|
135
|
+
typeof actor === 'object' &&
|
|
136
|
+
!Array.isArray(actor) &&
|
|
137
|
+
typeof actor['kind'] === 'string') {
|
|
138
|
+
v11 += 1;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
bad += 1;
|
|
142
|
+
}
|
|
143
|
+
if (i === nonEmpty.length - 1) {
|
|
144
|
+
const eh = obj['event_hash'];
|
|
145
|
+
if (typeof eh === 'string' && /^sha256:[0-9a-f]{64}$/.test(eh)) {
|
|
146
|
+
tailHash = eh;
|
|
147
|
+
}
|
|
148
|
+
const sq = obj['seq'];
|
|
149
|
+
if (typeof sq === 'number' && Number.isInteger(sq) && sq >= 1) {
|
|
150
|
+
tailSeq = sq;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const kind = classifyKind(v10, v11, bad);
|
|
155
|
+
return (0, caws_kernel_2.ok)({
|
|
156
|
+
kind,
|
|
157
|
+
stats: { v10_string_actor: v10, v11_object_actor: v11, unparseable: bad },
|
|
158
|
+
lineCount: nonEmpty.length,
|
|
159
|
+
tailHash,
|
|
160
|
+
tailSeq,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function classifyKind(v10, v11, bad) {
|
|
164
|
+
const totalParseable = v10 + v11;
|
|
165
|
+
if (totalParseable === 0 && bad > 0)
|
|
166
|
+
return 'unparseable_only';
|
|
167
|
+
if (v10 > 0 && v11 > 0)
|
|
168
|
+
return 'mixed_v10_v11';
|
|
169
|
+
if (v10 > 0)
|
|
170
|
+
return 'all_v10';
|
|
171
|
+
// v11 > 0 with no v10. We allow unparseable to coexist (rare crash
|
|
172
|
+
// recovery line) and still report 'all_v11' — the planner's clean-chain
|
|
173
|
+
// check explicitly excludes unparseable > 0 from triggering the friction
|
|
174
|
+
// flag, mirroring rotateEvents's isCleanV11 condition in events-store.ts.
|
|
175
|
+
if (v11 > 0)
|
|
176
|
+
return 'all_v11';
|
|
177
|
+
// No parseable lines and no unparseable lines reaches here only if the
|
|
178
|
+
// input was empty, which the caller handled before classifyKind ran.
|
|
179
|
+
return 'unparseable_only';
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Minimal v10-vs-v11 spec YAML scanner. Used by the events migrate
|
|
183
|
+
* command to enforce the half-upgrade refusal (A10): if v10-shape spec
|
|
184
|
+
* YAMLs exist alongside v10 events, the operator must either run the
|
|
185
|
+
* specs migration first or explicitly pass --allow-partial-upgrade.
|
|
186
|
+
*
|
|
187
|
+
* Classification heuristic (per the spec's A10 invariant — "the check
|
|
188
|
+
* is mechanical: scan .caws/specs/*.yaml for v10 top-level keys (type,
|
|
189
|
+
* status, acceptance_criteria) and refuse if any are found"):
|
|
190
|
+
*
|
|
191
|
+
* - v10: file contains any of the top-level keys `type:`, `status:`,
|
|
192
|
+
* or `acceptance_criteria:` at column 0.
|
|
193
|
+
* - v11: file contains any of the top-level keys `mode:`,
|
|
194
|
+
* `lifecycle_state:`, or `acceptance:` at column 0, AND none of
|
|
195
|
+
* the v10 keys.
|
|
196
|
+
* - unclassified: no signal in either direction (e.g., empty file,
|
|
197
|
+
* comment-only file, malformed YAML).
|
|
198
|
+
*
|
|
199
|
+
* This is a regex-level scan, not a full YAML parse. Deliverable 2
|
|
200
|
+
* (CAWS-MIGRATE-V10-SPECS-001) may replace it with detectSpecVersion
|
|
201
|
+
* from packages/caws-kernel/src/spec/migrate-v10.ts when that ships,
|
|
202
|
+
* but the refusal contract owned by this slice (A10) is named here.
|
|
203
|
+
*/
|
|
204
|
+
function detectV10SpecsPresent(files) {
|
|
205
|
+
const v10Paths = [];
|
|
206
|
+
const v11Paths = [];
|
|
207
|
+
const unclassifiedPaths = [];
|
|
208
|
+
const V10_KEY = /^(?:type|status|acceptance_criteria):/m;
|
|
209
|
+
const V11_KEY = /^(?:mode|lifecycle_state|acceptance):/m;
|
|
210
|
+
for (const file of files) {
|
|
211
|
+
const hasV10 = V10_KEY.test(file.raw);
|
|
212
|
+
const hasV11 = V11_KEY.test(file.raw);
|
|
213
|
+
if (hasV10) {
|
|
214
|
+
// Any v10 signal wins, even if v11 keys also appear (mixed-shape
|
|
215
|
+
// spec is itself a problem the specs migration owns).
|
|
216
|
+
v10Paths.push(file.path);
|
|
217
|
+
}
|
|
218
|
+
else if (hasV11) {
|
|
219
|
+
v11Paths.push(file.path);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
unclassifiedPaths.push(file.path);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
detected: v10Paths.length > 0,
|
|
227
|
+
v10Paths,
|
|
228
|
+
v11Paths,
|
|
229
|
+
unclassifiedPaths,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const ARCHIVE_PREFIX = 'events.jsonl.archive-';
|
|
233
|
+
/**
|
|
234
|
+
* Compose a deterministic rotation plan from a previously-detected
|
|
235
|
+
* events-log shape plus operator policy. Pure: no I/O, no clock access
|
|
236
|
+
* (the caller supplies opts.now).
|
|
237
|
+
*
|
|
238
|
+
* The planner is structurally consistent with rotateEvents's refusal
|
|
239
|
+
* logic in events-store.ts — same conditions, same diagnostic rules
|
|
240
|
+
* (sourced from STORE_RULES not from MIGRATION_RULES, so a `rotate
|
|
241
|
+
* --apply` later that goes through rotateEvents will emit the same
|
|
242
|
+
* rule ids). The migration command can therefore present a dry-run
|
|
243
|
+
* plan that exactly mirrors what would happen at apply time.
|
|
244
|
+
*
|
|
245
|
+
* Order of refusal checks (highest precedence first):
|
|
246
|
+
* 1. unparseable_only — nothing to rotate; the log is corrupt
|
|
247
|
+
* and the operator must inspect before any archiving.
|
|
248
|
+
* 2. partial_corruption — some unparseable lines alongside
|
|
249
|
+
* parseable ones; chain_rotated payload cannot honestly label
|
|
250
|
+
* this case. Mirrors STORE_RULES.EVENTS_ROTATE_PARTIAL_CORRUPTION
|
|
251
|
+
* in rotateEvents. No friction-flag escape in v11.2 scope.
|
|
252
|
+
* 3. v10_specs_present — half-upgrade refusal; requires
|
|
253
|
+
* allowPartialUpgrade.
|
|
254
|
+
* 4. clean_chain (all_v11) — friction flag; requires allowClean.
|
|
255
|
+
*
|
|
256
|
+
* If all checks pass, returns RotatePlan with the proposed archive
|
|
257
|
+
* name and the inputs the shell will pass to rotateEvents.
|
|
258
|
+
*/
|
|
259
|
+
function planEventsRotation(detection, opts) {
|
|
260
|
+
// 1. unparseable_only — refuse outright; rotation here would archive
|
|
261
|
+
// a corrupt chain without operator inspection. The shell points
|
|
262
|
+
// at the file and asks the operator what to do.
|
|
263
|
+
if (detection.kind === 'unparseable_only') {
|
|
264
|
+
return {
|
|
265
|
+
kind: 'refuse',
|
|
266
|
+
cause: 'unparseable_only',
|
|
267
|
+
diagnostic: (0, caws_kernel_1.diagnostic)({
|
|
268
|
+
rule: exports.MIGRATION_RULES.UNPARSEABLE_INPUT,
|
|
269
|
+
authority: 'kernel/diagnostics',
|
|
270
|
+
message: `events.jsonl has no JSON-parseable lines (${detection.stats.unparseable} unparseable, ${detection.lineCount} total). Inspect the file before rotation; manual recovery may be required.`,
|
|
271
|
+
}),
|
|
272
|
+
detection,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// 2. partial_corruption — some unparseable lines exist alongside
|
|
276
|
+
// parseable ones. The chain_rotated payload's prior_chain_status
|
|
277
|
+
// enum has no honest label for this case ('parseable_unverified'
|
|
278
|
+
// implies every line parsed; 'unparseable' implies none did).
|
|
279
|
+
// Refuse rather than archive a partially-corrupt log under a
|
|
280
|
+
// misleading status. Mirrors rotateEvents's same-named refusal
|
|
281
|
+
// so dry-run and apply paths agree exactly. No friction-flag
|
|
282
|
+
// escape in v11.2 scope; a future opt-in path may be added
|
|
283
|
+
// alongside a new 'partially_unparseable' enum value in a
|
|
284
|
+
// later slice.
|
|
285
|
+
if (detection.stats.unparseable > 0 &&
|
|
286
|
+
detection.stats.unparseable < detection.lineCount) {
|
|
287
|
+
const parseable = detection.stats.v10_string_actor + detection.stats.v11_object_actor;
|
|
288
|
+
return {
|
|
289
|
+
kind: 'refuse',
|
|
290
|
+
cause: 'partial_corruption',
|
|
291
|
+
diagnostic: (0, caws_kernel_1.diagnostic)({
|
|
292
|
+
rule: exports.MIGRATION_RULES.PARTIAL_CORRUPTION_REFUSED,
|
|
293
|
+
authority: 'kernel/diagnostics',
|
|
294
|
+
message: `events.jsonl has ${detection.stats.unparseable} unparseable line(s) alongside ${parseable} parseable line(s) (${detection.lineCount} total). Mixed parseable + unparseable cannot be honestly labeled by the chain_rotated payload. Inspect the file and recover manually, or remove the corrupt lines before retrying.`,
|
|
295
|
+
narrowRepair: 'Open events.jsonl, identify the unparseable line(s) (often a truncated/crash-recovery tail), and either restore them or remove them. Re-run after the file has only parseable JSON lines.',
|
|
296
|
+
}),
|
|
297
|
+
detection,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
// 3. Half-upgrade refusal. The planner only fires this when the
|
|
301
|
+
// caller has supplied a v10Specs scan AND detected: true. The
|
|
302
|
+
// contract is "if you scanned and found v10 specs, the planner
|
|
303
|
+
// enforces; if you didn't scan, the planner trusts you."
|
|
304
|
+
if (opts.v10Specs?.detected === true &&
|
|
305
|
+
opts.allowPartialUpgrade !== true) {
|
|
306
|
+
return {
|
|
307
|
+
kind: 'refuse',
|
|
308
|
+
cause: 'v10_specs_require_allow_partial_upgrade',
|
|
309
|
+
diagnostic: (0, caws_kernel_1.diagnostic)({
|
|
310
|
+
rule: exports.MIGRATION_RULES.V10_SPEC_DETECTED,
|
|
311
|
+
authority: 'kernel/diagnostics',
|
|
312
|
+
message: `events migrate --apply refuses: ${opts.v10Specs.v10Paths.length} v10-shape spec(s) detected (${opts.v10Specs.v10Paths.join(', ')}). Run 'caws specs migrate --from v10 --dry-run' first or pass --allow-partial-upgrade.`,
|
|
313
|
+
narrowRepair: "Run 'caws specs migrate --from v10' to migrate specs first, then re-run 'caws events migrate --apply'. If you intentionally want the events log to migrate ahead of specs, pass --allow-partial-upgrade.",
|
|
314
|
+
}),
|
|
315
|
+
detection,
|
|
316
|
+
v10Specs: opts.v10Specs,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// 4. Clean v11 chain friction flag. Mirrors rotateEvents's isCleanV11
|
|
320
|
+
// check in events-store.ts so dry-run and apply agree.
|
|
321
|
+
const isCleanV11 = detection.kind === 'all_v11' &&
|
|
322
|
+
detection.stats.v10_string_actor === 0 &&
|
|
323
|
+
detection.stats.unparseable === 0 &&
|
|
324
|
+
detection.stats.v11_object_actor > 0;
|
|
325
|
+
if (isCleanV11 && opts.allowClean !== true) {
|
|
326
|
+
return {
|
|
327
|
+
kind: 'refuse',
|
|
328
|
+
cause: 'clean_chain_requires_allow_clean',
|
|
329
|
+
diagnostic: (0, caws_kernel_1.diagnostic)({
|
|
330
|
+
rule: 'store.events.rotate.clean_chain_requires_allow_clean',
|
|
331
|
+
authority: 'kernel/diagnostics',
|
|
332
|
+
message: `rotateEvents would refuse: prior chain is a clean v11 chain (${detection.stats.v11_object_actor} structured actors); pass allowClean: true (CLI: --allow-clean) to rotate it anyway.`,
|
|
333
|
+
narrowRepair: 'If you intend to rotate a healthy v11 chain (e.g., for operational reasons unrelated to migration), pass --allow-clean. Otherwise, no rotation is needed.',
|
|
334
|
+
}),
|
|
335
|
+
detection,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
// All checks passed. Compose the rotate plan.
|
|
339
|
+
return {
|
|
340
|
+
kind: 'rotate',
|
|
341
|
+
reason: opts.reason,
|
|
342
|
+
allowClean: opts.allowClean === true,
|
|
343
|
+
now: opts.now,
|
|
344
|
+
proposedArchiveName: `${ARCHIVE_PREFIX}${windowsSafeIso(opts.now)}`,
|
|
345
|
+
detection,
|
|
346
|
+
...(opts.v10Specs !== undefined ? { v10Specs: opts.v10Specs } : {}),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Windows-safe ISO timestamp for archive filenames. Replaces both ':'
|
|
351
|
+
* and '.' with '-' so the archive name is filesystem-safe everywhere.
|
|
352
|
+
* Must match events-store.ts windowsSafeIso exactly so the planner's
|
|
353
|
+
* proposedArchiveName matches what rotateEvents will actually use.
|
|
354
|
+
*/
|
|
355
|
+
function windowsSafeIso(d) {
|
|
356
|
+
return d.toISOString().replace(/:/g, '-').replace(/\./g, '-');
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=events-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-migration.js","sourceRoot":"","sources":["../../src/store/events-migration.ts"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,oCAAoC;AACpC,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,yBAAyB;AACzB,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,qBAAqB;AACrB,EAAE;AACF,6EAA6E;AAC7E,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,wEAAwE;AACxE,uEAAuE;AACvE,wDAAwD;;;AAmHxD,oDAwEC;AA8DD,sDA8BC;AA6FD,gDAyGC;AA3dD,2DAAuD;AACvD,2DAAkF;AAElF,8EAA8E;AAC9E,iCAAiC;AACjC,EAAE;AACF,oEAAoE;AACpE,mEAAmE;AACnE,yDAAyD;AACzD,8EAA8E;AAEjE,QAAA,eAAe,GAAG;IAC7B,uEAAuE;IACvE,iBAAiB,EAAE,0CAA0C;IAC7D,oEAAoE;IACpE,WAAW,EAAE,oCAAoC;IACjD,mEAAmE;IACnE,iBAAiB,EAAE,0CAA0C;IAC7D;;;;;4CAKwC;IACxC,0BAA0B,EACxB,mDAAmD;IACrD;;;;kDAI8C;IAC9C,qBAAqB,EAAE,8CAA8C;IACrE;;;;;wEAKoE;IACpE,8BAA8B,EAC5B,uDAAuD;IACzD;;;;;qBAKiB;IACjB,2BAA2B,EACzB,4CAA4C;IAC9C;qDACiD;IACjD,wBAAwB,EACtB,+CAA+C;IACjD;sDACkD;IAClD,sBAAsB,EAAE,6CAA6C;IACrE;;yDAEqD;IACrD,4BAA4B,EAC1B,mDAAmD;CAC7C,CAAC;AAqCX;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,oBAAoB,CAClC,GAAW;IAEX,MAAM,eAAe,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAA,iBAAG,EACR,IAAA,wBAAU,EAAC;YACT,IAAI,EAAE,uBAAe,CAAC,WAAW;YACjC,SAAS,EAAE,oBAAoB;YAC/B,OAAO,EACL,0HAA0H;SAC7H,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,OAAO,GAAkB,IAAI,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QAC1B,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,IAAI,CAAC,CAAC;YACT,SAAS;QACX,CAAC;QACD,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,GAAG,IAAI,CAAC,CAAC;YACT,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,MAAiC,CAAC;QAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;aAAM,IACL,KAAK,KAAK,IAAI;YACd,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB,OAAQ,KAAiC,CAAC,MAAM,CAAC,KAAK,QAAQ,EAC9D,CAAC;YACD,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC/D,QAAQ,GAAG,EAAE,CAAC;YAChB,CAAC;YACD,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;YACtB,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC9D,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAkB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,IAAA,gBAAE,EAAC;QACR,IAAI;QACJ,KAAK,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE;QACzE,SAAS,EAAE,QAAQ,CAAC,MAAM;QAC1B,QAAQ;QACR,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,GAAW,EAAE,GAAW;IACzD,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,CAAC;IACjC,IAAI,cAAc,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAC/D,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,eAAe,CAAC;IAC/C,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9B,mEAAmE;IACnE,wEAAwE;IACxE,yEAAyE;IACzE,0EAA0E;IAC1E,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9B,uEAAuE;IACvE,qEAAqE;IACrE,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAwBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,qBAAqB,CACnC,KAA+B;IAE/B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,iBAAiB,GAAa,EAAE,CAAC;IAEvC,MAAM,OAAO,GAAG,wCAAwC,CAAC;IACzD,MAAM,OAAO,GAAG,wCAAwC,CAAC;IAEzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,iEAAiE;YACjE,sDAAsD;YACtD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,MAAM,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC7B,QAAQ;QACR,QAAQ;QACR,iBAAiB;KAClB,CAAC;AACJ,CAAC;AAiED,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,kBAAkB,CAChC,SAAyB,EACzB,IAAiB;IAEjB,qEAAqE;IACrE,mEAAmE;IACnE,mDAAmD;IACnD,IAAI,SAAS,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAC1C,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,kBAAkB;YACzB,UAAU,EAAE,IAAA,wBAAU,EAAC;gBACrB,IAAI,EAAE,uBAAe,CAAC,iBAAiB;gBACvC,SAAS,EAAE,oBAAoB;gBAC/B,OAAO,EAAE,6CAA6C,SAAS,CAAC,KAAK,CAAC,WAAW,iBAAiB,SAAS,CAAC,SAAS,6EAA6E;aACnM,CAAC;YACF,SAAS;SACV,CAAC;IACJ,CAAC;IAED,iEAAiE;IACjE,oEAAoE;IACpE,oEAAoE;IACpE,iEAAiE;IACjE,gEAAgE;IAChE,kEAAkE;IAClE,gEAAgE;IAChE,8DAA8D;IAC9D,6DAA6D;IAC7D,kBAAkB;IAClB,IACE,SAAS,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC;QAC/B,SAAS,CAAC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,SAAS,EACjD,CAAC;QACD,MAAM,SAAS,GACb,SAAS,CAAC,KAAK,CAAC,gBAAgB,GAAG,SAAS,CAAC,KAAK,CAAC,gBAAgB,CAAC;QACtE,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,oBAAoB;YAC3B,UAAU,EAAE,IAAA,wBAAU,EAAC;gBACrB,IAAI,EAAE,uBAAe,CAAC,0BAA0B;gBAChD,SAAS,EAAE,oBAAoB;gBAC/B,OAAO,EAAE,oBAAoB,SAAS,CAAC,KAAK,CAAC,WAAW,kCAAkC,SAAS,uBAAuB,SAAS,CAAC,SAAS,qLAAqL;gBAClU,YAAY,EACV,2LAA2L;aAC9L,CAAC;YACF,SAAS;SACV,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,iEAAiE;IACjE,kEAAkE;IAClE,4DAA4D;IAC5D,IACE,IAAI,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI;QAChC,IAAI,CAAC,mBAAmB,KAAK,IAAI,EACjC,CAAC;QACD,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,yCAAyC;YAChD,UAAU,EAAE,IAAA,wBAAU,EAAC;gBACrB,IAAI,EAAE,uBAAe,CAAC,iBAAiB;gBACvC,SAAS,EAAE,oBAAoB;gBAC/B,OAAO,EAAE,mCAAmC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,gCAAgC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,yFAAyF;gBACnO,YAAY,EACV,0MAA0M;aAC7M,CAAC;YACF,SAAS;YACT,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,0DAA0D;IAC1D,MAAM,UAAU,GACd,SAAS,CAAC,IAAI,KAAK,SAAS;QAC5B,SAAS,CAAC,KAAK,CAAC,gBAAgB,KAAK,CAAC;QACtC,SAAS,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC;QACjC,SAAS,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC;IACvC,IAAI,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC3C,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,kCAAkC;YACzC,UAAU,EAAE,IAAA,wBAAU,EAAC;gBACrB,IAAI,EAAE,sDAAsD;gBAC5D,SAAS,EAAE,oBAAoB;gBAC/B,OAAO,EAAE,gEAAgE,SAAS,CAAC,KAAK,CAAC,gBAAgB,sFAAsF;gBAC/L,YAAY,EACV,2JAA2J;aAC9J,CAAC;YACF,SAAS;SACV,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,IAAI;QACpC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,mBAAmB,EAAE,GAAG,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACnE,SAAS;QACT,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,CAAO;IAC7B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ChainedEvent, type EventBody, type Result } from '@paths.design/caws-kernel';
|
|
1
|
+
import { type Actor, type ChainedEvent, type EventBody, type Result } from '@paths.design/caws-kernel';
|
|
2
2
|
import type { EventsLoadResult } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Load events from `.caws/events.jsonl`.
|
|
@@ -30,4 +30,50 @@ export declare function loadEvents(cawsDir: string): Result<EventsLoadResult>;
|
|
|
30
30
|
* authority.
|
|
31
31
|
*/
|
|
32
32
|
export declare function appendEvent(cawsDir: string, body: EventBody): Result<ChainedEvent>;
|
|
33
|
+
export interface RotateEventsOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Operator-supplied reason recorded verbatim into chain_rotated.data.
|
|
36
|
+
* migration_reason. Required for every rotate invocation regardless of
|
|
37
|
+
* chain shape; see CAWS-MIGRATE-V10-EVENTS-001 A6/A8.
|
|
38
|
+
*/
|
|
39
|
+
readonly reason: string;
|
|
40
|
+
/**
|
|
41
|
+
* Actor to attribute the chain_rotated event to. The kernel envelope
|
|
42
|
+
* requires a structured Actor; the shell command's buildActor() helper
|
|
43
|
+
* is the conventional source.
|
|
44
|
+
*/
|
|
45
|
+
readonly actor: Actor;
|
|
46
|
+
/**
|
|
47
|
+
* Friction flag. When the prior chain has only structured (v11) actors,
|
|
48
|
+
* rotation is refused unless allowClean === true. Default false means
|
|
49
|
+
* rotation against a clean chain is treated as an operator slip; the
|
|
50
|
+
* caller must explicitly opt in to log rotation as a non-migration
|
|
51
|
+
* maintenance operation. See A8.
|
|
52
|
+
*/
|
|
53
|
+
readonly allowClean?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Override the wall-clock used for the archive timestamp. Tests inject
|
|
56
|
+
* a fixed Date; production omits this and the function uses new Date().
|
|
57
|
+
*/
|
|
58
|
+
readonly now?: Date;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Rotate the events.jsonl chain: archive the existing file under a
|
|
62
|
+
* timestamped name and write a fresh chain whose genesis event is
|
|
63
|
+
* chain_rotated, cryptographically tying the archive to the new chain
|
|
64
|
+
* via prior_file_digest.
|
|
65
|
+
*
|
|
66
|
+
* Refusals (typed Diagnostic, no file mutations on any refusal path):
|
|
67
|
+
* - EVENTS_ROTATE_NOTHING_TO_ROTATE: file missing or zero-length.
|
|
68
|
+
* - EVENTS_ROTATE_CLEAN_CHAIN_REQUIRES_ALLOW_CLEAN: all entries are
|
|
69
|
+
* structured (v11) actors and allowClean !== true.
|
|
70
|
+
* - EVENTS_PREPARE_APPEND_REJECTED: the constructed chain_rotated body
|
|
71
|
+
* failed kernel validation (programmer error in this function or a
|
|
72
|
+
* schema change drift). Carries kernel diagnostics in data.source_rule.
|
|
73
|
+
* - WRITE_IO_FAILED: rename or genesis-write failed at the FS layer.
|
|
74
|
+
*
|
|
75
|
+
* On success returns the new ChainedEvent (the chain_rotated genesis event
|
|
76
|
+
* that is now the entirety of the new events.jsonl).
|
|
77
|
+
*/
|
|
78
|
+
export declare function rotateEvents(cawsDir: string, opts: RotateEventsOptions): Result<ChainedEvent>;
|
|
33
79
|
//# sourceMappingURL=events-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-store.d.ts","sourceRoot":"","sources":["../../src/store/events-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"events-store.d.ts","sourceRoot":"","sources":["../../src/store/events-store.ts"],"names":[],"mappings":"AAuBA,OAAO,EAML,KAAK,KAAK,EACV,KAAK,YAAY,EAEjB,KAAK,SAAS,EACd,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAUhD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAoBpE;AAoFD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,GACd,MAAM,CAAC,YAAY,CAAC,CAgEtB;AAoCD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,mBAAmB,GACxB,MAAM,CAAC,YAAY,CAAC,CA0MtB"}
|