@cleocode/contracts 2026.5.28 → 2026.5.29

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/src/graph.ts CHANGED
@@ -158,6 +158,52 @@ export interface GraphNode {
158
158
  isExternal?: boolean;
159
159
  }
160
160
 
161
+ // ---------------------------------------------------------------------------
162
+ // Confidence label
163
+ // ---------------------------------------------------------------------------
164
+
165
+ /**
166
+ * Three-state confidence label for extracted edges.
167
+ *
168
+ * Complements the numeric `confidence` field with a categorical classification
169
+ * that maps to the pipeline's resolution tiers:
170
+ *
171
+ * - **`EXTRACTED`** (Tier 1): Statically verifiable from the AST — the
172
+ * relationship is directly present in source. Covers `defines`, `imports`,
173
+ * structural containment (`has_method`, `has_property`), and same-file
174
+ * `calls` / `extends` / `implements`. Numeric confidence ≥ 0.90.
175
+ *
176
+ * - **`INFERRED`** (Tier 2a): Resolved through import-scoped analysis — the
177
+ * target is reachable via a known import but requires cross-file name
178
+ * resolution. Covers `accesses`, cross-file `calls`, and cross-file
179
+ * `extends` / `implements`. Numeric confidence in range 0.80 – 0.89.
180
+ *
181
+ * - **`AMBIGUOUS`** (Tier 3): Global fallback resolution — the target was
182
+ * found by scanning the entire repository index with no direct import
183
+ * path. Multiple candidates may exist. Numeric confidence < 0.80.
184
+ *
185
+ * @since T1862
186
+ */
187
+ export type GraphEdgeConfidenceLabel = 'EXTRACTED' | 'INFERRED' | 'AMBIGUOUS';
188
+
189
+ /**
190
+ * Map a numeric confidence value to a {@link GraphEdgeConfidenceLabel}.
191
+ *
192
+ * Thresholds align with the pipeline resolution tiers defined in
193
+ * `resolution-context.ts`:
194
+ * - ≥ 0.90 → `EXTRACTED` (same-file 0.95, import-scoped 0.90, defines 1.0)
195
+ * - 0.80 – 0.89 → `INFERRED` (accesses 0.80, heritage import-scoped 0.85)
196
+ * - < 0.80 → `AMBIGUOUS` (global 0.50, speculative)
197
+ *
198
+ * @param confidence - Numeric confidence in range [0.0, 1.0]
199
+ * @returns The corresponding three-state label
200
+ */
201
+ export function confidenceLabelFromNumeric(confidence: number): GraphEdgeConfidenceLabel {
202
+ if (confidence >= 0.9) return 'EXTRACTED';
203
+ if (confidence >= 0.8) return 'INFERRED';
204
+ return 'AMBIGUOUS';
205
+ }
206
+
161
207
  // ---------------------------------------------------------------------------
162
208
  // Relation interface
163
209
  // ---------------------------------------------------------------------------
