@cleocode/contracts 2026.10.12 → 2026.10.13
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/attachment.d.ts +5 -2
- package/dist/attachment.d.ts.map +1 -1
- package/dist/branch-lock.d.ts +3 -0
- package/dist/branch-lock.d.ts.map +1 -1
- package/dist/branch-lock.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/dispatch/__tests__/operation-envelope-snapshots.test.js +8 -0
- package/dist/dispatch/__tests__/operation-envelope-snapshots.test.js.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +84 -2
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/done-plan.d.ts +1 -1
- package/dist/done-plan.d.ts.map +1 -1
- package/dist/graph.d.ts +24 -4
- package/dist/graph.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/invariants/sync-write-invariants.d.ts.map +1 -1
- package/dist/invariants/sync-write-invariants.js +30 -4
- package/dist/invariants/sync-write-invariants.js.map +1 -1
- package/dist/lean.d.ts +34 -0
- package/dist/lean.d.ts.map +1 -0
- package/dist/lean.js +14 -0
- package/dist/lean.js.map +1 -0
- package/dist/lease-ipc/messages.d.ts +10 -10
- package/dist/ledger/index.d.ts +4 -4
- package/dist/operations/docs.d.ts +259 -6
- package/dist/operations/docs.d.ts.map +1 -1
- package/dist/operations/docs.js.map +1 -1
- package/dist/operations/worktree.d.ts +50 -0
- package/dist/operations/worktree.d.ts.map +1 -1
- package/dist/project-hooks.d.ts +1 -1
- package/dist/resource-governor.d.ts +6 -0
- package/dist/resource-governor.d.ts.map +1 -1
- package/dist/resource-governor.js +6 -0
- package/dist/resource-governor.js.map +1 -1
- package/dist/templates/manifest.d.ts +1 -1
- package/dist/tools/atomic.d.ts +5 -2
- package/dist/tools/atomic.d.ts.map +1 -1
- package/dist/tools/atomic.js.map +1 -1
- package/dist/workgraph.d.ts +4 -4
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/attachment.ts +5 -2
- package/src/branch-lock.ts +4 -0
- package/src/config.ts +7 -0
- package/src/dispatch/__tests__/operation-envelope-snapshots.test.ts +8 -0
- package/src/dispatch/operations-registry.ts +89 -2
- package/src/done-plan.ts +1 -0
- package/src/graph.ts +25 -4
- package/src/index.ts +7 -0
- package/src/invariants/sync-write-invariants.ts +56 -29
- package/src/lean.ts +36 -0
- package/src/operations/docs.ts +266 -6
- package/src/operations/worktree.ts +49 -0
- package/src/resource-governor.ts +7 -0
- package/src/tools/atomic.ts +5 -2
package/src/attachment.ts
CHANGED
|
@@ -177,7 +177,9 @@ export type AttachmentKind = Attachment['kind'];
|
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
179
|
* Persisted metadata row for one attachment in the attachment registry
|
|
180
|
-
* (
|
|
180
|
+
* (the `attachments` table of the project `cleo.db`, twin-carried into
|
|
181
|
+
* `docs_attachments`; the legacy `.cleo/attachments/index.db` file is
|
|
182
|
+
* retired — T13362).
|
|
181
183
|
*
|
|
182
184
|
* The full {@link Attachment} value is stored as a JSON blob in the `attachment`
|
|
183
185
|
* field so the registry does not need a column per variant.
|
|
@@ -217,7 +219,8 @@ export interface AttachmentMetadata {
|
|
|
217
219
|
/**
|
|
218
220
|
* Junction row linking one attachment to one owner.
|
|
219
221
|
*
|
|
220
|
-
* Stored in the `attachment_refs` table of
|
|
222
|
+
* Stored in the `attachment_refs` table of the project `cleo.db`
|
|
223
|
+
* (twin-carried into `docs_attachment_refs`).
|
|
221
224
|
* A single attachment can be referenced by multiple owners simultaneously
|
|
222
225
|
* (e.g., the same RFC PDF attached to an epic and to every child task).
|
|
223
226
|
*/
|
package/src/branch-lock.ts
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* @adr ADR-062
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import type { WorktreeDisposalBlockers } from './operations/worktree.js';
|
|
21
|
+
|
|
20
22
|
// ---------------------------------------------------------------------------
|
|
21
23
|
// L1 — Worktree lifecycle types
|
|
22
24
|
// ---------------------------------------------------------------------------
|
|
@@ -85,6 +87,8 @@ export interface WorktreeMergeResult {
|
|
|
85
87
|
rebased: boolean;
|
|
86
88
|
/** Whether the worktree filesystem entry was removed. */
|
|
87
89
|
worktreeRemoved: boolean;
|
|
90
|
+
/** Set when the worktree was kept because something still needs its files (T13696). */
|
|
91
|
+
worktreeKept?: WorktreeDisposalBlockers;
|
|
88
92
|
/** Whether `task/<taskId>` was deleted post-merge. */
|
|
89
93
|
branchDeleted: boolean;
|
|
90
94
|
/** Error message if any step failed (non-fatal — caller decides). */
|
package/src/config.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { HeavyCommandHookMode } from './heavy-command-hook.js';
|
|
13
|
+
import type { LeanConfig } from './lean.js';
|
|
13
14
|
import type { ModelTransport } from './operations/llm.js';
|
|
14
15
|
|
|
15
16
|
/** Output format options. */
|
|
@@ -895,6 +896,12 @@ export interface ResourcesConfig {
|
|
|
895
896
|
|
|
896
897
|
/** CLEO project configuration (config.json). */
|
|
897
898
|
export interface CleoConfig {
|
|
899
|
+
/**
|
|
900
|
+
* ct-lean rule level (T13663).
|
|
901
|
+
*
|
|
902
|
+
* @defaultValue undefined (level `full`)
|
|
903
|
+
*/
|
|
904
|
+
lean?: LeanConfig;
|
|
898
905
|
/** Configuration schema version string. */
|
|
899
906
|
version: string;
|
|
900
907
|
/** Output formatting preferences. */
|
|
@@ -112,6 +112,14 @@ describe('operation envelope registry snapshots (T10615)', () => {
|
|
|
112
112
|
"required": false,
|
|
113
113
|
"type": "string",
|
|
114
114
|
},
|
|
115
|
+
{
|
|
116
|
+
"cli": {
|
|
117
|
+
"flag": "base-version-uid",
|
|
118
|
+
},
|
|
119
|
+
"name": "baseVersionUid",
|
|
120
|
+
"required": false,
|
|
121
|
+
"type": "string",
|
|
122
|
+
},
|
|
115
123
|
{
|
|
116
124
|
"cli": undefined,
|
|
117
125
|
"name": "message",
|
|
@@ -5038,6 +5038,35 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
5038
5038
|
},
|
|
5039
5039
|
] satisfies ParamDef[],
|
|
5040
5040
|
},
|
|
5041
|
+
{
|
|
5042
|
+
gateway: 'mutate',
|
|
5043
|
+
domain: 'pipeline',
|
|
5044
|
+
operation: 'manifest.update',
|
|
5045
|
+
description:
|
|
5046
|
+
'pipeline.manifest.update (mutate) — change only the given fields of a manifest entry; linkTask adds a linked task (T13678)',
|
|
5047
|
+
tier: 1,
|
|
5048
|
+
idempotent: true,
|
|
5049
|
+
sessionRequired: false,
|
|
5050
|
+
requiredParams: ['id'],
|
|
5051
|
+
params: [
|
|
5052
|
+
{ name: 'id', type: 'string', required: true, description: 'Manifest entry id' },
|
|
5053
|
+
{
|
|
5054
|
+
name: 'linkTask',
|
|
5055
|
+
type: 'string',
|
|
5056
|
+
required: false,
|
|
5057
|
+
description: 'Task id to add to linked_tasks',
|
|
5058
|
+
},
|
|
5059
|
+
{ name: 'title', type: 'string', required: false, description: 'New title' },
|
|
5060
|
+
{ name: 'topics', type: 'array', required: false, description: 'Replacement topics' },
|
|
5061
|
+
{
|
|
5062
|
+
name: 'key_findings',
|
|
5063
|
+
type: 'array',
|
|
5064
|
+
required: false,
|
|
5065
|
+
description: 'Replacement key findings',
|
|
5066
|
+
},
|
|
5067
|
+
{ name: 'status', type: 'string', required: false, description: 'New status' },
|
|
5068
|
+
] satisfies ParamDef[],
|
|
5069
|
+
},
|
|
5041
5070
|
{
|
|
5042
5071
|
gateway: 'mutate',
|
|
5043
5072
|
domain: 'pipeline',
|
|
@@ -8690,6 +8719,22 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8690
8719
|
},
|
|
8691
8720
|
],
|
|
8692
8721
|
},
|
|
8722
|
+
// ── docs.stats (T13363 — Epic T13340 / Saga T13339) ───────────────────────
|
|
8723
|
+
{
|
|
8724
|
+
gateway: 'query',
|
|
8725
|
+
domain: 'docs',
|
|
8726
|
+
operation: 'stats',
|
|
8727
|
+
description:
|
|
8728
|
+
'docs.stats (query) — per-project CleoDocs adoption metrics (read-only): add:update ' +
|
|
8729
|
+
'ratio from the docs audit log, loose-markdown count with scanned/excluded dirs, ' +
|
|
8730
|
+
'docs_wikilinks edge count, and live decision_adr_links count. Emitted for the ' +
|
|
8731
|
+
'Council pilot baseline comparisons.',
|
|
8732
|
+
tier: 1,
|
|
8733
|
+
idempotent: true,
|
|
8734
|
+
sessionRequired: false,
|
|
8735
|
+
requiredParams: [],
|
|
8736
|
+
params: [],
|
|
8737
|
+
},
|
|
8693
8738
|
{
|
|
8694
8739
|
gateway: 'mutate',
|
|
8695
8740
|
domain: 'docs',
|
|
@@ -8697,8 +8742,10 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8697
8742
|
description:
|
|
8698
8743
|
'docs.doctor (mutate) — apply the docs doctor repairs: set docVersion from the audit ' +
|
|
8699
8744
|
'log, backfill topics/related_tasks from content, archive dangling local-file rows, ' +
|
|
8700
|
-
'rebuild docs_wikilinks
|
|
8701
|
-
'
|
|
8745
|
+
'rebuild docs_wikilinks, and backfill hash-verified legacy bytes into the blob store. ' +
|
|
8746
|
+
'The dispatch layer creates a fresh backup (cleo backup add ' +
|
|
8747
|
+
'path) and requires its receipt before any write. repair:true restricts the run to ' +
|
|
8748
|
+
'the legacy-blob-coverage backfill only (T13653).',
|
|
8702
8749
|
tier: 1,
|
|
8703
8750
|
idempotent: false,
|
|
8704
8751
|
sessionRequired: false,
|
|
@@ -8710,6 +8757,14 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8710
8757
|
required: false,
|
|
8711
8758
|
description: 'Execute repairs (default false — dry-run plan only)',
|
|
8712
8759
|
},
|
|
8760
|
+
{
|
|
8761
|
+
name: 'repair',
|
|
8762
|
+
type: 'boolean' as const,
|
|
8763
|
+
required: false,
|
|
8764
|
+
description:
|
|
8765
|
+
'Execute ONLY the legacy-blob-coverage backfill: mirror hash-verified legacy ' +
|
|
8766
|
+
'bytes into the blob store so unmigrated docs become readable (T13653)',
|
|
8767
|
+
},
|
|
8713
8768
|
{
|
|
8714
8769
|
name: 'olderThanDays',
|
|
8715
8770
|
type: 'number' as const,
|
|
@@ -8718,6 +8773,24 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8718
8773
|
},
|
|
8719
8774
|
],
|
|
8720
8775
|
},
|
|
8776
|
+
// ── docs.migrate (T13360 — Epic T13340 / Saga T13339) ─────────────────────
|
|
8777
|
+
{
|
|
8778
|
+
gateway: 'mutate',
|
|
8779
|
+
domain: 'docs',
|
|
8780
|
+
operation: 'migrate',
|
|
8781
|
+
description:
|
|
8782
|
+
'docs.migrate (mutate) — the T13360 legacy docs migration (spec §5): import legacy ' +
|
|
8783
|
+
'docs + history into the re-keyed conduit store inside the T13448 safety harness ' +
|
|
8784
|
+
'(pre-step VACUUM INTO backup, before/after fingerprints, COMMIT only on full ' +
|
|
8785
|
+
'verification). Imported rows are labeled origin:migrated; dangling-pointer docs are ' +
|
|
8786
|
+
'content-captured or recorded dangling in conduit_doc_migration_ledger. Idempotent — ' +
|
|
8787
|
+
'a re-run is a verified no-op.',
|
|
8788
|
+
tier: 1,
|
|
8789
|
+
idempotent: true,
|
|
8790
|
+
sessionRequired: false,
|
|
8791
|
+
requiredParams: [],
|
|
8792
|
+
params: [],
|
|
8793
|
+
},
|
|
8721
8794
|
// ── docs.generate (T798) ─────────────────────────────────────────────────
|
|
8722
8795
|
{
|
|
8723
8796
|
gateway: 'query',
|
|
@@ -8826,6 +8899,20 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8826
8899
|
required: false,
|
|
8827
8900
|
description: 'Inline UTF-8 content (mutually exclusive with file)',
|
|
8828
8901
|
},
|
|
8902
|
+
{
|
|
8903
|
+
name: 'baseVersionUid',
|
|
8904
|
+
type: 'string' as const,
|
|
8905
|
+
required: false,
|
|
8906
|
+
description:
|
|
8907
|
+
'Expected base version uid — the metadata.headVersionUid from the `cleo docs fetch <slug>` envelope the edit was authored against (T13674). ' +
|
|
8908
|
+
'When the stored head has moved past it: append-shaped section edits are three-way merged through the section CRDT (both writers survive); ' +
|
|
8909
|
+
'a non-mergeable section edit is recorded as a named section conflict — nothing is silently dropped. ' +
|
|
8910
|
+
"A base that does not resolve to this doc's version history is refused with E_DOC_BASE_UNKNOWN before any write. " +
|
|
8911
|
+
'Works with --content and with a UTF-8 text --file; a non-text --file with a base is refused with E_DOC_BASE_UNSUPPORTED. ' +
|
|
8912
|
+
'The update result carries the new headVersionUid, so edits can chain without a re-fetch. ' +
|
|
8913
|
+
'Omit only when the edit was not based on an earlier fetch (the current head is then assumed).',
|
|
8914
|
+
cli: { flag: 'base-version-uid' },
|
|
8915
|
+
},
|
|
8829
8916
|
{
|
|
8830
8917
|
name: 'message',
|
|
8831
8918
|
type: 'string' as const,
|
package/src/done-plan.ts
CHANGED
package/src/graph.ts
CHANGED
|
@@ -769,15 +769,36 @@ export interface GraphPublicationRows {
|
|
|
769
769
|
generation?: string;
|
|
770
770
|
/** Source provenance and coverage belonging to this generation. */
|
|
771
771
|
assessment?: GraphIndexAssessment;
|
|
772
|
-
/**
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
772
|
+
/**
|
|
773
|
+
* Complete replacement node generation. May be serialized lazily as the
|
|
774
|
+
* publisher iterates it (once), so the graph is not held twice (T13656).
|
|
775
|
+
*/
|
|
776
|
+
nodes: Iterable<NexusNodeInsertRow>;
|
|
777
|
+
/** Complete replacement relationship generation; may be lazy like `nodes`. */
|
|
778
|
+
relations: Iterable<NexusRelationInsertRow>;
|
|
776
779
|
/**
|
|
777
780
|
* Per-file extraction memo changes committed in the same transaction as the rows.
|
|
778
781
|
* Absent when the producer does not maintain a parse cache.
|
|
779
782
|
*/
|
|
780
783
|
parseCache?: GraphParseCacheUpdate;
|
|
784
|
+
/**
|
|
785
|
+
* The generation's retained references, already in their stored encoding
|
|
786
|
+
* (T13656). When present, `assessment.references` is absent and
|
|
787
|
+
* `assessment.referenceCount` equals `references.count`.
|
|
788
|
+
*/
|
|
789
|
+
references?: GraphStoredReferences;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* A reference list in its stored encoding: the JSON array, one reference per
|
|
794
|
+
* line, as concatenated gzip members (T13326). Producers stream references into
|
|
795
|
+
* it as they are reported, so the list is never held as objects (T13656).
|
|
796
|
+
*/
|
|
797
|
+
export interface GraphStoredReferences {
|
|
798
|
+
/** Number of references encoded. */
|
|
799
|
+
count: number;
|
|
800
|
+
/** The compressed list, stored verbatim. */
|
|
801
|
+
payload: Uint8Array;
|
|
781
802
|
}
|
|
782
803
|
|
|
783
804
|
/**
|
package/src/index.ts
CHANGED
|
@@ -774,6 +774,7 @@ export type {
|
|
|
774
774
|
GraphPublicationRows,
|
|
775
775
|
GraphRelation,
|
|
776
776
|
GraphRelationType,
|
|
777
|
+
GraphStoredReferences,
|
|
777
778
|
ImpactResult,
|
|
778
779
|
InferredProvenance,
|
|
779
780
|
KnowledgeGraph,
|
|
@@ -896,6 +897,8 @@ export {
|
|
|
896
897
|
isLafsError,
|
|
897
898
|
isLafsSuccess,
|
|
898
899
|
} from './lafs.js';
|
|
900
|
+
// === ct-lean levels (T13663 / Epic T13418) ===
|
|
901
|
+
export type { LeanConfig, LeanLevel, LeanLevelSource } from './lean.js';
|
|
899
902
|
// === Lease-IPC v1.1 (PARALLEL DbWriterLease contract — T11627 · SG-RUNTIME-UNIFICATION) ===
|
|
900
903
|
export type {
|
|
901
904
|
ChildKilledUnresponsiveResponse,
|
|
@@ -1357,6 +1360,8 @@ export type {
|
|
|
1357
1360
|
export {
|
|
1358
1361
|
DOCS_LIFECYCLE_STATUSES,
|
|
1359
1362
|
type DocsLifecycleStatus,
|
|
1363
|
+
type DocsSectionConflict,
|
|
1364
|
+
type DocsSectionLeaseNotice,
|
|
1360
1365
|
type DocsUpdateParams,
|
|
1361
1366
|
} from './operations/docs.js';
|
|
1362
1367
|
// === Ensures-schema Zod registry (T11762 ST-1 / T11900 — cantbook ensures.schema SSoT) ===
|
|
@@ -2028,11 +2033,13 @@ export type {
|
|
|
2028
2033
|
PruneOrphanedWorktreesResult,
|
|
2029
2034
|
PruneWorktreesOptions,
|
|
2030
2035
|
PruneWorktreesResult,
|
|
2036
|
+
WorktreeDisposalBlockers,
|
|
2031
2037
|
WorktreeHook,
|
|
2032
2038
|
WorktreeHookResult,
|
|
2033
2039
|
WorktreeIncludePattern,
|
|
2034
2040
|
WorktreeInfo,
|
|
2035
2041
|
WorktreeInstallOutcome,
|
|
2042
|
+
WorktreeKeepMarker,
|
|
2036
2043
|
WorktreeLifecycleAction,
|
|
2037
2044
|
WorktreeLifecycleAuditEntry,
|
|
2038
2045
|
WorktreeListEntry,
|
|
@@ -462,21 +462,25 @@ export const SYNC_WRITE_INVARIANTS: readonly SyncWriteInvariant[] = Object.freez
|
|
|
462
462
|
['tasks_audit_log', 'audit_log'],
|
|
463
463
|
),
|
|
464
464
|
),
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
465
|
+
implemented(
|
|
466
|
+
rule(
|
|
467
|
+
'sticky.status.one-way',
|
|
468
|
+
'T12942',
|
|
469
|
+
'brain_sticky_notes',
|
|
470
|
+
['status', 'converted_to_json'],
|
|
471
|
+
['SK2', 'SK3', 'B24'],
|
|
472
|
+
'active→{converted, archived} is one-way; converted_to_json is write-once',
|
|
473
|
+
),
|
|
472
474
|
),
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
475
|
+
implemented(
|
|
476
|
+
rule(
|
|
477
|
+
'release.status.absorbing',
|
|
478
|
+
'T12943',
|
|
479
|
+
'tasks_releases',
|
|
480
|
+
['status'],
|
|
481
|
+
['REL-2', 'REL-3', 'REL-4', 'REL-5', 'REL-6', 'REL-7', 'REL-8'],
|
|
482
|
+
'shipped release statuses are absorbing',
|
|
483
|
+
),
|
|
480
484
|
),
|
|
481
485
|
implemented(
|
|
482
486
|
rule(
|
|
@@ -489,13 +493,15 @@ export const SYNC_WRITE_INVARIANTS: readonly SyncWriteInvariant[] = Object.freez
|
|
|
489
493
|
['tasks_playbook_approvals', 'playbook_approvals'],
|
|
490
494
|
),
|
|
491
495
|
),
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
496
|
+
implemented(
|
|
497
|
+
rule(
|
|
498
|
+
'docs.lifecycle.transitions',
|
|
499
|
+
'T12945',
|
|
500
|
+
'docs_attachments',
|
|
501
|
+
['lifecycle_status'],
|
|
502
|
+
['D04', 'D05', 'D31', 'D32', 'D39', 'D50'],
|
|
503
|
+
'superseded is sticky; lifecycle transitions follow a matrix',
|
|
504
|
+
),
|
|
499
505
|
),
|
|
500
506
|
// T13354 (D11165) — CleoDocs re-keyed history family; the typed merge rules
|
|
501
507
|
// land with the write path (T13355).
|
|
@@ -523,14 +529,35 @@ export const SYNC_WRITE_INVARIANTS: readonly SyncWriteInvariant[] = Object.freez
|
|
|
523
529
|
[],
|
|
524
530
|
'alias rows carry natural identity over (slug, doc_uid); identical aliases merge to one row',
|
|
525
531
|
),
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
'
|
|
533
|
-
|
|
532
|
+
// T13355 (D11165): the write-path behavior is implemented at the writer
|
|
533
|
+
// chokepoint (`upsertConduitDocHead`, now reachable from the docs update
|
|
534
|
+
// write path); cross-device convergence rides the Stage C journal merge
|
|
535
|
+
// engine (T12344) and needs no second rule.
|
|
536
|
+
{
|
|
537
|
+
id: 'docs.head.max-hlc',
|
|
538
|
+
class: 'monotonic-merge-rule',
|
|
539
|
+
tables: ['conduit_doc_heads'],
|
|
540
|
+
sites: [],
|
|
541
|
+
mergeRule: { table: 'conduit_doc_heads', columns: ['*'] },
|
|
542
|
+
inventory: [],
|
|
543
|
+
runtimeGate: {
|
|
544
|
+
module: 'packages/core/src/store/conduit-doc-history.ts',
|
|
545
|
+
functionName: 'upsertConduitDocHead',
|
|
546
|
+
},
|
|
547
|
+
reason:
|
|
548
|
+
'the projection keeps the max-HLC head; a losing concurrent head is recorded (conflict_count/last_conflict_json), never silently shadowed',
|
|
549
|
+
},
|
|
550
|
+
// T13355 — the docs write path adopts a legacy doc into the conduit family
|
|
551
|
+
// once (identity shell keyed by the immutable uid); the read-back guard is
|
|
552
|
+
// a local write-confirmation, not a merge rule.
|
|
553
|
+
{
|
|
554
|
+
id: 'docs.doc.adopt-once',
|
|
555
|
+
class: 'not-sync-relevant',
|
|
556
|
+
tables: ['conduit_attachments'],
|
|
557
|
+
sites: [],
|
|
558
|
+
reason:
|
|
559
|
+
'adopting a legacy doc inserts one immutable-uid identity shell; losing the write is refused loudly at the writer, not merged',
|
|
560
|
+
},
|
|
534
561
|
// T13359 (D11165) — decisions-vs-ADRs link table; the natural composite key
|
|
535
562
|
// makes identical links merge to one row, and the revoke is a one-way latch.
|
|
536
563
|
// T13597: enforced at merge, not just by the local accessor — 'revoked' is an
|
package/src/lean.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ct-lean levels — shared types (T13663).
|
|
3
|
+
*
|
|
4
|
+
* The lean-change rules (the `ct-lean` skill, adapted from Ponytail 5.1.0,
|
|
5
|
+
* DietrichGebert, MIT) run at one of four levels. The level resolves from the
|
|
6
|
+
* `CLEO_LEAN_LEVEL` environment variable, then the session-scoped level set by
|
|
7
|
+
* `cleo lean level <l> --session`, then the `lean.level` config key (project
|
|
8
|
+
* over global), then `full`.
|
|
9
|
+
*
|
|
10
|
+
* @task T13663
|
|
11
|
+
* @epic T13418
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* How strictly the lean-change rules apply.
|
|
16
|
+
*
|
|
17
|
+
* - `off` — no lean rules are emitted.
|
|
18
|
+
* - `lite` — build what was asked; name the smaller option in one line.
|
|
19
|
+
* - `full` — DEFAULT. The smallest complete change (the full ct-lean rules).
|
|
20
|
+
* - `ultra` — `full`, and also question the request before building.
|
|
21
|
+
*/
|
|
22
|
+
export type LeanLevel = 'off' | 'lite' | 'full' | 'ultra';
|
|
23
|
+
|
|
24
|
+
/** Where a resolved lean level came from. */
|
|
25
|
+
export type LeanLevelSource = 'env' | 'session' | 'config' | 'default';
|
|
26
|
+
|
|
27
|
+
/** The `lean` section of `.cleo/config.json`. */
|
|
28
|
+
export interface LeanConfig {
|
|
29
|
+
/**
|
|
30
|
+
* Default lean level for this project (or, in the global config, every
|
|
31
|
+
* project). `CLEO_LEAN_LEVEL` and a session-scoped level override it.
|
|
32
|
+
*
|
|
33
|
+
* @defaultValue 'full'
|
|
34
|
+
*/
|
|
35
|
+
level?: LeanLevel;
|
|
36
|
+
}
|