@adhd/backlog 1.0.5 → 1.0.6
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/CHANGELOG.md +53 -0
- package/README.md +194 -39
- package/api.d.ts +87 -0
- package/api.ir.json +1 -1
- package/citation.d.ts +176 -0
- package/envelope.d.ts +35 -1
- package/index.d.ts +23 -3
- package/index.js +106 -58
- package/index.mjs +11627 -7068
- package/ir-artifact.d.ts +7 -3
- package/lifecycle.d.ts +49 -0
- package/package.json +5 -5
- package/query/canonical.d.ts +16 -0
- package/query/card.d.ts +116 -4
- package/query/get.d.ts +8 -1
- package/query/index.d.ts +1 -0
- package/query/query.d.ts +20 -13
- package/query/redirect.d.ts +30 -0
- package/query/resolve.d.ts +48 -0
- package/query/similar-clusters.d.ts +8 -0
- package/query/similarity-signals.d.ts +47 -0
- package/query/spec-staleness.d.ts +21 -0
- package/query/types.d.ts +249 -34
- package/query/verdict-core.d.ts +21 -0
- package/query/verdict.d.ts +22 -0
- package/query/views/catalog.d.ts +47 -0
- package/query/views/registry.d.ts +27 -7
- package/query/views/report.d.ts +49 -0
- package/query/views/semantic.d.ts +28 -5
- package/query/views/stats.d.ts +38 -2
- package/readiness.d.ts +29 -0
- package/retry-policy.d.ts +44 -0
- package/serve.d.ts +1 -1
- package/server.d.ts +71 -3
- package/service-config.d.ts +109 -0
- package/service-errors.d.ts +51 -0
- package/skill/SKILL.md +688 -81
- package/store/catalog-invariant-guard.d.ts +4 -4
- package/vocabulary.d.ts +48 -0
- package/write/anchor-check.d.ts +139 -0
- package/write/attestation.d.ts +64 -0
- package/write/catalog-merge.d.ts +15 -8
- package/write/catalog.d.ts +63 -0
- package/write/citation-path.d.ts +31 -0
- package/write/citation.d.ts +157 -0
- package/write/create-issue.d.ts +143 -29
- package/write/errors.d.ts +159 -0
- package/write/gate.d.ts +67 -0
- package/write/merge-project.d.ts +54 -0
- package/write/obligation.d.ts +133 -0
- package/write/relate.d.ts +1 -1
- package/write/revision.d.ts +27 -0
- package/write/similarity-scan.d.ts +84 -0
- package/write/spec-revision.d.ts +131 -0
- package/write/spec-revision.reconcile.d.ts +48 -0
- package/write/transition.d.ts +13 -2
- package/write/tx.d.ts +21 -1
- package/write/update.d.ts +23 -1
package/query/types.d.ts
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* `IIssue*`/`IProject*` interfaces field-for-field — this file is the single
|
|
7
|
-
* place those interfaces are declared for the read layer; `get.ts`/`query.ts`/
|
|
8
|
-
* `registry.ts` all import from here rather than re-declaring their own
|
|
9
|
-
* copies, and the six sibling write verbs (`update`/`transition`/`claim`/
|
|
10
|
-
* `relate`/`move`/`delete`) should import {@link IIssueCard} /
|
|
11
|
-
* {@link IIssueField} from here too, rather than re-declaring a third copy
|
|
12
|
-
* alongside `create-issue.ts`'s own `IIssueCard` (see this module's own
|
|
13
|
-
* top-level doc comment in `index.ts` for the reconciliation note).
|
|
14
|
-
*/
|
|
1
|
+
import { CatalogKindName, ICatalogTerm, ICatalogView } from './views/catalog.js';
|
|
2
|
+
import { SpecFreshness } from './spec-staleness.js';
|
|
3
|
+
import { ICitationRecord } from '../citation.js';
|
|
4
|
+
import { IObligationAppliesTo, IObligationOverride, IObligationSeverity, IPredicate } from '../write/obligation.js';
|
|
5
|
+
|
|
15
6
|
/** Identity is the global `uid` (SPEC.md §6.1) — a single scalar, never a composite key. */
|
|
16
7
|
export type IssueUid = string;
|
|
17
8
|
/**
|
|
@@ -32,31 +23,25 @@ export type IssueUid = string;
|
|
|
32
23
|
* response) and is therefore NEVER included in the default card.
|
|
33
24
|
*/
|
|
34
25
|
export type IIssuePlainField = 'uid' | 'title' | 'kind' | 'status' | 'priority' | 'project' | 'component' | 'createdAt' | 'updatedAt' | 'assignee' | 'author' | 'closedAt' | 'gitContext';
|
|
35
|
-
export type IIssuePseudoField = 'body' | 'citations' | 'notes' | 'auditTrail' | 'blockers' | 'related' | '_score' | '_vector';
|
|
26
|
+
export type IIssuePseudoField = 'body' | 'citations' | 'notes' | 'auditTrail' | 'blockers' | 'related' | '_score' | '_vector' | 'blocksOut' | 'dependents' | 'partOf' | 'obligations' | 'verdict' | 'spec' | 'similar';
|
|
36
27
|
export type IIssueField = IIssuePlainField | IIssuePseudoField;
|
|
37
28
|
export declare const ISSUE_PLAIN_FIELDS: readonly IIssuePlainField[];
|
|
38
29
|
export declare const ISSUE_PSEUDO_FIELDS: readonly IIssuePseudoField[];
|
|
39
30
|
export declare function isKnownIssueField(name: string): name is IIssueField;
|
|
40
31
|
/** SPEC.md §6.5: "Default (`fields` omitted): the exact five-field terse card established by `DEFAULT_CARD_FIELDS`." */
|
|
41
32
|
export declare const DEFAULT_ISSUE_CARD_FIELDS: readonly IIssuePlainField[];
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
|
-
context?: string;
|
|
56
|
-
symbol?: string;
|
|
57
|
-
sha: string;
|
|
58
|
-
at: string;
|
|
59
|
-
}
|
|
33
|
+
/**
|
|
34
|
+
* A citation, projected for read — the ONE citation contract
|
|
35
|
+
* (`../citation.ts`'s `ICitationRecord`: `ICitation` plus the server-computed
|
|
36
|
+
* `uid`/`sha`/`at` and the persisted `target_type`) with no re-declaration
|
|
37
|
+
* here. `context` is the per-citation free-text prose (the contract's
|
|
38
|
+
* `context`, persisted on the node's `content` column); it is NOT the item's
|
|
39
|
+
* disclosure-contract git context, which is ITEM-level provenance on
|
|
40
|
+
* {@link IIssueCard.gitContext} and rendered once at the head of the block.
|
|
41
|
+
* `revision`, when present, names the git revision the target was resolved
|
|
42
|
+
* against (a revision-pinned citation).
|
|
43
|
+
*/
|
|
44
|
+
export type IIssueCitation = ICitationRecord;
|
|
60
45
|
export interface IIssueNote {
|
|
61
46
|
uid: string;
|
|
62
47
|
author: string;
|
|
@@ -78,6 +63,91 @@ export interface IIssueRef {
|
|
|
78
63
|
uid: string;
|
|
79
64
|
title: string;
|
|
80
65
|
status: string;
|
|
66
|
+
/**
|
|
67
|
+
* Which live relation produced this ref (C2 — structural legibility).
|
|
68
|
+
* ADDITIVE — existing consumers reading `uid`/`title`/`status` are
|
|
69
|
+
* unaffected. `related` now surfaces every live relation type: `relates_to`
|
|
70
|
+
* and `part_of` in both directions, and `blocks` (outbound, tagged
|
|
71
|
+
* `blocks`) / incoming (tagged `blocked_by`). `similar_to` (C9's reviewed
|
|
72
|
+
* similarity link) and the reserved `duplicate_of` are declared here for
|
|
73
|
+
* the same ref shape's future producers.
|
|
74
|
+
*/
|
|
75
|
+
rel?: 'relates_to' | 'part_of' | 'blocks' | 'blocked_by' | 'similar_to' | 'duplicate_of';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A declared obligation, projected for read (C4). This is the STORED shape,
|
|
79
|
+
* never an evaluation: `requirement` is the predicate as written, and nothing
|
|
80
|
+
* on the read path resolves it (that is C5's gate / C6's verdict). `on_fail` is
|
|
81
|
+
* returned verbatim so a caller can see the declared severity.
|
|
82
|
+
*
|
|
83
|
+
* The predicate/applies-to/override types are imported `import type`-only from
|
|
84
|
+
* `write/obligation.ts` — the grammar is declared in exactly one place, and a
|
|
85
|
+
* type-only import introduces no runtime dependency from `query/**` onto
|
|
86
|
+
* `write/**` (the two are already coupled on `write/errors.js`).
|
|
87
|
+
*/
|
|
88
|
+
export interface IObligationView {
|
|
89
|
+
uid: string;
|
|
90
|
+
applies_to: IObligationAppliesTo;
|
|
91
|
+
requirement: IPredicate;
|
|
92
|
+
on_fail: IObligationSeverity;
|
|
93
|
+
override?: IObligationOverride;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Provenance of an `IIssueCard._score` (DESIGN §2 Invariant 5: "a `score_kind`
|
|
97
|
+
* provenance tag on every derived score"). A rank-derived score (`rrf`) is
|
|
98
|
+
* ORDINAL — never to be labelled or read as a similarity/confidence; `bm25`
|
|
99
|
+
* is likewise corpus-relative. A consumer that sees a bare `_score` with no
|
|
100
|
+
* `_score_kind` cannot know which regime produced it, which is exactly the
|
|
101
|
+
* conflation this tag prevents.
|
|
102
|
+
*/
|
|
103
|
+
export type IScoreKind = 'rrf' | 'bm25' | 'cosine' | 'rank' | 'priority';
|
|
104
|
+
/**
|
|
105
|
+
* The closed CONDITION type vocabulary. A `Condition` names one thing that can
|
|
106
|
+
* make an item non-actionable (or warn about it); `status` says whether that
|
|
107
|
+
* named condition HOLDS (`{type:'Blocked',status:True}` ⇒ the item IS blocked).
|
|
108
|
+
*/
|
|
109
|
+
export type IConditionType = 'Blocked' | 'Obligation' | 'Evidence' | 'Claim' | 'Reference' | 'Budget';
|
|
110
|
+
/** Whether the NAMED condition holds. `Unknown` is a first-class "could not determine", distinct from `False`. */
|
|
111
|
+
export type IConditionStatus = 'True' | 'False' | 'Unknown';
|
|
112
|
+
/** `block` flips actionability false; `warn` is reported but never blocks (systemd Condition-vs-Assert split). */
|
|
113
|
+
export type IConditionSeverity = 'block' | 'warn';
|
|
114
|
+
/**
|
|
115
|
+
* The governed reason-code core (DESIGN §2 Primitive 4) plus the
|
|
116
|
+
* `<domain>/<Code>` extension namespace. `Unknown` is the honest "the check
|
|
117
|
+
* was not run / could not be decided".
|
|
118
|
+
*/
|
|
119
|
+
export type IVerdictReasonCode = 'BlockedBy' | 'MissingObligation' | 'EvidenceUnverified' | 'EvidenceStale' | 'ClaimStale' | 'ReferenceUnresolved' | 'Unknown' | `${string}/${string}`;
|
|
120
|
+
/**
|
|
121
|
+
* TRI-STATE (DESIGN §2 Primitive 4) — NEVER a bare boolean. `'unknown'` is
|
|
122
|
+
* never a green light: a caller that handles only booleans must be told, and
|
|
123
|
+
* the list path must report `'unknown'` rather than `true` where it cannot
|
|
124
|
+
* afford the rung. `false` iff a `block`-severity condition is `True`;
|
|
125
|
+
* `'unknown'` iff a `block`-severity condition is `Unknown` (and none is
|
|
126
|
+
* `True`); otherwise `true`.
|
|
127
|
+
*/
|
|
128
|
+
export type IActionable = boolean | 'unknown';
|
|
129
|
+
/** One named condition of a {@link IVerdict}. */
|
|
130
|
+
export interface ICondition {
|
|
131
|
+
type: IConditionType;
|
|
132
|
+
/** Whether the NAMED condition HOLDS: `True` on a `Blocked` condition = IS blocked. */
|
|
133
|
+
status: IConditionStatus;
|
|
134
|
+
severity: IConditionSeverity;
|
|
135
|
+
code: IVerdictReasonCode;
|
|
136
|
+
message?: string;
|
|
137
|
+
/** The thing to fix (blocker uid / attestation uid / obligation uid). */
|
|
138
|
+
subject?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The verdict — derived on read, never stored (`revision` is the node's own
|
|
142
|
+
* current content revision, so a caller can detect staleness; there is no
|
|
143
|
+
* materialized status field anywhere).
|
|
144
|
+
*/
|
|
145
|
+
export interface IVerdict {
|
|
146
|
+
actionable: IActionable;
|
|
147
|
+
evaluated_at: string;
|
|
148
|
+
revision: number;
|
|
149
|
+
/** Ordered block-severity first, then warn. */
|
|
150
|
+
conditions: ICondition[];
|
|
81
151
|
}
|
|
82
152
|
/**
|
|
83
153
|
* The projected issue card (SPEC.md §6.5's `IIssueCard`). Every field is
|
|
@@ -116,7 +186,52 @@ export interface IIssueCard {
|
|
|
116
186
|
blockers?: IIssueRef[];
|
|
117
187
|
related?: IIssueRef[];
|
|
118
188
|
_score?: number;
|
|
189
|
+
/** Provenance tag for `_score` (DESIGN §2 Invariant 5). Present iff `_score` is; a rank-derived score is ordinal, never similarity/confidence. */
|
|
190
|
+
_score_kind?: IScoreKind;
|
|
119
191
|
_vector?: number[];
|
|
192
|
+
/** Outbound `blocks` — issues that cannot start until this one is terminal. */
|
|
193
|
+
blocksOut?: IIssueRef[];
|
|
194
|
+
/**
|
|
195
|
+
* Transitive dependent count: how many nodes reach THIS node via `blocks`
|
|
196
|
+
* (inclusive of direct dependents). Deterministic, scope-bounded (bounded to
|
|
197
|
+
* a page's candidate id set on a list read; unbounded but cycle-safe on a
|
|
198
|
+
* single `get`).
|
|
199
|
+
*/
|
|
200
|
+
dependents?: number;
|
|
201
|
+
/** The `part_of` parent, if any (`n:1` — at most one). */
|
|
202
|
+
partOf?: IIssueRef | null;
|
|
203
|
+
/** The declared obligations on this item, in `has_obligation` edge order. */
|
|
204
|
+
obligations?: IObligationView[];
|
|
205
|
+
/** The derived actionability verdict + its typed reasons. */
|
|
206
|
+
verdict?: IVerdict;
|
|
207
|
+
/**
|
|
208
|
+
* C10 — the work item's current spec revision pointer. The card carries the
|
|
209
|
+
* revision uid + its `'sha256:<hex>'` token (the token a reader holds and
|
|
210
|
+
* compares) and the sequence — NEVER the revision body. Absent when the item
|
|
211
|
+
* has no spec, or when the `spec` pseudo field was not requested.
|
|
212
|
+
*/
|
|
213
|
+
spec?: IIssueSpecProjection;
|
|
214
|
+
/**
|
|
215
|
+
* C9 — reviewed `similar_to` links touching this item, both directions
|
|
216
|
+
* (`ISimilarLinks`). This is the ADVISORY similarity relation, populated
|
|
217
|
+
* only when explicitly requested via `fields:['similar']`; it never includes
|
|
218
|
+
* the reserved `duplicate_of` same-judgement relation.
|
|
219
|
+
*/
|
|
220
|
+
similar?: ISimilarLinks;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* C10 — the spec pointer projected onto an issue card (DESIGN §12). Additive:
|
|
224
|
+
* a consumer can hold `spec_revision_token` and later hand it to `spec-check`
|
|
225
|
+
* to learn whether it has gone stale.
|
|
226
|
+
*/
|
|
227
|
+
export interface IIssueSpecProjection {
|
|
228
|
+
/** The current revision uid (the pointer's target). */
|
|
229
|
+
spec_revision: string;
|
|
230
|
+
/** `'sha256:<hex>'` — the token a reader holds and compares. */
|
|
231
|
+
spec_revision_token: string;
|
|
232
|
+
revision_seq: number;
|
|
233
|
+
/** Present only when the caller supplied a token to compare against. */
|
|
234
|
+
freshness?: SpecFreshness;
|
|
120
235
|
}
|
|
121
236
|
/**
|
|
122
237
|
* `get`'s uid-addressed shape (SPEC.md §6.3.1/§6.5/AC-13) — the implementation
|
|
@@ -128,6 +243,17 @@ export interface IIssueCard {
|
|
|
128
243
|
export interface IIssueGetByUidInput {
|
|
129
244
|
uid: IssueUid;
|
|
130
245
|
fields?: readonly IIssueField[];
|
|
246
|
+
/** Bounds the `auditTrail`/`citations`/`related`/`blockers` pseudo fields to the LAST N rows (preserving each resolver's own order — the audit trail's oldest-first order is sliced to its tail). */
|
|
247
|
+
lastN?: number;
|
|
248
|
+
/** Cursor for the bounded sub-collection (opaque; from the previous page's last returned uid). */
|
|
249
|
+
after?: string;
|
|
250
|
+
/**
|
|
251
|
+
* C6 — the highest verdict ladder rung this `get` may run. Default 3 (the
|
|
252
|
+
* single-item default); a caller may raise it to 5 for a full anchor
|
|
253
|
+
* re-resolve. The list views never accept this and always derive at rung 2
|
|
254
|
+
* (DESIGN §2 Primitive 4, "Bounded derivation").
|
|
255
|
+
*/
|
|
256
|
+
deriveThrough?: 1 | 2 | 3 | 4 | 5;
|
|
131
257
|
}
|
|
132
258
|
/** SPEC.md §6.5's `IIssueFilter`. */
|
|
133
259
|
export interface IIssueFilter {
|
|
@@ -171,6 +297,14 @@ export interface IIssueFilter {
|
|
|
171
297
|
since?: string;
|
|
172
298
|
until?: string;
|
|
173
299
|
};
|
|
300
|
+
/**
|
|
301
|
+
* C9 — uid of X: return items linked `similar_to` X (i.e. the SOURCE side of
|
|
302
|
+
* an outgoing `similar_to` edge whose target is X). Renamed from the removed
|
|
303
|
+
* `duplicateOf`; `similar_to` is the reviewed similarity relation.
|
|
304
|
+
*/
|
|
305
|
+
similarTo?: string;
|
|
306
|
+
/** C9 — true: return items with ≥1 incoming `similar_to` link (the DST side). Renamed from the removed `hasDuplicates`. */
|
|
307
|
+
hasSimilar?: boolean;
|
|
174
308
|
}
|
|
175
309
|
export type IIssueSort = 'priority' | 'updated' | 'created' | 'relevance' | 'textMatch';
|
|
176
310
|
export type IIssueSortDirection = 'asc' | 'desc';
|
|
@@ -182,7 +316,7 @@ export type IIssueSortDirection = 'asc' | 'desc';
|
|
|
182
316
|
* `listLocations`, distinct from the issue-search views above (§6.1:
|
|
183
317
|
* "conflating the two would be wrong").
|
|
184
318
|
*/
|
|
185
|
-
export type IIssueView = 'list' | 'ready' | 'graph' | 'order' | 'stale' | 'similar' | 'overlap' | 'projects' | 'components' | 'locations';
|
|
319
|
+
export type IIssueView = 'list' | 'ready' | 'graph' | 'order' | 'stale' | 'similar' | 'overlap' | 'projects' | 'components' | 'locations' | 'kinds' | 'catalogs';
|
|
186
320
|
export type IIssueQueryFormat = 'json' | 'markdown';
|
|
187
321
|
/** SPEC.md §5, §6.1's `axis` — the grouping dimension for `overlapUids` (§6.2). */
|
|
188
322
|
export type IOverlapAxis = 'file' | 'project' | 'component' | 'author';
|
|
@@ -220,6 +354,8 @@ export interface IIssueQueryInput {
|
|
|
220
354
|
overlapUids?: readonly string[];
|
|
221
355
|
/** `view:'stale'` only — minutes since `claimedAt`; falls back to `project_policy.claim_stale_after_min` (default 30) when omitted. */
|
|
222
356
|
staleAfterMin?: number;
|
|
357
|
+
/** C8 — `view:'catalogs'` only: narrow to one vocabulary catalog. Omitted ⇒ every catalog's terms (the same set `view:'kinds'` exposes). */
|
|
358
|
+
catalog?: CatalogKindName;
|
|
223
359
|
}
|
|
224
360
|
export declare const MAX_QUERY_LIMIT = 1000;
|
|
225
361
|
export declare const DEFAULT_QUERY_LIMIT = 50;
|
|
@@ -301,6 +437,7 @@ export type IIssueQueryResult = IIssueListResult | {
|
|
|
301
437
|
} | {
|
|
302
438
|
view: 'similar';
|
|
303
439
|
items: IIssueCard[];
|
|
440
|
+
clusters?: ISimilarViewClusterBlock;
|
|
304
441
|
} | {
|
|
305
442
|
view: 'overlap';
|
|
306
443
|
groups: IOverlapGroup[];
|
|
@@ -313,6 +450,12 @@ export type IIssueQueryResult = IIssueListResult | {
|
|
|
313
450
|
} | {
|
|
314
451
|
view: 'locations';
|
|
315
452
|
items: ILocationSummary[];
|
|
453
|
+
} | {
|
|
454
|
+
view: 'kinds';
|
|
455
|
+
catalogs: ICatalogView;
|
|
456
|
+
} | {
|
|
457
|
+
view: 'catalogs';
|
|
458
|
+
terms: ICatalogTerm[];
|
|
316
459
|
} | IIssueMarkdownResult;
|
|
317
460
|
export interface IProjectSummary {
|
|
318
461
|
uid: string;
|
|
@@ -391,6 +534,28 @@ export interface ILookupResult {
|
|
|
391
534
|
};
|
|
392
535
|
/** Present when only a partial (project-level, or path-prefix) match was found — never a silent null (§3a). */
|
|
393
536
|
hint?: string;
|
|
537
|
+
/**
|
|
538
|
+
* C1 — a resolved-by-token hint. When `lookup` recognises `q` as a uid/uid
|
|
539
|
+
* prefix or a unique issue title, the registry shape does not apply; instead
|
|
540
|
+
* the caller is told which verb to re-issue (`get`) and with which uid, so a
|
|
541
|
+
* transport can forward exactly one canonical request rather than guessing.
|
|
542
|
+
*/
|
|
543
|
+
redirect?: {
|
|
544
|
+
verb: 'get' | 'query';
|
|
545
|
+
uid?: string;
|
|
546
|
+
query?: string;
|
|
547
|
+
};
|
|
548
|
+
/**
|
|
549
|
+
* C1 — the candidate set behind an ambiguity this read CHOSE to surface
|
|
550
|
+
* rather than fail on. (A `lookup` whose title grep matches ≥2 issues still
|
|
551
|
+
* throws `AmbiguousReferenceError`; this field exists for callers that
|
|
552
|
+
* surface candidates alongside a chosen primary.)
|
|
553
|
+
*/
|
|
554
|
+
candidates?: Array<{
|
|
555
|
+
uid: string;
|
|
556
|
+
kind: string;
|
|
557
|
+
name: string;
|
|
558
|
+
}>;
|
|
394
559
|
}
|
|
395
560
|
/**
|
|
396
561
|
* `get`'s registry-detail shape (SPEC.md §3a/§8 AC-11) — `get --input
|
|
@@ -448,3 +613,53 @@ export type IIssueGetInput = IIssueGetByUidInput | IIssueGetRegistryInput;
|
|
|
448
613
|
* repro — so no workaround is needed here; this type is plain `IIssueCard`.
|
|
449
614
|
*/
|
|
450
615
|
export type IIssueGetResult = IIssueCard | IProjectDetail | IComponentDetail | ILocationDetail;
|
|
616
|
+
/** C9 — one reviewed `similar_to` neighbour of a card, in the compact cross-reference shape. */
|
|
617
|
+
export interface ISimilarRef {
|
|
618
|
+
uid: string;
|
|
619
|
+
title: string;
|
|
620
|
+
status: string;
|
|
621
|
+
projectUid?: string;
|
|
622
|
+
repoUrl?: string;
|
|
623
|
+
}
|
|
624
|
+
/** C9 — a card's reviewed `similar_to` links, both directions (`n:m`, so both are sets). */
|
|
625
|
+
export interface ISimilarLinks {
|
|
626
|
+
/** Items THIS one is linked `similar_to` (outgoing, n:m). */
|
|
627
|
+
similarTo: ISimilarRef[];
|
|
628
|
+
/** Items linked `similar_to` THIS one (incoming, n:m). */
|
|
629
|
+
similarFrom: ISimilarRef[];
|
|
630
|
+
}
|
|
631
|
+
/** C9 — one member of an advisory or linked similarity cluster. */
|
|
632
|
+
export interface ISimilarMember {
|
|
633
|
+
uid: string;
|
|
634
|
+
title: string;
|
|
635
|
+
projectUid: string;
|
|
636
|
+
projectName: string;
|
|
637
|
+
componentUid?: string;
|
|
638
|
+
repoUrl?: string;
|
|
639
|
+
/** Cosine to the cluster seed (undefined for linked-only members). */
|
|
640
|
+
score?: number;
|
|
641
|
+
/** Which independent signals fired, e.g. `['cosine','title-tokens']`. */
|
|
642
|
+
signals?: string[];
|
|
643
|
+
/** A `similar_to` target when linked. */
|
|
644
|
+
linkedTo?: string;
|
|
645
|
+
}
|
|
646
|
+
/** C9 — a single-linkage similarity cluster: `seedUid` is the top-scoring member that anchored it. */
|
|
647
|
+
export interface ISimilarCluster {
|
|
648
|
+
seedUid: string;
|
|
649
|
+
members: ISimilarMember[];
|
|
650
|
+
/** true iff live `similar_to` edges exist among members. */
|
|
651
|
+
linked: boolean;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* C9 — the additive cluster block `view:'similar'` gains when a scope filter
|
|
655
|
+
* (`project`/`component`) is present. `candidate` is the advisory,
|
|
656
|
+
* write-nothing scan output; `linked` is built from existing live `similar_to`
|
|
657
|
+
* edges only. Without the embedding substrate `candidate` is `[]` (the
|
|
658
|
+
* documented degraded mode) while `linked` still returns.
|
|
659
|
+
*/
|
|
660
|
+
export interface ISimilarViewClusterBlock {
|
|
661
|
+
candidate: ISimilarCluster[];
|
|
662
|
+
linked: ISimilarCluster[];
|
|
663
|
+
scanned: number;
|
|
664
|
+
computedAt: string;
|
|
665
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IActionable, ICondition } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ONE actionability rule (DESIGN §2 Primitive 4).
|
|
5
|
+
*
|
|
6
|
+
* - `false` iff at least one `block`-severity condition is `True` (the item IS
|
|
7
|
+
* blocked — a definite answer beats an uncertain one);
|
|
8
|
+
* - `'unknown'` iff any `block`-severity condition is `Unknown` and none is
|
|
9
|
+
* `True` (the check could not be run / decided — NEVER a green light);
|
|
10
|
+
* - otherwise `true`.
|
|
11
|
+
*
|
|
12
|
+
* `'Unknown'` is never treated as `false` OR as `true`. `warn`-severity
|
|
13
|
+
* conditions never affect the result.
|
|
14
|
+
*/
|
|
15
|
+
export declare function computeActionable(conditions: readonly ICondition[]): IActionable;
|
|
16
|
+
/**
|
|
17
|
+
* Stable ordering: all `block` before all `warn`; within a band, by `code`
|
|
18
|
+
* then `subject` (both lexical, `undefined` subject sorts first). Pure and
|
|
19
|
+
* total — two callers ordering the same set always agree.
|
|
20
|
+
*/
|
|
21
|
+
export declare function orderConditions(conditions: readonly ICondition[]): ICondition[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IVerdict } from './types.js';
|
|
2
|
+
import { GraphBackend, NodeRecord } from '@adhd/sox-graph-store';
|
|
3
|
+
|
|
4
|
+
/** Highest ladder rung `deriveVerdict` may run. */
|
|
5
|
+
export type IVerdictRung = 1 | 2 | 3 | 4 | 5;
|
|
6
|
+
export interface IDeriveVerdictOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Highest ladder rung this call is allowed to run. Default 2 (the list
|
|
9
|
+
* bound). 5 = full re-resolve. A budget stop yields an `Unknown` condition.
|
|
10
|
+
*/
|
|
11
|
+
maxRung?: IVerdictRung;
|
|
12
|
+
/** The instant used for staleness maths; defaults to nowISO(). */
|
|
13
|
+
at?: string;
|
|
14
|
+
/** Staleness threshold (minutes); defaults to 30 (project_policy default). */
|
|
15
|
+
claimStaleAfterMin?: number;
|
|
16
|
+
/** Test instrumentation: invoked with each rung actually evaluated. */
|
|
17
|
+
onRung?: (rung: number) => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Derive the verdict for a live issue (DESIGN §2 Primitive 4). NEVER writes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function deriveVerdict(graph: GraphBackend, issue: NodeRecord, opts?: IDeriveVerdictOptions): Promise<IVerdict>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { GraphBackend } from '@adhd/sox-graph-store';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The catalogs this view exposes. `kind`/`status`/`priority` are store-backed
|
|
5
|
+
* (open vocabularies minted by the write layer); the rest are fixed in-code
|
|
6
|
+
* vocabularies projected from their validating source.
|
|
7
|
+
*/
|
|
8
|
+
export type CatalogKindName = 'kind' | 'status' | 'priority' | 'relation' | 'field' | 'error_code' | 'location_type' | 'verb';
|
|
9
|
+
/** The in-code source a term was generated from. Named so the catalog is provably generated, not hand-maintained. */
|
|
10
|
+
export type CatalogSource = 'store' | 'edge_kind_table' | 'reserved_terminal_status_names' | 'issue_field_union' | 'error_code_union' | 'valid_location_types' | 'mounted_verb_surface';
|
|
11
|
+
export type CatalogLifecycle = 'active' | 'deprecated';
|
|
12
|
+
export interface ICatalogTerm {
|
|
13
|
+
/** The term's canonical name. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Live row uid when a store row backs it; absent for in-code source terms. */
|
|
16
|
+
uid?: string;
|
|
17
|
+
/** Which vocabulary this term belongs to. */
|
|
18
|
+
catalog: CatalogKindName;
|
|
19
|
+
/** The validating source this term was generated from at call time. */
|
|
20
|
+
source: CatalogSource;
|
|
21
|
+
lifecycle: CatalogLifecycle;
|
|
22
|
+
/** Present when deprecated: the term to use instead. */
|
|
23
|
+
replacedBy?: string;
|
|
24
|
+
/** For `kind`/`status`/`priority`: the live callers count, read at call time. */
|
|
25
|
+
usageCount?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ICatalogView {
|
|
28
|
+
catalogs: CatalogKindName[];
|
|
29
|
+
terms: ICatalogTerm[];
|
|
30
|
+
/** True when any term is a case-fold collision of another within its catalog (the invariant the read layer depends on). */
|
|
31
|
+
hasCaseCollisions: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* ONE read view over every vocabulary (AC1). Every non-`store` term is derived
|
|
35
|
+
* from its in-code source at call time — never a hand-written list — and every
|
|
36
|
+
* `store` term is a live row with its caller count.
|
|
37
|
+
*
|
|
38
|
+
* Read-only: it never opens a transaction and never writes, so it is safe
|
|
39
|
+
* against any store, including the live one.
|
|
40
|
+
*/
|
|
41
|
+
export declare function catalogView(graph: GraphBackend): Promise<ICatalogView>;
|
|
42
|
+
/**
|
|
43
|
+
* The terms of ONE catalog (AC1's narrowed sibling). Derived from the SAME
|
|
44
|
+
* {@link catalogView} — there is no second generation path, so `kinds` and
|
|
45
|
+
* `catalogs` can never disagree about a catalog's contents.
|
|
46
|
+
*/
|
|
47
|
+
export declare function catalogFor(graph: GraphBackend, catalog: CatalogKindName): Promise<ICatalogTerm[]>;
|
|
@@ -33,11 +33,31 @@ export declare function getRegistryDetail(graph: GraphBackend, input: {
|
|
|
33
33
|
name: string;
|
|
34
34
|
}): Promise<ILocationDetail>;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* distinct, actionable outcome from "found, but only a hint" (the `hint`
|
|
41
|
-
* field below).
|
|
36
|
+
* The optional kind HINT `lookup` accepts (C1, §3a). `q` is the token to
|
|
37
|
+
* resolve; `kind` narrows which routing branch runs, so a caller that already
|
|
38
|
+
* knows it is holding an issue uid or a project name can suppress the other
|
|
39
|
+
* branches instead of relying on the default precedence.
|
|
42
40
|
*/
|
|
43
|
-
export
|
|
41
|
+
export interface ILookupInput {
|
|
42
|
+
q: string;
|
|
43
|
+
/** optional: `'location' | 'project' | 'component' | 'issue'` */
|
|
44
|
+
kind?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `query --input '{"view":"lookup", "lookup": "<tool|file|url|uid|title|project>"}'`
|
|
48
|
+
* (§3a, C1 AC4) — resolve ANY token a consumer holds to exactly one canonical
|
|
49
|
+
* answer, or fail loudly naming what was searched.
|
|
50
|
+
*
|
|
51
|
+
* Routing order (C1 spec, fixed):
|
|
52
|
+
* 1. a uid or uid PREFIX → a `redirect` to `get` (the registry shape does not
|
|
53
|
+
* apply to a node reached by identity);
|
|
54
|
+
* 2. an issue TITLE → exactly one hit redirects to `get`; ≥2 is
|
|
55
|
+
* `AmbiguousReferenceError`; zero falls through;
|
|
56
|
+
* 3. the existing location classify→match→walk;
|
|
57
|
+
* 4. a project `name`/`repoUrl` match;
|
|
58
|
+
* then `CatalogNotFoundError('location', q)` — `lookup` is never a silent null.
|
|
59
|
+
*
|
|
60
|
+
* Existing location-only consumers keep working: their exact-path query misses
|
|
61
|
+
* the uid/title/project branches and is served by step 3 unchanged.
|
|
62
|
+
*/
|
|
63
|
+
export declare function lookup(graph: GraphBackend, input: string | ILookupInput): Promise<ILookupResult>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { IQueryStoreHandle } from '../query.js';
|
|
2
|
+
import { IIssueFilter } from '../types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `report`'s filter — the four dimensions `priorityMatrix` composes with
|
|
6
|
+
* (`project`/`component`/`kind`/`status`). `status` is the coarse
|
|
7
|
+
* `open`/`closed`/`all` selector (never a name list): `report`'s whole point
|
|
8
|
+
* is a scope-named aggregate, and `statusScope` echoes exactly what was
|
|
9
|
+
* counted. An omitted `status` defaults to `'open'`, matching `priorityMatrix`.
|
|
10
|
+
*/
|
|
11
|
+
export interface IReportInput {
|
|
12
|
+
filter?: {
|
|
13
|
+
project?: string;
|
|
14
|
+
component?: string;
|
|
15
|
+
kind?: string | string[];
|
|
16
|
+
status?: 'open' | 'closed' | 'all';
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface IReportResult {
|
|
20
|
+
/** Counts by `kind` name (live, in-scope rows only), name-ascending. */
|
|
21
|
+
byKind: Array<{
|
|
22
|
+
kind: string;
|
|
23
|
+
count: number;
|
|
24
|
+
}>;
|
|
25
|
+
/** Counts by `priority` name + rank (composed from `priorityMatrix`). */
|
|
26
|
+
byPriority: Array<{
|
|
27
|
+
priority: string;
|
|
28
|
+
rank?: number;
|
|
29
|
+
count: number;
|
|
30
|
+
}>;
|
|
31
|
+
/** Status histogram: status name, its terminal flag, and the count. */
|
|
32
|
+
byStatus: Array<{
|
|
33
|
+
status: string;
|
|
34
|
+
terminal: boolean;
|
|
35
|
+
count: number;
|
|
36
|
+
}>;
|
|
37
|
+
/** Average age in days of OPEN (non-terminal) in-scope items, measured from `tCreated` at report time. */
|
|
38
|
+
avgAgeDays: number;
|
|
39
|
+
/** Names what was counted — `'open'` when the filter omitted `status`. */
|
|
40
|
+
statusScope: NonNullable<IIssueFilter['status']>;
|
|
41
|
+
/** The instant every time-relative number above was computed against. */
|
|
42
|
+
computedAt: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* SPEC.md §5's grouped rollup (DESIGN §5 AC7) — every count computed from the
|
|
46
|
+
* store in this call, none stored. See this file's header for the
|
|
47
|
+
* composition rule.
|
|
48
|
+
*/
|
|
49
|
+
export declare function report(handle: IQueryStoreHandle, input: IReportInput): Promise<IReportResult>;
|
|
@@ -72,23 +72,46 @@ export interface IRelevanceRankOptions {
|
|
|
72
72
|
* `view:'similar'` itself.
|
|
73
73
|
*/
|
|
74
74
|
export declare function rankByFusedRelevance(handle: IQueryStoreHandle, opts: IRelevanceRankOptions): Promise<SearchResult[]>;
|
|
75
|
+
/**
|
|
76
|
+
* `view:'similar'`'s result when the caller also needs completeness truth
|
|
77
|
+
* (`has_more`/`limit`) — see {@link querySimilarViewWithMeta}. `hasMore` is
|
|
78
|
+
* derived by fetching one row beyond the page, never fabricated.
|
|
79
|
+
*/
|
|
80
|
+
export interface ISimilarViewResult {
|
|
81
|
+
items: IIssueCard[];
|
|
82
|
+
hasMore: boolean;
|
|
83
|
+
/** The caller-facing page size actually applied. */
|
|
84
|
+
limit: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* `view:'similar'` (SPEC.md §5a) — the plain `IIssueCard[]` every existing
|
|
88
|
+
* caller (and `semantic.spec.ts`) already reads. Thin wrapper over
|
|
89
|
+
* {@link querySimilarViewWithMeta}, which also yields the completeness flag
|
|
90
|
+
* the C7 envelope attaches.
|
|
91
|
+
*/
|
|
92
|
+
export declare function querySimilarView(handle: IQueryStoreHandle, input: IIssueQueryInput): Promise<IIssueCard[]>;
|
|
75
93
|
/**
|
|
76
94
|
* `view:'similar'` (SPEC.md §5a) — `filter.anchor` (item-anchored) or
|
|
77
95
|
* `filter.semantic` (free text), fused text+vec ranked via
|
|
78
|
-
* {@link rankByFusedRelevance}, projected to `IIssueCard`s with `_score`
|
|
79
|
-
* populated when requested (`card.ts`'s
|
|
80
|
-
*
|
|
96
|
+
* {@link rankByFusedRelevance}, projected to `IIssueCard`s with `_score`/`_score_kind`
|
|
97
|
+
* populated when requested (`card.ts`'s `IAssembleIssueCardOptions` seam — SPEC.md
|
|
98
|
+
* §5a's `_score` exposure; `_score_kind:'rrf'` per DESIGN §2 Invariant 5).
|
|
81
99
|
*
|
|
82
100
|
* The anchor issue is EXCLUDED from its own results (RAG-SPEC.md §3.2's
|
|
83
101
|
* carried-forward "the query item itself is excluded" — SPEC.md §5a does not
|
|
84
102
|
* restate this explicitly, a genuine spec gap this implementation fills per
|
|
85
103
|
* that precedent rather than silently, since "similar to X" trivially
|
|
86
104
|
* self-matching X at rank 1 is a real usability defect, not a feature).
|
|
87
|
-
* Exclusion is done POST-search (fetch
|
|
105
|
+
* Exclusion is done POST-search (fetch beyond the page, drop the anchor,
|
|
88
106
|
* slice to `limit`) rather than by enumerating the whole issue table to
|
|
89
107
|
* subtract one id up front — far cheaper for the common "no other filter"
|
|
90
108
|
* case, and still exactly correct.
|
|
91
109
|
*
|
|
110
|
+
* **Completeness (`hasMore`):** the fetch is one row beyond the page — plus
|
|
111
|
+
* one MORE when anchored, since the anchor consumes a slot when it appears in
|
|
112
|
+
* the window — so `hasMore` is genuinely "a live row exists beyond this page",
|
|
113
|
+
* not an inference from `items.length === limit`.
|
|
114
|
+
*
|
|
92
115
|
* Errors: `IssueNotFoundError(anchor)` (SPEC.md §6.1's general `uid`-
|
|
93
116
|
* addressing convention — `anchor` is `uid`-typed per §6.1's own statement
|
|
94
117
|
* that it is "the SAME `uid`-typed field" as every other addressing field;
|
|
@@ -98,4 +121,4 @@ export declare function rankByFusedRelevance(handle: IQueryStoreHandle, opts: IR
|
|
|
98
121
|
* `InvalidArgumentError('filter', ...)` (neither `anchor` nor `semantic`
|
|
99
122
|
* given). `BacklogValidationError('limit', ...)` (out-of-range `limit`).
|
|
100
123
|
*/
|
|
101
|
-
export declare function
|
|
124
|
+
export declare function querySimilarViewWithMeta(handle: IQueryStoreHandle, input: IIssueQueryInput): Promise<ISimilarViewResult>;
|