@cleocode/contracts 2026.10.10-canary.2 → 2026.10.10
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/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +59 -0
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/invariants/sync-write-invariants.d.ts.map +1 -1
- package/dist/invariants/sync-write-invariants.js +6 -0
- package/dist/invariants/sync-write-invariants.js.map +1 -1
- package/dist/operations/docs.d.ts +44 -1
- package/dist/operations/docs.d.ts.map +1 -1
- package/dist/operations/docs.js.map +1 -1
- package/dist/release/plan.d.ts +1 -0
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +2 -0
- package/dist/release/plan.js.map +1 -1
- package/dist/task.d.ts +4 -0
- package/dist/task.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/dispatch/operations-registry.ts +62 -0
- package/src/invariants/sync-write-invariants.ts +15 -0
- package/src/operations/docs.ts +45 -0
- package/src/release/plan.ts +2 -0
- package/src/task.ts +4 -0
|
@@ -8169,6 +8169,61 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8169
8169
|
},
|
|
8170
8170
|
],
|
|
8171
8171
|
},
|
|
8172
|
+
// ── docs.link-decision / docs.unlink-decision (T13598) ──────────────────
|
|
8173
|
+
{
|
|
8174
|
+
gateway: 'mutate',
|
|
8175
|
+
domain: 'docs',
|
|
8176
|
+
operation: 'link-decision',
|
|
8177
|
+
description:
|
|
8178
|
+
'docs.link-decision (mutate) — link a D#### decision to the ADR doc that ratifies it (decision_adr_links); idempotent, refuses a revoked pair (T13598)',
|
|
8179
|
+
tier: 1,
|
|
8180
|
+
idempotent: true,
|
|
8181
|
+
sessionRequired: false,
|
|
8182
|
+
requiredParams: ['adrSlug', 'decisionId'],
|
|
8183
|
+
params: [
|
|
8184
|
+
{
|
|
8185
|
+
name: 'adrSlug',
|
|
8186
|
+
type: 'string' as const,
|
|
8187
|
+
required: true,
|
|
8188
|
+
description: 'Slug of the ADR doc',
|
|
8189
|
+
cli: { positional: true },
|
|
8190
|
+
},
|
|
8191
|
+
{
|
|
8192
|
+
name: 'decisionId',
|
|
8193
|
+
type: 'string' as const,
|
|
8194
|
+
required: true,
|
|
8195
|
+
description: 'The D#### brain ledger decision id the ADR ratifies',
|
|
8196
|
+
cli: { positional: true },
|
|
8197
|
+
},
|
|
8198
|
+
],
|
|
8199
|
+
},
|
|
8200
|
+
{
|
|
8201
|
+
gateway: 'mutate',
|
|
8202
|
+
domain: 'docs',
|
|
8203
|
+
operation: 'unlink-decision',
|
|
8204
|
+
description:
|
|
8205
|
+
'docs.unlink-decision (mutate) — revoke a decision-to-ADR link as a permanent tombstone; the pair can never be re-linked (T13598)',
|
|
8206
|
+
tier: 1,
|
|
8207
|
+
idempotent: true,
|
|
8208
|
+
sessionRequired: false,
|
|
8209
|
+
requiredParams: ['adrSlug', 'decisionId'],
|
|
8210
|
+
params: [
|
|
8211
|
+
{
|
|
8212
|
+
name: 'adrSlug',
|
|
8213
|
+
type: 'string' as const,
|
|
8214
|
+
required: true,
|
|
8215
|
+
description: 'Slug of the ADR doc',
|
|
8216
|
+
cli: { positional: true },
|
|
8217
|
+
},
|
|
8218
|
+
{
|
|
8219
|
+
name: 'decisionId',
|
|
8220
|
+
type: 'string' as const,
|
|
8221
|
+
required: true,
|
|
8222
|
+
description: 'The D#### brain ledger decision id to unlink',
|
|
8223
|
+
cli: { positional: true },
|
|
8224
|
+
},
|
|
8225
|
+
],
|
|
8226
|
+
},
|
|
8172
8227
|
// ── docs.supersede (T10162) ──────────────────────────────────────────────
|
|
8173
8228
|
{
|
|
8174
8229
|
gateway: 'mutate',
|
|
@@ -9477,6 +9532,13 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
9477
9532
|
required: false,
|
|
9478
9533
|
description: 'Require the unified-hooks pilot for this stable promotion',
|
|
9479
9534
|
},
|
|
9535
|
+
{
|
|
9536
|
+
name: 'hooksV1Waiver',
|
|
9537
|
+
type: 'string',
|
|
9538
|
+
required: false,
|
|
9539
|
+
description:
|
|
9540
|
+
'Audited reason to ship a source change that opens the hooks-v1 gate without the promotion',
|
|
9541
|
+
},
|
|
9480
9542
|
{
|
|
9481
9543
|
name: 'dryRun',
|
|
9482
9544
|
type: 'boolean',
|
|
@@ -519,6 +519,21 @@ export const SYNC_WRITE_INVARIANTS: readonly SyncWriteInvariant[] = Object.freez
|
|
|
519
519
|
[],
|
|
520
520
|
'the projection keeps the max-HLC head; a losing concurrent head is recorded (conflict_count/last_conflict_json), never silently shadowed',
|
|
521
521
|
),
|
|
522
|
+
// T13359 (D11165) — decisions-vs-ADRs link table; the natural composite key
|
|
523
|
+
// makes identical links merge to one row, and the revoke is a one-way latch.
|
|
524
|
+
// T13597: enforced at merge, not just by the local accessor — 'revoked' is an
|
|
525
|
+
// absorbing state with no leave op, so a concurrent same-uid link op cannot
|
|
526
|
+
// flip a tombstoned row back to 'linked' on any replica.
|
|
527
|
+
implemented(
|
|
528
|
+
rule(
|
|
529
|
+
'docs.decision-adr-links.revoke-monotonic',
|
|
530
|
+
'T13597',
|
|
531
|
+
'decision_adr_links',
|
|
532
|
+
['status', 'revoked_by'],
|
|
533
|
+
[],
|
|
534
|
+
'status flips linked→revoked exactly once (the row is the tombstone, never DELETEd); the merge engine refuses a non-absorbing status write onto a revoked row, so a concurrent re-link can never resurrect the pair',
|
|
535
|
+
),
|
|
536
|
+
),
|
|
522
537
|
|
|
523
538
|
// §3.6.0 identity-layer rows.
|
|
524
539
|
{
|
package/src/operations/docs.ts
CHANGED
|
@@ -371,6 +371,15 @@ export interface DocsFetchResult {
|
|
|
371
371
|
inlined: boolean;
|
|
372
372
|
/** Current attachment backend in use. */
|
|
373
373
|
attachmentBackend?: AttachmentBackend;
|
|
374
|
+
/**
|
|
375
|
+
* `D####` brain ledger decisions linked to this ADR doc through
|
|
376
|
+
* `decision_adr_links` (T13359, spec `cleodocs-rearch-design` §4/§10,
|
|
377
|
+
* D11165) — the ADR→decision direction of the two-way trace. Present only
|
|
378
|
+
* for fetched docs that have live (non-revoked) links; the ledger stays
|
|
379
|
+
* the operational authority, so an ADR always names the decisions it
|
|
380
|
+
* ratifies.
|
|
381
|
+
*/
|
|
382
|
+
linkedDecisions?: string[];
|
|
374
383
|
}
|
|
375
384
|
|
|
376
385
|
// --------------------------------------------------------------------------
|
|
@@ -899,6 +908,38 @@ export interface DocsSupersedeResult {
|
|
|
899
908
|
reason?: string;
|
|
900
909
|
}
|
|
901
910
|
|
|
911
|
+
// --------------------------------------------------------------------------
|
|
912
|
+
// docs.link-decision / docs.unlink-decision — decision_adr_links writers (T13598)
|
|
913
|
+
// --------------------------------------------------------------------------
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Parameters for `docs.link-decision` and `docs.unlink-decision`.
|
|
917
|
+
*
|
|
918
|
+
* @task T13598
|
|
919
|
+
*/
|
|
920
|
+
export interface DocsDecisionLinkParams {
|
|
921
|
+
/** The ADR doc slug (`adr-NNN-…`). */
|
|
922
|
+
adrSlug: string;
|
|
923
|
+
/** The `D####` brain ledger decision id. */
|
|
924
|
+
decisionId: string;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Result of `docs.link-decision` and `docs.unlink-decision`.
|
|
929
|
+
*
|
|
930
|
+
* @task T13598
|
|
931
|
+
*/
|
|
932
|
+
export interface DocsDecisionLinkResult {
|
|
933
|
+
/** The ADR doc slug. */
|
|
934
|
+
adrSlug: string;
|
|
935
|
+
/** The `D####` decision id. */
|
|
936
|
+
decisionId: string;
|
|
937
|
+
/** The link's state after the call. */
|
|
938
|
+
status: 'linked' | 'revoked';
|
|
939
|
+
/** False for an idempotent repeat (already linked, or already revoked). */
|
|
940
|
+
changed: boolean;
|
|
941
|
+
}
|
|
942
|
+
|
|
902
943
|
// --------------------------------------------------------------------------
|
|
903
944
|
// docs.doctor — store health diagnostics + safe repairs (T13447)
|
|
904
945
|
// --------------------------------------------------------------------------
|
|
@@ -1006,6 +1047,8 @@ export type DocsOps =
|
|
|
1006
1047
|
| { op: 'docs.remove'; params: DocsRemoveParams; result: DocsRemoveResult }
|
|
1007
1048
|
| { op: 'docs.update'; params: DocsUpdateParams; result: DocsUpdateResult }
|
|
1008
1049
|
| { op: 'docs.supersede'; params: DocsSupersedeParams; result: DocsSupersedeResult }
|
|
1050
|
+
| { op: 'docs.link-decision'; params: DocsDecisionLinkParams; result: DocsDecisionLinkResult }
|
|
1051
|
+
| { op: 'docs.unlink-decision'; params: DocsDecisionLinkParams; result: DocsDecisionLinkResult }
|
|
1009
1052
|
| { op: 'docs.doctor'; params: DocsDoctorParams; result: DocsDoctorResult };
|
|
1010
1053
|
|
|
1011
1054
|
/**
|
|
@@ -1024,4 +1067,6 @@ export type DocsOp =
|
|
|
1024
1067
|
| 'docs.remove'
|
|
1025
1068
|
| 'docs.update'
|
|
1026
1069
|
| 'docs.supersede'
|
|
1070
|
+
| 'docs.link-decision'
|
|
1071
|
+
| 'docs.unlink-decision'
|
|
1027
1072
|
| 'docs.doctor';
|
package/src/release/plan.ts
CHANGED
|
@@ -379,6 +379,8 @@ export const ReleasePlanSchema = z
|
|
|
379
379
|
releaseKind: ReleaseKindSchema,
|
|
380
380
|
/** Explicit hooks-v1 stable promotion; ordinary and hotfix releases are exempt. */
|
|
381
381
|
hooksV1Promotion: z.boolean().optional(),
|
|
382
|
+
/** Audited reason for shipping a source change that opens the hooks-v1 gate without the promotion (T13555). */
|
|
383
|
+
hooksV1Waiver: NonEmptyString.optional(),
|
|
382
384
|
/** ISO-8601 timestamp the plan was written. */
|
|
383
385
|
createdAt: Iso8601,
|
|
384
386
|
/** Identifier of the actor that wrote the plan (agent name or operator). */
|
package/src/task.ts
CHANGED
|
@@ -344,6 +344,10 @@ export type EvidenceAtom =
|
|
|
344
344
|
treeHash?: string;
|
|
345
345
|
/** Tracked `evidence.runtimePaths` files the tree hash left out (T13554). */
|
|
346
346
|
runtimeExcluded?: string[];
|
|
347
|
+
/** Changed code paths this receipt's roots leave uncovered; judged with its kind's other receipts (T13580). */
|
|
348
|
+
uncovered?: string[];
|
|
349
|
+
/** Dependent packages this receipt's roots leave uncovered (T13580). */
|
|
350
|
+
uncoveredPackages?: string[];
|
|
347
351
|
}
|
|
348
352
|
| {
|
|
349
353
|
kind: 'tool';
|