diffwiki 0.17.3 → 0.18.0-rc.202611121225.38e2b9e

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/bin.js CHANGED
@@ -7,6 +7,7 @@ import { ensureHome } from "diffwiki-core";
7
7
  import { spawn as spawn4 } from "child_process";
8
8
  import path5 from "path";
9
9
  import { fileURLToPath as fileURLToPath3 } from "url";
10
+ import { readFile } from "fs/promises";
10
11
  import { Command, Option } from "commander";
11
12
  import {
12
13
  addExternalCollection,
@@ -14,6 +15,13 @@ import {
14
15
  collectionGitStatus,
15
16
  createArticle,
16
17
  createCollection,
18
+ createMetaRecord,
19
+ initMeta,
20
+ reindexMeta,
21
+ findCollection,
22
+ parseFrontmatter,
23
+ CollectionNotFoundError,
24
+ DiffwikiError as DiffwikiError2,
17
25
  doctor,
18
26
  getConfigValue,
19
27
  initRepoWiki,
@@ -38,10 +46,9 @@ import {
38
46
  resolveCwdCollection,
39
47
  resolveEditorCommand,
40
48
  resolveEditTarget,
41
- setArticleMeta,
42
49
  setConfigValue,
43
50
  setTags,
44
- updateArticleBody
51
+ updateArticle
45
52
  } from "diffwiki-core";
46
53
 
47
54
  // src/version.ts
@@ -359,15 +366,18 @@ async function createArticleAction(target, opts) {
359
366
  async function updateArticleAction(target, opts) {
360
367
  const tagList = splitTags(opts.tag);
361
368
  const hasMeta = opts.audience !== void 0 || opts.status !== void 0;
362
- if (opts.body === void 0 && tagList.length === 0 && !hasMeta) {
363
- console.error("Nothing to update \u2014 pass -b/--body, -t/--tag, --audience, and/or --status.");
369
+ if (opts.title === void 0 && opts.body === void 0 && tagList.length === 0 && !hasMeta) {
370
+ console.error("Nothing to update \u2014 pass --title, -b/--body, -t/--tag, --audience, and/or --status.");
364
371
  process.exitCode = 1;
365
372
  return;
366
373
  }
367
- let article;
368
- if (opts.body !== void 0) article = await updateArticleBody(target, opts.body);
369
- if (tagList.length > 0) article = await setTags(target, tagList);
370
- if (hasMeta) article = await setArticleMeta(target, { audience: opts.audience, status: opts.status });
374
+ const article = await updateArticle(target, {
375
+ title: opts.title,
376
+ body: opts.body,
377
+ ...tagList.length ? { tags: tagList } : {},
378
+ audience: opts.audience,
379
+ status: opts.status
380
+ });
371
381
  console.log(`Updated ${article.path}`);
372
382
  }
373
383
  async function removeArticleAction(target) {
@@ -524,9 +534,9 @@ async function templatesInitAction() {
524
534
  if (seeded.length === 0 && skipped.length === 0) console.log(" (no bundled templates found)");
525
535
  }
526
536
  async function templatesListAction(opts) {
527
- const infos = await listTemplates(bundledTemplatesDir());
537
+ const infos = await listTemplates(bundledTemplatesDir(), opts.category);
528
538
  if (infos.length === 0) {
529
- console.log("No bundled templates found.");
539
+ console.log("No templates found.");
530
540
  return;
531
541
  }
532
542
  if (opts.json) {
@@ -538,6 +548,38 @@ async function templatesListAction(opts) {
538
548
  console.log(`${t.shape} ${t.purpose}${budget}`);
539
549
  }
540
550
  }
551
+ function reportMeta(result, opts) {
552
+ if (opts.json) console.log(JSON.stringify(result, null, 2));
553
+ else {
554
+ console.log(`Metadata: ${result.created.length} mirrors created, ${result.kept.length} kept.`);
555
+ for (const file of result.index_paths) console.log(file);
556
+ }
557
+ for (const warning of result.warnings) console.error(`! ${warning}`);
558
+ for (const error of result.errors) console.error(`\u2716 ${error}`);
559
+ if (result.errors.length) process.exitCode = 1;
560
+ }
561
+ async function metaInitAction(name, opts) {
562
+ const entries = name ? [await findCollection(name)] : await listCollections2();
563
+ if (entries.some((entry) => !entry)) throw new CollectionNotFoundError(name);
564
+ reportMeta(await initMeta(entries.filter((entry) => entry !== void 0)), opts);
565
+ }
566
+ async function metaNewAction(target, opts) {
567
+ const colon = target.indexOf(":");
568
+ const name = colon < 0 ? target : target.slice(0, colon);
569
+ const articlePath = colon < 0 ? void 0 : target.slice(colon + 1);
570
+ const entry = await findCollection(name);
571
+ if (!entry) throw new CollectionNotFoundError(name);
572
+ const template = (await listTemplates(bundledTemplatesDir(), "meta")).find((item) => item.shape === opts.template);
573
+ if (!template) throw new DiffwikiError2(`Metadata template ${opts.template} not found. Run: diffwiki templates init`);
574
+ try {
575
+ const { body } = parseFrontmatter(await readFile(template.path, "utf8"));
576
+ const record = await createMetaRecord(entry, articlePath, opts.template, body.replace(/<!--[\s\S]*?-->/g, ""));
577
+ console.log(opts.json ? JSON.stringify(record, null, 2) : record.path);
578
+ } catch (err) {
579
+ if (err instanceof DiffwikiError2) throw err;
580
+ throw new DiffwikiError2(`Cannot capture ${target}: ${String(err)}`);
581
+ }
582
+ }
541
583
  var parseNames = (csv) => csv.split(",").map((s) => s.trim()).filter(Boolean);
542
584
  async function warnUnknownCollections(names) {
543
585
  const known = new Set((await listCollections2()).map((c) => c.name));
@@ -702,8 +744,8 @@ function createProgram() {
702
744
  "deprecated"
703
745
  ])
704
746
  ).action(withErrors((target, opts) => createArticleAction(target, opts)));
705
- article.command("update").description("Update an article's body, tags, audience, and/or status").argument("<target>", '"collection:slug"').option("-b, --body <markdown>", "replace the article body").option("-t, --tag <tag>", "replace all tags (repeatable, comma-separated)", collect, []).addOption(new Option("--audience <audience>", "set visibility").choices(["public", "private", "system"])).addOption(new Option("--status <status>", "set publish status").choices(["draft", "published", "deprecated"])).action(withErrors((target, opts) => updateArticleAction(target, opts)));
706
- article.command("remove").description("Delete an article").argument("<target>", '"collection:slug"').action(withErrors((target) => removeArticleAction(target)));
747
+ article.command("update").description("Update an article's display title, body, tags, audience, and/or status").argument("<target>", '"collection:slug"').option("--title <title>", "set the display title without renaming the file").option("-b, --body <markdown>", "replace the article body").option("-t, --tag <tag>", "replace all tags (repeatable, comma-separated)", collect, []).addOption(new Option("--audience <audience>", "set visibility").choices(["public", "private", "system"])).addOption(new Option("--status <status>", "set publish status").choices(["draft", "published", "deprecated"])).action(withErrors((target, opts) => updateArticleAction(target, opts)));
748
+ article.command("remove").description("Delete an article").argument("<target>", '"[collection:]slug"').action(withErrors((target) => removeArticleAction(target)));
707
749
  article.command("edit").description("Open an article in your editor \u2014 GUI not required").argument("<target>", '"collection:slug"').option("--editor <cmd>", "editor command (overrides config `editor`, $VISUAL, $EDITOR)").action(withErrors((target, opts) => editAction(target, opts.editor)));
708
750
  const tags = program.command("tags").description("Manage an article's tags");
709
751
  const registerTagsSub = (name, description, fn) => {
@@ -745,9 +787,21 @@ function createProgram() {
745
787
  context.command("set").description("Replace the recall-context collections").argument("<names>", "comma-separated collection names").action(withErrors((names) => contextSetAction(names)));
746
788
  context.command("add").description("Add collections to the recall context").argument("<names>", "comma-separated collection names").action(withErrors((names) => contextAddAction(names)));
747
789
  context.command("remove").description("Remove collections from the recall context").argument("<names>", "comma-separated collection names").action(withErrors((names) => contextRemoveAction(names)));
790
+ const meta = program.command("meta").description("Capture raw sources beside collection and article paths");
791
+ meta.command("init").description("Create missing source manifests for existing articles").argument("[collection]", "limit to one registered collection").option("--json", "output paths and diagnostics as JSON").action(withErrors(metaInitAction));
792
+ meta.command("new").description("Create a source-record template for a collection or exact article filename").argument("<target>", "collection or collection:relative-file.md").addOption(
793
+ new Option("--template <kind>", "source template").choices(["history", "external-source-extract", "dream-learning"]).makeOptionMandatory()
794
+ ).option("--json", "output the record and index paths as JSON").action(withErrors(metaNewAction));
795
+ meta.command("reindex").description("Refresh generated source listings from current metadata files").argument("[collection]", "limit to one metadata collection").option("--json", "output paths and diagnostics as JSON").action(
796
+ withErrors(
797
+ async (name, opts) => reportMeta(await reindexMeta(name), opts)
798
+ )
799
+ );
748
800
  const templates = program.command("templates").description("Manage authoring templates (~/.diffwiki/templates)");
749
801
  templates.command("init").description("Seed ~/.diffwiki/templates from the bundled templates (never overwrites your own)").action(withErrors(templatesInitAction));
750
- templates.command("list").description("List templates with their shape + purpose (read from each template\u2019s frontmatter)").option("--json", "output as JSON").action(withErrors((opts) => templatesListAction(opts)));
802
+ templates.command("list").description("List templates with their shape + purpose (read from each template\u2019s frontmatter)").addOption(
803
+ new Option("--category <category>", "template category").choices(["article", "meta", "all"]).default("article")
804
+ ).option("--json", "output as JSON").action(withErrors((opts) => templatesListAction(opts)));
751
805
  const config = program.command("config").description("Read and write diffwiki config");
752
806
  config.command("set").description("Set a config value (e.g. defaultCollection, or defaultSearch <engine[:type]>)").argument("<key>", "config key").argument("<value>", "config value").action(withErrors((key, value) => configSetAction(key, value)));
753
807
  config.command("get").description("Read a config value").argument("<key>", "config key").action(withErrors((key) => configGetAction(key)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffwiki",
3
- "version": "0.17.3",
3
+ "version": "0.18.0-rc.202611121225.38e2b9e",
4
4
  "description": "diffwiki command-line interface",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,7 +18,7 @@
18
18
  "@logtape/logtape": "^2.2.4",
19
19
  "@logtape/file": "^2.2.4",
20
20
  "commander": "^13.0.0",
21
- "diffwiki-core": "0.17.3"
21
+ "diffwiki-core": "0.18.0-rc.202611121225.38e2b9e"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^22.0.0"
@@ -18,7 +18,7 @@ Authoring rules:
18
18
  - No prose paragraphs, no examples, no code blocks
19
19
  - Keep descriptions to a single clause — enough to distinguish siblings
20
20
  - Do not copy over html comments or the template specific yaml frontmatter above this section. Write a diffwiki article yaml frontmatter as shown below this comment.
21
- - Use concise descriptive titles in article frontmatter
21
+ - Use concise descriptive titles in article frontmatter. An index.md filename must not become the display title "index" or a path ending in /index.
22
22
  - Tag the collection topic and add collection-index tag
23
23
  - Default to public audience and published status for index files
24
24
  -->
@@ -0,0 +1,30 @@
1
+ ---
2
+ shape: dream-learning
3
+ category: meta
4
+ purpose: Keep one dream change inspectable through its raw evidence and observed result.
5
+ ---
6
+
7
+ ## Run
8
+
9
+ - Tool: dw-dream
10
+ - Run / original event time: unknown
11
+
12
+ ## Raw user requests
13
+
14
+ Not captured. Quote the request and include its session/message location. Do not infer preferences.
15
+
16
+ ## Raw session/tool outputs
17
+
18
+ Not captured. Include speaker, command, output, exit status, and source locations. Label assistant text as generated and unverified.
19
+
20
+ ## Source snippets
21
+
22
+ Not captured. Preserve the relevant original code or document excerpts and their locations.
23
+
24
+ ## Source record links
25
+
26
+ None captured. Link preserved primary evidence from every affected page.
27
+
28
+ ## Change and result
29
+
30
+ Not captured. Include affected paths, the exact patch or action, and the observed result. Record partial failures plainly.
@@ -0,0 +1,29 @@
1
+ ---
2
+ shape: external-source-extract
3
+ category: meta
4
+ purpose: Store retrieved documentation, web page, or paper excerpts with their origin.
5
+ ---
6
+
7
+ ## Source
8
+
9
+ - Requested URL: unknown
10
+ - Resolved URL: unknown
11
+ - Title / author / publisher: unknown
12
+ - Published date / document version: unknown
13
+ - Retrieved at (UTC): unknown
14
+ - Heading / page / line locator: unknown
15
+
16
+ ## Exact excerpt
17
+
18
+ Not captured. Quote the retrieved text with enough context. Do not substitute a summary.
19
+
20
+ ## Capture details
21
+
22
+ - Format / extraction method: unknown
23
+ - Coverage / omitted sections / truncation: unknown
24
+ - Retrieval failure or redactions: unknown
25
+ - Original attachment path / checksum, if retained: unknown
26
+
27
+ ## Source record links
28
+
29
+ None captured. Link related records without replacing their original text.
@@ -0,0 +1,37 @@
1
+ ---
2
+ shape: history
3
+ category: meta
4
+ purpose: Preserve original user requests, verbatim harness sessions, human review feedback, session outputs, and source code.
5
+ ---
6
+
7
+ ## Raw harness session and artifacts
8
+
9
+ Not captured. Record the harness name, raw session transcript path, and relative links to verbatim session logs or artifacts stored under `.meta/attachments/<record-id>/`.
10
+
11
+ ## Raw user requests
12
+
13
+ Not captured. Include exact quotations, speaker, original time, and session/message location when known.
14
+
15
+ ## Stated rationale
16
+
17
+ Not captured. Quote the user's explanation. Do not infer a reason.
18
+
19
+ ## Human review and plan feedback (.difflab & forge PR/MR comments)
20
+
21
+ Not captured. Include verbatim human reviewer comments from `.difflab/plans/*/revisions/*.md` (`## Feedback`), `.difflab/reviews/*/REVIEW.md`, and directly on the forge (`gh`/`glab` PR/MR review comments when not in local `.difflab` files) with file/revision/thread locators. Exclude AI-generated review comments.
22
+
23
+ ## Raw session/tool outputs
24
+
25
+ Not captured. Include the command, output, exit status, and source location. Label assistant text as generated and unverified.
26
+
27
+ ## Source snippets
28
+
29
+ Not captured. Preserve code and whitespace. Include repository, file, symbol/lines, commit when known, and local changes.
30
+
31
+ ## Source record links
32
+
33
+ None captured. Link any shared collection evidence, attachments, or earlier records.
34
+
35
+ ## Change and result
36
+
37
+ Not captured. Name affected files and the observed result. Keep capture time separate from the original event time.
@@ -2,25 +2,33 @@
2
2
  shape: session-transcript
3
3
  purpose: dw-learn capture into the hidden transcripts collection (not linted).
4
4
  ---
5
- <!-- SESSION TRANSCRIPT. The agent fills this by introspecting its own session.
5
+ <!-- SESSION TRANSCRIPT. Summarizes the session while verbatim raw harness logs,
6
+ session artifacts, and .difflab review/plan files are stored in
7
+ ~/.diffwiki/meta/transcripts/ via `diffwiki meta new "transcripts:<project>/<file>.md" --template history`.
6
8
  Goes into the hidden `transcripts` collection with `--audience system`; NOT linted
7
- as a knowledge entry. Terse and factual — raw material for dw-learn, not a doc.
9
+ as a knowledge entry. Do not invent dialogue, causes, preferences, or lessons.
8
10
  Title (passed to the CLI) is "<project>/<date>-<short-id>"; tags are
9
11
  [transcript, <tool>, <project>]. Do not write frontmatter — the CLI owns it. -->
10
12
 
11
- **Tool:** <claude-code|codex|opencode|goose|pi> · **Project:** <repo-or-path> · **Date:** <YYYY-MM-DD> · **Session:** <id-if-known>
13
+ **Tool:** <claude-code|antigravity|codex|cursor|opencode|goose|pi|aider> · **Project:** <repo-or-path> · **Date:** <YYYY-MM-DD> · **Session:** <id-if-known>
12
14
 
13
- ## Worked on
14
- - <goal — what was attempted and the outcome>
15
+ ## Session summary
16
+ - <1-3 bullet summary of the goal, approach, and outcome>
15
17
 
16
- ## Issues & learnings
17
- - <problem — root cause — how it was resolved (or that it's unresolved)>
18
+ ## Raw user requests
19
+ - <exact quotation, original time, session/message location>
18
20
 
19
- ## Decisions & patterns
20
- - <architectural decision or reusable pattern observed — and why>
21
+ ## Reviews and plan feedback (.difflab & human reviewer comments)
22
+ - <summary and exact quotes of HUMAN feedback from .difflab/plans/*/revisions/*.md (## Feedback), .difflab/reviews/*/REVIEW.md, and human review comments made directly on the forge (GitHub/GitLab PR/MR review threads via `gh`/`glab`) when not already in local .difflab files; exclude AI-generated review comments; or "None in this session.">
21
23
 
22
- ## Key tool actions
23
- - <notable commands, files created/changed, workflows — the reproducible bits>
24
+ ## Raw session outputs
25
+ - <speaker/role, exact output, source message location; label assistant text generated/unverified>
24
26
 
25
- ## Open threads
26
- - <unfinished work, follow-ups, questions for next time>
27
+ ## Commands and results
28
+ - <command, exact relevant stdout/stderr, exit status, original event time>
29
+
30
+ ## Source snippets
31
+ - <original code/document excerpt, repository, file/lines, commit/version, local changes>
32
+
33
+ ## Source locations and gaps
34
+ - <links to verbatim raw harness session log and session/.difflab artifacts in ~/.diffwiki/meta/transcripts/.meta/; omitted/redacted/unavailable material>