@cleocode/contracts 2026.5.113 → 2026.5.120
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/__tests__/meta-tokens.test.d.ts +16 -0
- package/dist/__tests__/meta-tokens.test.d.ts.map +1 -0
- package/dist/__tests__/meta-tokens.test.js +99 -0
- package/dist/__tests__/meta-tokens.test.js.map +1 -0
- package/dist/boundary.js +3 -3
- package/dist/boundary.js.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +119 -0
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/__tests__/tasks-input-contracts.test.d.ts +18 -0
- package/dist/operations/__tests__/tasks-input-contracts.test.d.ts.map +1 -0
- package/dist/operations/__tests__/tasks-input-contracts.test.js +80 -0
- package/dist/operations/__tests__/tasks-input-contracts.test.js.map +1 -0
- package/dist/operations/docs.d.ts +166 -8
- package/dist/operations/docs.d.ts.map +1 -1
- package/dist/operations/docs.js +9 -7
- package/dist/operations/docs.js.map +1 -1
- package/dist/operations/tasks.d.ts +109 -0
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/operations/tasks.js +237 -1
- package/dist/operations/tasks.js.map +1 -1
- package/dist/task-record.d.ts +7 -0
- package/dist/task-record.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/meta-tokens.test.ts +107 -0
- package/src/boundary.ts +3 -3
- package/src/dispatch/operations-registry.ts +124 -0
- package/src/index.ts +12 -0
- package/src/operations/__tests__/tasks-input-contracts.test.ts +106 -0
- package/src/operations/docs.ts +187 -9
- package/src/operations/tasks.ts +321 -0
- package/src/task-record.ts +7 -0
package/src/operations/tasks.ts
CHANGED
|
@@ -36,6 +36,7 @@ import type {
|
|
|
36
36
|
TaskView,
|
|
37
37
|
} from '../tasks.js';
|
|
38
38
|
import type { DocsType } from './docs.js';
|
|
39
|
+
import type { JsonSchema, OperationInputContract } from './input-contract.js';
|
|
39
40
|
|
|
40
41
|
export type { TaskPriority, TaskStatus };
|
|
41
42
|
|
|
@@ -124,6 +125,19 @@ export interface TasksFindParams {
|
|
|
124
125
|
* @task T9072
|
|
125
126
|
*/
|
|
126
127
|
kind?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Unified urgency surface (T9905).
|
|
130
|
+
*
|
|
131
|
+
* When `true`, the predicate is
|
|
132
|
+
*
|
|
133
|
+
* `priority IN ('critical','high') OR severity IN ('P0','P1')`
|
|
134
|
+
*
|
|
135
|
+
* combining the two orthogonal urgency axes (priority + severity) into a
|
|
136
|
+
* single filter. Composes with other filters via AND.
|
|
137
|
+
*
|
|
138
|
+
* @task T9905
|
|
139
|
+
*/
|
|
140
|
+
urgent?: boolean;
|
|
127
141
|
}
|
|
128
142
|
export type TasksFindResult = MinimalTask[];
|
|
129
143
|
|
|
@@ -1352,3 +1366,310 @@ export type TasksOps = {
|
|
|
1352
1366
|
/** T10121 — idempotent cron-safe auto-close repair (supersedes T10098 scope). */
|
|
1353
1367
|
readonly 'saga.reconcile': readonly [TasksSagaReconcileParams, TasksSagaReconcileResult];
|
|
1354
1368
|
};
|
|
1369
|
+
|
|
1370
|
+
// ---------------------------------------------------------------------------
|
|
1371
|
+
// OperationInputContract schemas (T9917 / Epic T9903 / Saga T9855)
|
|
1372
|
+
// ---------------------------------------------------------------------------
|
|
1373
|
+
//
|
|
1374
|
+
// JSON Schema documents that describe the accepted input shape for each
|
|
1375
|
+
// tasks.* mutate operation. The `tasks.add`, `tasks.add-batch`, and
|
|
1376
|
+
// `tasks.update` schemas back the schema-first `mutate(operation, input)`
|
|
1377
|
+
// DX surface introduced by T9914 and validated by T9915.
|
|
1378
|
+
//
|
|
1379
|
+
// Schemas live in `contracts/` because the CLI (`packages/cleo/`) and the
|
|
1380
|
+
// CORE registry (`packages/core/`) both depend on them — contracts is the
|
|
1381
|
+
// leaf package both packages already import from, so colocation avoids a
|
|
1382
|
+
// fan-out violation (T10074).
|
|
1383
|
+
//
|
|
1384
|
+
// Each schema sets `additionalProperties: false` to reject typo'd flags
|
|
1385
|
+
// outright instead of silently dropping them on the floor at the dispatch
|
|
1386
|
+
// boundary.
|
|
1387
|
+
// ---------------------------------------------------------------------------
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Per-task entry inside a `tasks.add-batch` payload.
|
|
1391
|
+
*
|
|
1392
|
+
* Mirrors the shape of {@link TasksAddBatchParams.tasks | TasksAddBatchParams.tasks[]}
|
|
1393
|
+
* exactly — every field is identical to a `tasks.add` spec EXCEPT `dryRun`,
|
|
1394
|
+
* which is hoisted to the batch level so a single dispatch can preview the
|
|
1395
|
+
* whole batch atomically.
|
|
1396
|
+
*
|
|
1397
|
+
* @task T9917
|
|
1398
|
+
*/
|
|
1399
|
+
export interface TasksAddBatchEntry {
|
|
1400
|
+
/** Task title (3–500 characters). Required. */
|
|
1401
|
+
title: string;
|
|
1402
|
+
/** Detailed task description (must differ meaningfully from title). */
|
|
1403
|
+
description?: string;
|
|
1404
|
+
/** Parent task ID (makes this task a subtask). */
|
|
1405
|
+
parent?: string;
|
|
1406
|
+
/** Comma-separated dependency task IDs. */
|
|
1407
|
+
depends?: string[];
|
|
1408
|
+
/** Task priority (low | medium | high | critical). */
|
|
1409
|
+
priority?: string;
|
|
1410
|
+
/** Lowercase alphanumeric + hyphens + periods labels. */
|
|
1411
|
+
labels?: string[];
|
|
1412
|
+
/** Task type (saga | epic | task | subtask). */
|
|
1413
|
+
type?: TaskType; // SSoT-EXEMPT:kind≠type — same axis split as TasksAddBatchParams (T944) // ssot-exempt-ok: mirrors parent type
|
|
1414
|
+
/** Pipe-separated acceptance criteria, normalized to string[]. */
|
|
1415
|
+
acceptance?: string[];
|
|
1416
|
+
/** Phase slug to assign the task to. */
|
|
1417
|
+
phase?: string;
|
|
1418
|
+
/** Scope size estimate (small | medium | large). */
|
|
1419
|
+
size?: string;
|
|
1420
|
+
/** Initial note entry for the task. */
|
|
1421
|
+
notes?: string;
|
|
1422
|
+
/** Files touched by the task (relative paths). */
|
|
1423
|
+
files?: string[];
|
|
1424
|
+
/** Task kind / intent axis (work | research | experiment | bug | spike | release). */
|
|
1425
|
+
kind?: string;
|
|
1426
|
+
/** Task scope / granularity axis (project | feature | unit). */
|
|
1427
|
+
scope?: string;
|
|
1428
|
+
/** Severity level (P0 | P1 | P2 | P3). */
|
|
1429
|
+
severity?: string;
|
|
1430
|
+
/** Bypass BRAIN duplicate-task rejection (audited). */
|
|
1431
|
+
forceDuplicate?: boolean;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* JSON Schema draft-07 document describing the accepted input shape for
|
|
1436
|
+
* the `tasks.add` mutate operation.
|
|
1437
|
+
*
|
|
1438
|
+
* Mirrors {@link TasksAddParams} field-for-field. Set
|
|
1439
|
+
* `additionalProperties: false` so a typo'd flag fails fast with a typed
|
|
1440
|
+
* `E_VAL_ADDITIONALPROPERTIES` error instead of being silently dropped.
|
|
1441
|
+
*
|
|
1442
|
+
* @task T9917
|
|
1443
|
+
*/
|
|
1444
|
+
export const TASKS_ADD_INPUT_SCHEMA: JsonSchema = {
|
|
1445
|
+
type: 'object',
|
|
1446
|
+
required: ['title'],
|
|
1447
|
+
additionalProperties: false,
|
|
1448
|
+
properties: {
|
|
1449
|
+
title: { type: 'string', minLength: 1, maxLength: 500 },
|
|
1450
|
+
description: { type: 'string' },
|
|
1451
|
+
parent: { type: 'string' },
|
|
1452
|
+
depends: { type: 'array', items: { type: 'string' } },
|
|
1453
|
+
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
|
|
1454
|
+
labels: { type: 'array', items: { type: 'string' } },
|
|
1455
|
+
type: { type: 'string', enum: ['saga', 'epic', 'task', 'subtask'] },
|
|
1456
|
+
acceptance: { type: 'array', items: { type: 'string' } },
|
|
1457
|
+
phase: { type: 'string' },
|
|
1458
|
+
size: { type: 'string', enum: ['small', 'medium', 'large'] },
|
|
1459
|
+
notes: { type: 'string' },
|
|
1460
|
+
files: { type: 'array', items: { type: 'string' } },
|
|
1461
|
+
dryRun: { type: 'boolean' },
|
|
1462
|
+
parentSearch: { type: 'string' },
|
|
1463
|
+
kind: {
|
|
1464
|
+
type: 'string',
|
|
1465
|
+
enum: ['work', 'research', 'experiment', 'bug', 'spike', 'release'],
|
|
1466
|
+
},
|
|
1467
|
+
scope: { type: 'string', enum: ['project', 'feature', 'unit'] },
|
|
1468
|
+
severity: { type: 'string', enum: ['P0', 'P1', 'P2', 'P3'] },
|
|
1469
|
+
forceDuplicate: { type: 'boolean' },
|
|
1470
|
+
},
|
|
1471
|
+
};
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* Schema-first input contract for `tasks.add`.
|
|
1475
|
+
*
|
|
1476
|
+
* @task T9917
|
|
1477
|
+
*/
|
|
1478
|
+
export const tasksAddInputContract: OperationInputContract<TasksAddParams> = {
|
|
1479
|
+
operation: 'tasks.add',
|
|
1480
|
+
schema: TASKS_ADD_INPUT_SCHEMA,
|
|
1481
|
+
examples: [
|
|
1482
|
+
{
|
|
1483
|
+
name: 'minimal',
|
|
1484
|
+
value: { title: 'Ship E7-MUTATE-DX-SCHEMA-FIRST' },
|
|
1485
|
+
description: 'Smallest valid input — title is the only required field.',
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
name: 'subtask-with-acceptance',
|
|
1489
|
+
value: {
|
|
1490
|
+
title: 'Wire validator into add command',
|
|
1491
|
+
parent: 'T9903',
|
|
1492
|
+
priority: 'high',
|
|
1493
|
+
acceptance: ['validator runs before dispatch', 'errors surface in envelope'],
|
|
1494
|
+
},
|
|
1495
|
+
},
|
|
1496
|
+
],
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
/**
|
|
1500
|
+
* JSON Schema draft-07 document describing the accepted input shape for
|
|
1501
|
+
* the `tasks.add-batch` mutate operation.
|
|
1502
|
+
*
|
|
1503
|
+
* Wraps N `tasks.add` specs in a single atomic transaction. `dryRun` is
|
|
1504
|
+
* hoisted to the batch level (single rollback unit), so the per-entry
|
|
1505
|
+
* schema OMITS `dryRun` deliberately.
|
|
1506
|
+
*
|
|
1507
|
+
* @task T9917
|
|
1508
|
+
*/
|
|
1509
|
+
export const TASKS_ADD_BATCH_INPUT_SCHEMA: JsonSchema = {
|
|
1510
|
+
type: 'object',
|
|
1511
|
+
required: ['tasks'],
|
|
1512
|
+
additionalProperties: false,
|
|
1513
|
+
properties: {
|
|
1514
|
+
tasks: {
|
|
1515
|
+
type: 'array',
|
|
1516
|
+
minItems: 1,
|
|
1517
|
+
items: {
|
|
1518
|
+
type: 'object',
|
|
1519
|
+
required: ['title'],
|
|
1520
|
+
additionalProperties: false,
|
|
1521
|
+
properties: {
|
|
1522
|
+
title: { type: 'string', minLength: 1, maxLength: 500 },
|
|
1523
|
+
description: { type: 'string' },
|
|
1524
|
+
parent: { type: 'string' },
|
|
1525
|
+
depends: { type: 'array', items: { type: 'string' } },
|
|
1526
|
+
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
|
|
1527
|
+
labels: { type: 'array', items: { type: 'string' } },
|
|
1528
|
+
type: { type: 'string', enum: ['saga', 'epic', 'task', 'subtask'] },
|
|
1529
|
+
acceptance: { type: 'array', items: { type: 'string' } },
|
|
1530
|
+
phase: { type: 'string' },
|
|
1531
|
+
size: { type: 'string', enum: ['small', 'medium', 'large'] },
|
|
1532
|
+
notes: { type: 'string' },
|
|
1533
|
+
files: { type: 'array', items: { type: 'string' } },
|
|
1534
|
+
kind: {
|
|
1535
|
+
type: 'string',
|
|
1536
|
+
enum: ['work', 'research', 'experiment', 'bug', 'spike', 'release'],
|
|
1537
|
+
},
|
|
1538
|
+
scope: { type: 'string', enum: ['project', 'feature', 'unit'] },
|
|
1539
|
+
severity: { type: 'string', enum: ['P0', 'P1', 'P2', 'P3'] },
|
|
1540
|
+
forceDuplicate: { type: 'boolean' },
|
|
1541
|
+
},
|
|
1542
|
+
},
|
|
1543
|
+
},
|
|
1544
|
+
defaultParent: { type: 'string' },
|
|
1545
|
+
dryRun: { type: 'boolean' },
|
|
1546
|
+
},
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
/**
|
|
1550
|
+
* Schema-first input contract for `tasks.add-batch`.
|
|
1551
|
+
*
|
|
1552
|
+
* @task T9917
|
|
1553
|
+
*/
|
|
1554
|
+
export const tasksAddBatchInputContract: OperationInputContract<TasksAddBatchParams> = {
|
|
1555
|
+
operation: 'tasks.add-batch',
|
|
1556
|
+
schema: TASKS_ADD_BATCH_INPUT_SCHEMA,
|
|
1557
|
+
examples: [
|
|
1558
|
+
{
|
|
1559
|
+
name: 'two-tasks',
|
|
1560
|
+
value: {
|
|
1561
|
+
tasks: [{ title: 'first task' }, { title: 'second task' }],
|
|
1562
|
+
},
|
|
1563
|
+
description: 'Atomic insert of two tasks under no shared parent.',
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
name: 'with-default-parent',
|
|
1567
|
+
value: {
|
|
1568
|
+
defaultParent: 'T9903',
|
|
1569
|
+
tasks: [{ title: 'a' }, { title: 'b', parent: 'T9914' }],
|
|
1570
|
+
},
|
|
1571
|
+
description: 'defaultParent applies to entries without an explicit parent.',
|
|
1572
|
+
},
|
|
1573
|
+
],
|
|
1574
|
+
};
|
|
1575
|
+
|
|
1576
|
+
/**
|
|
1577
|
+
* JSON Schema draft-07 document describing the accepted input shape for
|
|
1578
|
+
* the `tasks.update` mutate operation.
|
|
1579
|
+
*
|
|
1580
|
+
* Mirrors {@link TasksUpdateQueryParams}. `taskId` is REQUIRED. All other
|
|
1581
|
+
* fields are optional — `tasks.update` is a partial update; only the
|
|
1582
|
+
* fields supplied are mutated.
|
|
1583
|
+
*
|
|
1584
|
+
* @task T9917
|
|
1585
|
+
*/
|
|
1586
|
+
export const TASKS_UPDATE_INPUT_SCHEMA: JsonSchema = {
|
|
1587
|
+
type: 'object',
|
|
1588
|
+
required: ['taskId'],
|
|
1589
|
+
additionalProperties: false,
|
|
1590
|
+
properties: {
|
|
1591
|
+
taskId: { type: 'string', minLength: 1 },
|
|
1592
|
+
title: { type: 'string', minLength: 1, maxLength: 500 },
|
|
1593
|
+
description: { type: 'string' },
|
|
1594
|
+
status: {
|
|
1595
|
+
type: 'string',
|
|
1596
|
+
enum: ['pending', 'active', 'blocked', 'done', 'cancelled'],
|
|
1597
|
+
},
|
|
1598
|
+
priority: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
|
|
1599
|
+
notes: { type: 'string' },
|
|
1600
|
+
labels: { type: 'array', items: { type: 'string' } },
|
|
1601
|
+
addLabels: { type: 'array', items: { type: 'string' } },
|
|
1602
|
+
removeLabels: { type: 'array', items: { type: 'string' } },
|
|
1603
|
+
depends: { type: 'array', items: { type: 'string' } },
|
|
1604
|
+
addDepends: { type: 'array', items: { type: 'string' } },
|
|
1605
|
+
removeDepends: { type: 'array', items: { type: 'string' } },
|
|
1606
|
+
acceptance: { type: 'array', items: { type: 'string' } },
|
|
1607
|
+
parent: { type: ['string', 'null'] },
|
|
1608
|
+
type: { type: 'string', enum: ['saga', 'epic', 'task', 'subtask'] },
|
|
1609
|
+
size: { type: 'string', enum: ['small', 'medium', 'large'] },
|
|
1610
|
+
files: { type: 'array', items: { type: 'string' } },
|
|
1611
|
+
addFiles: { type: 'array', items: { type: 'string' } },
|
|
1612
|
+
removeFiles: { type: 'array', items: { type: 'string' } },
|
|
1613
|
+
pipelineStage: { type: 'string' },
|
|
1614
|
+
kind: {
|
|
1615
|
+
type: 'string',
|
|
1616
|
+
enum: ['work', 'research', 'experiment', 'bug', 'spike', 'release'],
|
|
1617
|
+
},
|
|
1618
|
+
scope: { type: 'string', enum: ['project', 'feature', 'unit'] },
|
|
1619
|
+
severity: { type: 'string', enum: ['P0', 'P1', 'P2', 'P3'] },
|
|
1620
|
+
reason: { type: 'string' },
|
|
1621
|
+
dependsWaiver: { type: 'string' },
|
|
1622
|
+
clearBlockedBy: { type: 'boolean' },
|
|
1623
|
+
relates: {
|
|
1624
|
+
type: 'array',
|
|
1625
|
+
items: {
|
|
1626
|
+
type: 'object',
|
|
1627
|
+
required: ['taskId', 'type'],
|
|
1628
|
+
additionalProperties: false,
|
|
1629
|
+
properties: {
|
|
1630
|
+
taskId: { type: 'string', minLength: 1 },
|
|
1631
|
+
type: { type: 'string', minLength: 1 },
|
|
1632
|
+
reason: { type: 'string' },
|
|
1633
|
+
},
|
|
1634
|
+
},
|
|
1635
|
+
},
|
|
1636
|
+
addRelates: {
|
|
1637
|
+
type: 'array',
|
|
1638
|
+
items: {
|
|
1639
|
+
type: 'object',
|
|
1640
|
+
required: ['taskId', 'type'],
|
|
1641
|
+
additionalProperties: false,
|
|
1642
|
+
properties: {
|
|
1643
|
+
taskId: { type: 'string', minLength: 1 },
|
|
1644
|
+
type: { type: 'string', minLength: 1 },
|
|
1645
|
+
reason: { type: 'string' },
|
|
1646
|
+
},
|
|
1647
|
+
},
|
|
1648
|
+
},
|
|
1649
|
+
removeRelates: { type: 'array', items: { type: 'string' } },
|
|
1650
|
+
},
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* Schema-first input contract for `tasks.update`.
|
|
1655
|
+
*
|
|
1656
|
+
* @task T9917
|
|
1657
|
+
*/
|
|
1658
|
+
export const tasksUpdateInputContract: OperationInputContract<TasksUpdateQueryParams> = {
|
|
1659
|
+
operation: 'tasks.update',
|
|
1660
|
+
schema: TASKS_UPDATE_INPUT_SCHEMA,
|
|
1661
|
+
examples: [
|
|
1662
|
+
{
|
|
1663
|
+
name: 'set-status',
|
|
1664
|
+
value: { taskId: 'T9917', status: 'active' },
|
|
1665
|
+
description: 'Transition status to active.',
|
|
1666
|
+
},
|
|
1667
|
+
{
|
|
1668
|
+
name: 'add-labels-incrementally',
|
|
1669
|
+
value: {
|
|
1670
|
+
taskId: 'T9917',
|
|
1671
|
+
addLabels: ['saga.t9855', 'epic.t9903'],
|
|
1672
|
+
},
|
|
1673
|
+
},
|
|
1674
|
+
],
|
|
1675
|
+
};
|
package/src/task-record.ts
CHANGED
|
@@ -103,4 +103,11 @@ export interface MinimalTaskRecord {
|
|
|
103
103
|
type?: string;
|
|
104
104
|
/** Scope size estimate — helps agents decide if decomposition is needed. @task T091 */
|
|
105
105
|
size?: string;
|
|
106
|
+
/**
|
|
107
|
+
* Bug severity axis — P0|P1|P2|P3 (string-widened). Surfaced so the unified
|
|
108
|
+
* urgency surface (`cleo find --urgent`) can identify P0/P1 rows without a
|
|
109
|
+
* follow-up `cleo show` per row.
|
|
110
|
+
* @task T9905
|
|
111
|
+
*/
|
|
112
|
+
severity?: string | null;
|
|
106
113
|
}
|