@adhd/backlog 0.0.2 → 0.1.1

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.
@@ -61,8 +61,19 @@ export interface BacklogItem {
61
61
  createdAt: string;
62
62
  updatedAt: string;
63
63
  }
64
+ /**
65
+ * BUG-BACKLOG-REPO-LOOKUP-UX-001: a `(repo, humanId)` miss is frequently NOT
66
+ * "this item doesn't exist" but "this item exists under a DIFFERENT `repo`
67
+ * string" (e.g. `"adhd"` vs `"PseudoSky/adhd"` both live in the same store
68
+ * for what is logically one project). `foundInRepos` — populated by
69
+ * `store/query.ts`'s `buildNotFoundError` helper, which every throw site now
70
+ * calls instead of constructing this directly — carries the OTHER repo
71
+ * value(s) the humanId actually lives under, so the thrown message names the
72
+ * fix instead of leaving the caller to guess.
73
+ */
64
74
  export declare class BacklogItemNotFoundError extends Error {
65
- constructor(repo: string, humanId: string);
75
+ readonly foundInRepos: string[];
76
+ constructor(repo: string, humanId: string, foundInRepos?: string[]);
66
77
  }
67
78
  export declare class CitationRequiredError extends Error {
68
79
  constructor(status: BacklogStatus);
@@ -104,6 +115,14 @@ export interface CreateItemResult {
104
115
  item: BacklogItem;
105
116
  created: boolean;
106
117
  duplicateCandidates: BacklogItem[];
118
+ /**
119
+ * BUG-BACKLOG-REPO-LOOKUP-UX-001: set (soft warning, never blocks the
120
+ * write) when `input.repo` doesn't match any repo value already known to
121
+ * this store — a likely typo/inconsistent-repo-string drift (e.g. filing
122
+ * under `"adhd"` when every existing item uses `"PseudoSky/adhd"`) rather
123
+ * than a genuine first-time-use of a new repo, which is always allowed.
124
+ */
125
+ repoWarning?: string;
107
126
  }
108
127
  export interface UpdateItemInput {
109
128
  title?: string;
@@ -155,6 +174,19 @@ export interface BacklogFilter {
155
174
  * duplicated into root.
156
175
  */
157
176
  rootLevel?: boolean;
177
+ /**
178
+ * Drops items with `metadata.archivedAt` set (BACKLOG-adoption's
179
+ * `archiveResolved` — SPEC.md §5.4). `renderToMarkdown` always applies
180
+ * this internally (a markdown projection never shows archived rows), but
181
+ * `listItems`/`queryItemNodes` do NOT default to it — auditing/reporting
182
+ * consumers legitimately need to see archived items too. A caller that
183
+ * needs to reproduce `renderToMarkdown`'s exact item set through
184
+ * `listItems` (e.g. `render-projections.mjs`/`parity-check.mjs` verifying
185
+ * a rendered projection against the graph's own view of the same filter —
186
+ * BUG-BACKLOG-RENDER-VERIFY-ARCHIVED-MISMATCH-001) must set this
187
+ * explicitly; otherwise the two queries diverge on every archived row.
188
+ */
189
+ excludeArchived?: boolean;
158
190
  limit?: number;
159
191
  offset?: number;
160
192
  }
@@ -269,6 +301,8 @@ export interface ImportResult {
269
301
  }>;
270
302
  /** Headers that look like a corrupted/typo'd id and were dropped instead of parsed — never silent (DEBT-BACKLOG-IMPORT-SILENT-DROP-001). */
271
303
  malformedHeaders: MalformedHeaderInfo[];
304
+ /** See `CreateItemResult.repoWarning` (BUG-BACKLOG-REPO-LOOKUP-UX-001) — computed once for `input.repo`, not per item. */
305
+ repoWarning?: string;
272
306
  }
273
307
  export interface AuditTrailEntry {
274
308
  at: string;
package/package.json CHANGED
@@ -1,34 +1,29 @@
1
1
  {
2
2
  "name": "@adhd/backlog",
3
- "version": "0.0.2",
3
+ "version": "0.1.1",
4
4
  "bin": {
5
- "backlog": "./dist/index.js"
5
+ "backlog": "index.js"
6
6
  },
7
7
  "dependencies": {
8
8
  "@adhd/sox-graph-store": "^0.3.0",
9
9
  "better-sqlite3": "^12.10.0",
10
- "@adhd/environment": "0.0.2",
11
- "@adhd/environment-base-spec": "0.0.3",
12
- "@adhd/apigen-core-client": "^0.1.1",
13
- "@adhd/apigen-plugin-api-fastify": "^0.1.2",
14
- "@adhd/apigen-plugin-openapi": "^0.1.3",
15
- "@adhd/apigen-plugin-mcp": "^0.1.2",
16
- "@adhd/apigen-plugin-cli-output": "^0.1.3",
17
- "@adhd/apigen-engine-naming": "^0.1.3",
18
- "yaml": "1.10.3"
10
+ "@adhd/environment": "^0.1.1",
11
+ "@adhd/environment-base-spec": "^0.1.0",
12
+ "@adhd/apigen-core-client": "^0.2.1",
13
+ "@adhd/apigen-plugin-api-fastify": "^0.2.1",
14
+ "@adhd/apigen-plugin-openapi": "^0.2.1",
15
+ "@adhd/apigen-plugin-mcp": "^0.2.1",
16
+ "@adhd/apigen-plugin-batch": "^0.2.0",
17
+ "@adhd/apigen-plugin-cli-output": "^0.2.1",
18
+ "@adhd/apigen-engine-naming": "^0.2.1",
19
+ "yaml": "1.10.3",
20
+ "pino": "10.3.1",
21
+ "pino-pretty": "13.1.3"
19
22
  },
20
- "devDependencies": {
21
- "@types/better-sqlite3": "^7.6.13"
22
- },
23
- "main": "./dist/index.js",
24
- "module": "./dist/index.mjs",
25
- "typings": "./dist/index.d.ts",
23
+ "main": "./index.js",
24
+ "module": "./index.mjs",
25
+ "typings": "./index.d.ts",
26
26
  "publishConfig": {
27
27
  "access": "public"
28
- },
29
- "files": [
30
- "dist",
31
- "CHANGELOG.md",
32
- "skill"
33
- ]
28
+ }
34
29
  }
@@ -1,5 +1,5 @@
1
1
  import { BacklogCtx } from './client.js';
2
- import { composeSchemas, Operation, OutputPlugin, RunInput } from '@adhd/apigen-core-client';
2
+ import { composeSchemas, Operation, Logger, OutputPlugin, RunInput } from '@adhd/apigen-core-client';
3
3
  import { Scope } from '@adhd/environment-base-spec';
4
4
 
5
5
  /**
@@ -13,6 +13,30 @@ import { Scope } from '@adhd/environment-base-spec';
13
13
  * plain re-export instead.
14
14
  */
15
15
  export declare function requireRun(plugin: OutputPlugin): (input: RunInput) => Promise<void>;
16
+ /**
17
+ * Test-only `RunInput.logger` override (exported for `cli.ts`'s identical
18
+ * third-transport mount). Every one of the three apigen output plugins
19
+ * (`apigen-plugin-api-fastify`, `-mcp`, `-cli-output`) falls back to its own
20
+ * `createLogger()` — real pino, level `info`, writing jsonl to stderr —
21
+ * whenever `input.logger` is absent, which floods the console on every test
22
+ * run that actually mounts a transport (`server.spec.ts`, `server.mcp.spec.ts`,
23
+ * `serve.spec.ts`, and `cli.spec.ts`'s spawned-binary cases, since
24
+ * `spawnSync`'s `env: { ...process.env }` inherits vitest's own
25
+ * `VITEST=true`). None of those specs assert on log content — they assert
26
+ * status codes and response bodies — so under vitest this swaps in a no-op
27
+ * logger. `mcpPlugin`/`cliPlugin` only ever call `.info`/`.error` on it, but
28
+ * `apiFastifyPlugin` hands it straight to `Fastify({ logger })`, whose own
29
+ * `validateLogger` (`fastify/lib/logger.js`) REQUIRES the full pino surface
30
+ * (`info,error,debug,fatal,warn,trace,child`) or throws
31
+ * `FST_ERR_LOG_INVALID_LOGGER` — confirmed empirically, not guessed, by a
32
+ * first cut here that only stubbed `info`/`error` and blew up every
33
+ * `server.spec.ts` HTTP test with exactly that error. `child()` returns the
34
+ * same no-op instance (fastify calls it per-request to derive a child
35
+ * logger; a self-referencing no-op keeps every descendant silent too).
36
+ * Outside vitest (a real `backlog serve` or CLI invocation) this returns
37
+ * `undefined` and the real pino default logger is used, unchanged.
38
+ */
39
+ export declare function testSilentLogger(): Logger | undefined;
16
40
  export interface StartOpts {
17
41
  transport: 'http' | 'mcp' | 'both';
18
42
  port?: number;
@@ -1,12 +1,38 @@
1
1
  import { BacklogNodeMeta } from './mapping.js';
2
2
  import { GraphBacklogStore } from './graph-backlog-store.js';
3
- import { AuditTrailResult, BacklogFilter, BacklogItem, DependencyGraph, StatsScope, TopoOrderResult } from '../model.js';
3
+ import { AuditTrailResult, BacklogFilter, BacklogItem, DependencyGraph, StatsScope, TopoOrderResult, BacklogItemNotFoundError } from '../model.js';
4
4
  import { NodeRecord } from '@adhd/sox-graph-store';
5
5
 
6
6
  /** Raw NodeRecord query — used internally where the full node (not just the mapped BacklogItem) is needed. */
7
7
  export declare function queryItemNodes(store: GraphBacklogStore, filter?: BacklogFilter): NodeRecord[];
8
8
  export declare function listItems(store: GraphBacklogStore, filter?: BacklogFilter): BacklogItem[];
9
9
  export declare function findItemNode(store: GraphBacklogStore, repo: string, humanId: string): NodeRecord | null;
10
+ /**
11
+ * Finds every LIVE node carrying this `humanId`, across ALL repos (no
12
+ * `namespace` filter) — BUG-BACKLOG-REPO-LOOKUP-UX-001's "did you mean repo
13
+ * X?" hint needs this to distinguish "this humanId truly doesn't exist" from
14
+ * "it exists, just filed under a different repo string than the caller
15
+ * passed." Used only on the miss path (`buildNotFoundError`) — never on the
16
+ * hot successful-lookup path, so it costs nothing when a lookup is correct.
17
+ */
18
+ export declare function findHumanIdInAnyRepo(store: GraphBacklogStore, humanId: string): NodeRecord[];
19
+ /**
20
+ * Every distinct repo value any LIVE backlog item is currently filed under.
21
+ * Used by `createItemNode`'s soft repo-drift warning (write-time half of
22
+ * BUG-BACKLOG-REPO-LOOKUP-UX-001) — an empty store (no items yet) has no
23
+ * "known" repos, so the very first item filed under any repo string never
24
+ * triggers a false-positive warning.
25
+ */
26
+ export declare function knownRepos(store: GraphBacklogStore): Set<string>;
27
+ /**
28
+ * Builds the `BacklogItemNotFoundError` every miss site throws — the single
29
+ * place that decides whether a "did you mean repo X?" hint is warranted
30
+ * (BUG-BACKLOG-REPO-LOOKUP-UX-001, read-time half). Callers pass the SAME
31
+ * `(repo, humanId)` they just failed to find via `findItemNode` — this
32
+ * re-queries WITHOUT the `namespace` restriction to see if the humanId lives
33
+ * under a different repo string instead.
34
+ */
35
+ export declare function buildNotFoundError(store: GraphBacklogStore, repo: string, humanId: string): BacklogItemNotFoundError;
10
36
  export declare function computeStats(store: GraphBacklogStore, scope?: StatsScope): import('../model.js').BacklogStats;
11
37
  export declare function spotlight(store: GraphBacklogStore, scope?: StatsScope, limit?: number): BacklogItem[];
12
38
  export declare function blockers(store: GraphBacklogStore, repo: string, humanId: string): BacklogItem[];