@deskwork/studio 0.16.0 → 0.17.0

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.
@@ -3,13 +3,26 @@
3
3
  * handlers use this when they need both metadata (from the sidecar) and
4
4
  * the live document content (from the markdown artifact on disk).
5
5
  *
6
- * The artifact path depends on stage: scrapbook docs (idea/plan/outline)
7
- * for early stages, the canonical `index.md` for Drafting / Final /
8
- * Published. Off-pipeline stages (Blocked / Cancelled) carry their
9
- * priorStage so the resolver can locate the artifact even when the
10
- * entry is paused.
6
+ * Issue #222 (Option B + hybrid refinement) `index.md` is always
7
+ * "the document under review" for index.md-canonical entries. The
8
+ * studio renders `index.md` regardless of `currentStage`. Per-stage
9
+ * scrapbook files are frozen snapshots produced by `approveEntryStage`.
11
10
  *
12
- * Pipeline-redesign Task 33 Phase 6 entry resolver.
11
+ * Resolution order (T1 + non-index.md fallback):
12
+ * 1. If the sidecar carries an `artifactPath`:
13
+ * a. Prefer `<dirname(artifactPath)>/index.md` IF it exists on disk
14
+ * (T1's index.md-canonical case).
15
+ * b. Otherwise fall back to `artifactPath` itself. Supports
16
+ * shared-directory layouts (multiple entries per directory,
17
+ * each addressed by its own filename) — e.g. deskwork's own
18
+ * feature-doc layout where prd.md / workplan.md / README.md
19
+ * share a directory.
20
+ * 2. No artifactPath: try `<contentDir>/<slug>/index.md` (pre-#140
21
+ * entries that the doctor migration hasn't processed yet).
22
+ *
23
+ * Pre-T1 the resolver routed by stage (Ideas → idea.md, Planned →
24
+ * plan.md, Outlining → outline.md, Drafting/Final/Published →
25
+ * index.md). That routing has been retired — see Issue #222.
13
26
  */
14
27
  import type { Entry } from '@deskwork/core/schema/entry';
15
28
  interface ResolveResult {
@@ -1 +1 @@
1
- {"version":3,"file":"entry-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/entry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,6BAA6B,CAAC;AAEhE,UAAU,aAAa;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAaD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAoB5F"}
1
+ {"version":3,"file":"entry-resolver.d.ts","sourceRoot":"","sources":["../../src/lib/entry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAOH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEzD,UAAU,aAAa;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqBD,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAK5F"}
@@ -3,46 +3,53 @@
3
3
  * handlers use this when they need both metadata (from the sidecar) and
4
4
  * the live document content (from the markdown artifact on disk).
5
5
  *
6
- * The artifact path depends on stage: scrapbook docs (idea/plan/outline)
7
- * for early stages, the canonical `index.md` for Drafting / Final /
8
- * Published. Off-pipeline stages (Blocked / Cancelled) carry their
9
- * priorStage so the resolver can locate the artifact even when the
10
- * entry is paused.
6
+ * Issue #222 (Option B + hybrid refinement) `index.md` is always
7
+ * "the document under review" for index.md-canonical entries. The
8
+ * studio renders `index.md` regardless of `currentStage`. Per-stage
9
+ * scrapbook files are frozen snapshots produced by `approveEntryStage`.
11
10
  *
12
- * Pipeline-redesign Task 33 Phase 6 entry resolver.
11
+ * Resolution order (T1 + non-index.md fallback):
12
+ * 1. If the sidecar carries an `artifactPath`:
13
+ * a. Prefer `<dirname(artifactPath)>/index.md` IF it exists on disk
14
+ * (T1's index.md-canonical case).
15
+ * b. Otherwise fall back to `artifactPath` itself. Supports
16
+ * shared-directory layouts (multiple entries per directory,
17
+ * each addressed by its own filename) — e.g. deskwork's own
18
+ * feature-doc layout where prd.md / workplan.md / README.md
19
+ * share a directory.
20
+ * 2. No artifactPath: try `<contentDir>/<slug>/index.md` (pre-#140
21
+ * entries that the doctor migration hasn't processed yet).
22
+ *
23
+ * Pre-T1 the resolver routed by stage (Ideas → idea.md, Planned →
24
+ * plan.md, Outlining → outline.md, Drafting/Final/Published →
25
+ * index.md). That routing has been retired — see Issue #222.
13
26
  */
14
27
  import { readFile } from 'node:fs/promises';
15
- import { join } from 'node:path';
28
+ import { existsSync } from 'node:fs';
29
+ import { basename, dirname, join } from 'node:path';
16
30
  import { readSidecar } from '@deskwork/core/sidecar';
17
31
  import { getContentDir } from '@deskwork/core/config';
18
- const STAGE_ARTIFACT = {
19
- Ideas: (s, d) => join(d, s, 'scrapbook', 'idea.md'),
20
- Planned: (s, d) => join(d, s, 'scrapbook', 'plan.md'),
21
- Outlining: (s, d) => join(d, s, 'scrapbook', 'outline.md'),
22
- Drafting: (s, d) => join(d, s, 'index.md'),
23
- Final: (s, d) => join(d, s, 'index.md'),
24
- Published: (s, d) => join(d, s, 'index.md'),
25
- Blocked: null,
26
- Cancelled: null,
27
- };
28
- export async function resolveEntry(projectRoot, uuid) {
29
- const entry = await readSidecar(projectRoot, uuid);
30
- // #140: prefer the explicit artifactPath when set; fall back to the
31
- // slug+stage heuristic only for entries that don't have one (entries
32
- // created pre-#140 fix and not yet doctor-repaired).
33
- let artifactPath;
32
+ function resolveIndexPath(projectRoot, entry) {
34
33
  if (entry.artifactPath) {
35
- artifactPath = join(projectRoot, entry.artifactPath);
36
- }
37
- else {
38
- const stage = entry.priorStage ?? entry.currentStage;
39
- const pathFn = STAGE_ARTIFACT[stage];
40
- if (pathFn === null) {
41
- throw new Error(`No artifact path for stage ${stage}`);
42
- }
43
- const contentDir = getContentDir(projectRoot);
44
- artifactPath = pathFn(entry.slug, contentDir);
34
+ const absArtifact = join(projectRoot, entry.artifactPath);
35
+ // Strip the scrapbook segment for legacy `<dir>/scrapbook/<file>.md`
36
+ // shapes; otherwise dirname(absArtifact) IS the doc dir.
37
+ const dir = basename(dirname(absArtifact)) === 'scrapbook'
38
+ ? dirname(dirname(absArtifact))
39
+ : dirname(absArtifact);
40
+ const indexPath = join(dir, 'index.md');
41
+ // T1's index.md-canonical preference: only if it actually exists.
42
+ // Otherwise fall back to artifactPath (shared-directory layouts).
43
+ if (existsSync(indexPath))
44
+ return indexPath;
45
+ return absArtifact;
45
46
  }
47
+ const contentDir = getContentDir(projectRoot);
48
+ return join(contentDir, entry.slug, 'index.md');
49
+ }
50
+ export async function resolveEntry(projectRoot, uuid) {
51
+ const entry = await readSidecar(projectRoot, uuid);
52
+ const artifactPath = resolveIndexPath(projectRoot, entry);
46
53
  const artifactBody = await readFile(artifactPath, 'utf8');
47
54
  return { entry, artifactBody, artifactPath };
48
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entry-resolver.js","sourceRoot":"","sources":["../../src/lib/entry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAStD,MAAM,cAAc,GAAyE;IAC3F,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC;IACrD,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,YAAY,CAAC;IAC1D,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;IAC1C,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;IACvC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC;IAC3C,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,IAAY;IAClE,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEnD,oEAAoE;IACpE,qEAAqE;IACrE,qDAAqD;IACrD,IAAI,YAAoB,CAAC;IACzB,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,YAAY,CAAC;QACrD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC9C,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"entry-resolver.js","sourceRoot":"","sources":["../../src/lib/entry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAStD,SAAS,gBAAgB,CAAC,WAAmB,EAAE,KAAY;IACzD,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QAC1D,qEAAqE;QACrE,yDAAyD;QACzD,MAAM,GAAG,GACP,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,KAAK,WAAW;YAC5C,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACxC,kEAAkE;QAClE,kEAAkE;QAClE,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,UAAU,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,IAAY;IAClE,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAC/C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deskwork/studio",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "description": "Editorial review studio — local web UI for the deskwork plugin",
6
6
  "homepage": "https://github.com/audiocontrol-org/deskwork#readme",
@@ -46,7 +46,7 @@
46
46
  "@codemirror/language": "^6.12.3",
47
47
  "@codemirror/state": "^6.6.0",
48
48
  "@codemirror/view": "^6.41.1",
49
- "@deskwork/core": "0.16.0",
49
+ "@deskwork/core": "0.17.0",
50
50
  "@hono/node-server": "^1.13.7",
51
51
  "@lezer/highlight": "^1.2.3",
52
52
  "esbuild": "^0.28.0",