@@ -168,6 +214,11 @@ export interface GraphNode {
168
214
  * The `source` and `target` fields reference node IDs (see {@link GraphNode.id}).
169
215
  * Confidence reflects how certain the extractor is about this relationship,
170
216
  * from 0.0 (speculative) to 1.0 (statically verified).
217
+ *
218
+ * The `confidenceLabel` field provides a categorical three-state classification
219
+ * (see {@link GraphEdgeConfidenceLabel}) derived from the numeric `confidence`.
220
+ * Both fields are kept for backward compatibility: existing consumers that read
221
+ * the numeric field are unaffected; new consumers can use the label directly.
171
222
  */
172
223
  export interface GraphRelation {
173
224
  /** ID of the originating node. */
@@ -186,6 +237,15 @@ export interface GraphRelation {
186
237
  * - `accesses`: 0.8 (field read/write, may be indirect)
187
238
  */
188
239
  confidence: number;
240
+ /**
241
+ * Three-state categorical label derived from the numeric `confidence` tier.
242
+ *
243
+ * Optional for backward compatibility with callers that construct
244
+ * `GraphRelation` objects directly. Pipeline code SHOULD populate this
245
+ * field. See {@link GraphEdgeConfidenceLabel} and
246
+ * {@link confidenceLabelFromNumeric} for values and thresholds.
247
+ */
248
+ confidenceLabel?: GraphEdgeConfidenceLabel;
189
249
  /** Human-readable note explaining why this relation was emitted. */
190
250
  reason?: string;
191
251
  }
package/src/index.ts CHANGED
@@ -212,6 +212,8 @@ export type {
212
212
  ConfigSource,
213
213
  DaemonLLMConfig,
214
214
  DateFormat,
215
+ DecisionsConfig,
216
+ DepsRequiredAt,
215
217
  EnforcementProfile,
216
218
  HierarchyConfig,
217
219
  LifecycleConfig,
@@ -257,6 +259,7 @@ export {
257
259
  ClassifierUnregisteredAgentError,
258
260
  createErrorResult,
259
261
  createSuccessResult,
262
+ DecisionValidatorFailedError,
260
263
  formatError,
261
264
  getErrorMessage,
262
265
  isErrorResult,
@@ -338,9 +341,10 @@ export {
338
341
  AGENT_TYPES,
339
342
  BRAIN_OBSERVATION_TYPES,
340
343
  } from './facade.js';
341
- // === Graph Intelligence Types (T512, T529) ===
344
+ // === Graph Intelligence Types (T512, T529, T1862) ===
342
345
  export type {
343
346
  CommunityNode,
347
+ GraphEdgeConfidenceLabel,
344
348
  GraphNode,
345
349
  GraphNodeKind,
346
350
  GraphRelation,
@@ -350,6 +354,7 @@ export type {
350
354
  ProcessNode,
351
355
  SymbolIndex,
352
356
  } from './graph.js';
357
+ export { confidenceLabelFromNumeric } from './graph.js';
353
358
  export type { AdapterHookProvider } from './hooks.js';
354
359
  export type { AdapterInstallProvider, InstallOptions, InstallResult } from './install.js';
355
360
  export type {
@@ -830,6 +835,9 @@ export type {
830
835
  } from './operations/session.js';
831
836
  // === Task Operation Types (T1425 — typed-dispatch migration) ===
832
837
  export type {
838
+ DepGraphIssue,
839
+ DepsTreeEdge,
840
+ DepsTreeNode,
833
841
  TasksAddParams,
834
842
  TasksAddResult,
835
843
  TasksAnalyzeQueryParams,
@@ -852,6 +860,11 @@ export type {
852
860
  TasksDeleteQueryResult,
853
861
  TasksDependsParams,
854
862
  TasksDependsResult,
863
+ // T1857 — dep-graph validation + tree rendering (T1855 guardrails)
864
+ TasksDepsTreeParams,
865
+ TasksDepsTreeResult,
866
+ TasksDepsValidateParams,
867
+ TasksDepsValidateResult,
855
868
  TasksFindParams,
856
869
  TasksFindResult,
857
870
  TasksHistoryParams,
@@ -1035,6 +1048,8 @@ export type {
1035
1048
  TaskRefPriority,
1036
1049
  TaskSummary,
1037
1050
  } from './results.js';
1051
+ // === SDK Tool Contract (Category B harness-agnostic SDK utilities — T1768 / ADR-064) ===
1052
+ export type { SdkTool, SdkToolIdentity } from './sdk-tool.js';
1038
1053
  // === Sentient Tier-2 Types (T1008) ===
1039
1054
  export type {
1040
1055
  ProposalCandidate,
@@ -247,6 +247,16 @@ export interface MemoryDecisionFindParams {
247
247
  taskId?: string;
248
248
  /** Max results. */
249
249
  limit?: number;
250
+ /**
251
+ * T1830: when true, include AGT-* agent dispatch rows in results.
252
+ *
253
+ * By default `decision-find` excludes `decision_category = 'agent_dispatch'`
254
+ * rows so that architectural decisions are not buried by execution noise.
255
+ * Set to true to surface agent execution history.
256
+ *
257
+ * @default false
258
+ */
259
+ includeAgentDispatch?: boolean;
250
260
  }
251
261
  /** A single decision entry returned by the API. */
252
262
  export interface MemoryDecisionEntry {
@@ -317,6 +327,16 @@ export interface MemoryDecisionEntry {
317
327
  * `undefined` / `null` when the decision has never been validated.
318
328
  */
319
329
  validatorRunAt?: number | null;
330
+ /**
331
+ * Decision category (T1830).
332
+ *
333
+ * - `'architectural'` — Architectural or technical decision (default).
334
+ * - `'agent_dispatch'` — AGT-* agent execution dispatch outcome.
335
+ * - `'other'` — Miscellaneous.
336
+ *
337
+ * Defaults to `'architectural'` for rows written before T1830.
338
+ */
339
+ decisionCategory?: 'architectural' | 'agent_dispatch' | 'other';
320
340
  }
321
341
  /** Result of `memory.decision.find`. */
322
342
  export type MemoryDecisionFindResult = MemoryDecisionEntry[];
@@ -237,6 +237,114 @@ export interface TasksAnalyzeQueryParams {
237
237
  */
238
238
  export type TasksAnalyzeQueryResult = TaskAnalysisResult & { tierLimit: number };
239
239
 
240
+ // tasks.deps.validate
241
+ /**
242
+ * Parameters for `tasks.deps.validate`.
243
+ *
244
+ * @task T1857
245
+ * @epic T1855
246
+ */
247
+ export interface TasksDepsValidateParams {
248
+ /** Scope to direct children of this epic (optional). */
249
+ epicId?: string;
250
+ /** Which tasks to include: all, open, or critical-priority only. @defaultValue 'all' */
251
+ scope?: 'all' | 'open' | 'critical';
252
+ }
253
+
254
+ /**
255
+ * A single dep-graph issue found by `tasks.deps.validate`.
256
+ *
257
+ * @task T1857
258
+ * @epic T1855
259
+ */
260
+ export interface DepGraphIssue {
261
+ /** Machine-readable issue code. */
262
+ code: 'E_ORPHAN' | 'E_CIRCULAR' | 'E_CROSS_EPIC_GAP' | 'E_STALE_DEP' | 'E_MISSING_REF';
263
+ /** The task ID where the issue originates. */
264
+ taskId: string;
265
+ /** Human-readable description. */
266
+ message: string;
267
+ /** Related task IDs (dep IDs, cycle members, etc.). */
268
+ relatedIds?: string[];
269
+ /** Source epic ID (for E_CROSS_EPIC_GAP issues). */
270
+ epicA?: string;
271
+ /** Target epic ID (for E_CROSS_EPIC_GAP issues). */
272
+ epicB?: string;
273
+ }
274
+
275
+ /**
276
+ * Result of `tasks.deps.validate`.
277
+ *
278
+ * @task T1857
279
+ * @epic T1855
280
+ */
281
+ export interface TasksDepsValidateResult {
282
+ /** True when no issues were found. */
283
+ valid: boolean;
284
+ /** All detected issues. Empty when valid. */
285
+ issues: DepGraphIssue[];
286
+ /** Human-readable summary line. */
287
+ summary: string;
288
+ }
289
+
290
+ // tasks.deps.tree
291
+ /**
292
+ * Parameters for `tasks.deps.tree`.
293
+ *
294
+ * @task T1857
295
+ * @epic T1855
296
+ */
297
+ export interface TasksDepsTreeParams {
298
+ /** Epic ID to visualize (required). */
299
+ epicId: string;
300
+ /** Output format. @defaultValue 'text' */
301
+ format?: 'text' | 'mermaid' | 'json';
302
+ }
303
+
304
+ /** A node in the deps tree JSON output. */
305
+ export interface DepsTreeNode {
306
+ /** Task ID. */
307
+ id: string;
308
+ /** Task title. */
309
+ title: string;
310
+ /** Task status. */
311
+ status: string;
312
+ /** Direct dependency IDs. */
313
+ depends: string[];
314
+ }
315
+
316
+ /** An edge in the deps tree JSON output. */
317
+ export interface DepsTreeEdge {
318
+ /** Source task ID (dependency). */
319
+ from: string;
320
+ /** Target task ID (dependent). */
321
+ to: string;
322
+ }
323
+
324
+ /**
325
+ * Result of `tasks.deps.tree`.
326
+ *
327
+ * @task T1857
328
+ * @epic T1855
329
+ */
330
+ export interface TasksDepsTreeResult {
331
+ /** The epic ID the tree is scoped to. */
332
+ epicId: string;
333
+ /** Output format that was rendered. */
334
+ format: 'text' | 'mermaid' | 'json';
335
+ /**
336
+ * Rendered text or Mermaid output (when format is 'text' or 'mermaid').
337
+ * Null when format is 'json'.
338
+ */
339
+ rendered: string | null;
340
+ /** Structured node list (always populated). */
341
+ nodes: DepsTreeNode[];
342
+ /** Directed edges in the graph (dependency → dependent). */
343
+ edges: DepsTreeEdge[];
344
+ /** Task IDs on the critical path (longest dep chain), or empty if none. */
345
+ criticalPath: string[];
346
+ }
347
+
240
348
  // tasks.impact
241
349
  export interface TasksImpactParams {
242
350
  change: string;
@@ -756,6 +864,8 @@ export type TasksOps = {
756
864
  readonly tree: readonly [TasksTreeDispatchParams, TasksTreeDispatchResult];
757
865
  readonly blockers: readonly [TasksBlockersQueryParams, TasksBlockersQueryResult];
758
866
  readonly depends: readonly [TasksDependsParams, TasksDependsResult];
867
+ readonly 'deps.validate': readonly [TasksDepsValidateParams, TasksDepsValidateResult];
868
+ readonly 'deps.tree': readonly [TasksDepsTreeParams, TasksDepsTreeResult];
759
869
  readonly analyze: readonly [TasksAnalyzeQueryParams, TasksAnalyzeQueryResult];
760
870
  readonly impact: readonly [TasksImpactParams, TasksImpactResult];
761
871
  readonly next: readonly [TasksNextQueryParams, TasksNextQueryResult];
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SdkTool contract — Category B harness-agnostic SDK utility.
3
+ *
4
+ * An SDK Tool is a harness-agnostic utility that every adapter, harness, and
5
+ * orchestration pathway MUST consume. SDK Tools:
6
+ *
7
+ * - MUST have zero harness-specific imports.
8
+ * - MUST expose a typed contract via `packages/contracts/src/`.
9
+ * - MUST be consumed by ALL adapters that invoke the relevant operation.
10
+ * - MUST be pure or side-effect-isolated (testable without running an agent).
11
+ * - SHOULD be deterministic given identical inputs.
12
+ *
13
+ * Canonical location: `packages/core/src/tools/sdk/`
14
+ *
15
+ * Distinct from Category A (Agent Tool — LLM-callable primitive registered in
16
+ * AgentToolRegistry) and Category C (Domain Utility — internal to a specific
17
+ * domain, not required cross-harness).
18
+ *
19
+ * @arch See ADR-064 (SDK Tools taxonomy: Category A Agent Tool vs Category B SDK Tool)
20
+ * @task T1815
21
+ * @epic T1768
22
+ */
23
+
24
+ /**
25
+ * Identity metadata shared by all SDK Tools.
26
+ *
27
+ * Each SDK Tool MUST declare a stable `name` (used in diagnostics and audits),
28
+ * a human-readable `description`, and the semver-compatible `version` of the
29
+ * contract it exposes.
30
+ */
31
+ export interface SdkToolIdentity {
32
+ /** Stable machine-readable identifier (kebab-case, e.g. `worktree-isolation`). */
33
+ name: string;
34
+ /** Human-readable description of the tool's purpose. */
35
+ description: string;
36
+ /**
37
+ * Contract version in `MAJOR.MINOR.PATCH` form.
38
+ *
39
+ * Increment MAJOR when the interface shape changes in a breaking way.
40
+ * Callers may guard on this field to detect incompatible contract upgrades.
41
+ */
42
+ version: string;
43
+ }
44
+
45
+ /**
46
+ * Base interface for all SDK Tools.
47
+ *
48
+ * Implementors extend this with operation-specific methods. The `identity`
49
+ * field is the only required member — it gives diagnostics and audit layers
50
+ * a stable handle on which SDK Tool is in play.
51
+ *
52
+ * @arch See ADR-064
53
+ * @task T1815
54
+ */
55
+ export interface SdkTool {
56
+ /** Static identity metadata for this SDK Tool. */
57
+ readonly identity: SdkToolIdentity;
58
+ }