@difflab/difflab-cli 0.10.0 → 0.11.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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +201 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -66,7 +66,9 @@ difflab-cli templates list
66
66
  difflab-cli templates scaffold spec-driven-plan docs/plans first-plan.md --cwd /absolute/project/path
67
67
  ```
68
68
 
69
- The CLI defaults `--cwd` to its current directory. The MCP server exposes `template_list({})` and `scaffold({"name":"spec-driven-plan","cwd":"/absolute/project/path","path":"docs/plans","filename":"first-plan.md"})`. Both interfaces take a hyphenated template name, a relative destination **directory** (`path`, or `.` for `cwd`), and a separate **filename**. MCP always requires an absolute existing `cwd`. Missing destination directories are created. Available names: `spec-driven-plan`, `software-architecture-design`, `architecture-decision-record`, `product-requirements-document`, `agents`, `code-review`, `planning-intent`, `ui-component-architecture`, `pull-request-description` (adapted from Diffpi's PR template), `flow-definition`, `flow-instance`, `exploration-summary`, `exploration-research`, `exploration-proposal`, and `poc-readme`.
69
+ The CLI defaults `--cwd` to its current directory. The MCP server exposes `template_list({})` and `scaffold({"name":"spec-driven-plan","cwd":"/absolute/project/path","path":"docs/plans","filename":"first-plan.md"})`. Both interfaces take a hyphenated template name, a relative destination **directory** (`path`, or `.` for `cwd`), and a separate **filename**. MCP always requires an absolute existing `cwd`. Missing destination directories are created. Available names: `spec-driven-plan`, `software-architecture-design`, `architecture-decision-record`, `product-requirements-document`, `agents`, `code-review`, `code-review-rubric`, `planning-intent`, `ui-component-architecture`, `pull-request-description` (adapted from Diffpi's PR template), `flow-definition`, `flow-instance`, `exploration-summary`, `exploration-research`, `exploration-proposal`, and `poc-readme`.
70
+
71
+ Reviews scaffold `code-review` as `REVIEW.md` and `code-review-rubric` as `rubric.yaml` in `.difflab/reviews/YYMMDD-name`. The installed rubric is `~/.difflab/templates/code-review-rubric.yaml`. Fill its criterion results during the review. File-scoped criteria require a path-tagged result for every changed source file. Function findings can include `file:line` locations. Evidence guidance and review instructions stay in the review skill, outside the lean YAML template.
70
72
 
71
73
  Use `difflab-cli templates scaffold agents . AGENTS.md --cwd /absolute/project/path` to start repository guidance. Fill the prompts with known rules and remove unused prompts. The template separates Hard Rules, Organization, Style, and Testing. Hard Rules name required task runners and repository tools. Organization separates directory layout from section headers, code ordering, and grouping within files. Review addressing saves explicit user repository rules immediately and marks inferred or uncertain rules with `[Proposed]`. It asks before reorganizing existing guidance to match the template and adapts the existing structure if permission is declined. It retains terse file-level organization rules and keeps guidance within 500 soft-wrapped source lines.
72
74
 
package/dist/index.js CHANGED
@@ -48664,6 +48664,8 @@ var code_review_default = `# Review: [change or pull request]
48664
48664
  - **Intent:** [stated objective and source]
48665
48665
  - **Reviewer:** [name]
48666
48666
 
48667
+ [Apply root and applicable nested AGENTS.md rules throughout every section. Repository rules take precedence over generic rubric conventions. Cite violations under the relevant section.]
48668
+
48667
48669
  ## Intent Delivery
48668
48670
 
48669
48671
  [Does the change actually deliver the intended behavior? What is missing or outside scope?]
@@ -48674,7 +48676,7 @@ var code_review_default = `# Review: [change or pull request]
48674
48676
 
48675
48677
  ## Semantic Organization
48676
48678
 
48677
- [Do modules have clear roles and useful public APIs? Identify mixed responsibilities and unclear ownership. Refactor or simplify at the scope needed to make the change understandable, including across files. Keep unrelated work out of scope.]
48679
+ [Do modules have clear roles and useful public APIs? Are exported types meaningful for the module role? Are methods and classes easy to discover and use? Identify mixed responsibilities and unclear ownership. Refactor or simplify at the scope needed to make the change understandable, including across files. Keep unrelated work out of scope.]
48678
48680
 
48679
48681
  ## Maintainability
48680
48682
 
@@ -48682,11 +48684,11 @@ var code_review_default = `# Review: [change or pull request]
48682
48684
 
48683
48685
  ## Reliability/Testing
48684
48686
 
48685
- [Prioritize end-to-end application behavior, then module behavior through public APIs, then focused unit behavior with public APIs first. Name missing observable contracts or regressions; do not demand coverage of every function or a percentage. Check semantic grouping, clear Arrange/Act/Assert blocks, fixtures, and existing shared helpers. Flag walls of repeated setup or interleaved actions/assertions that hide the behavior. Report executed checks and limits honestly.]
48687
+ [Prioritize end-to-end application behavior, then module behavior through public APIs, then focused unit behavior with public APIs first. Flag tests that only verify external dependencies rather than the repository's source behavior or integration contract. Require test names to identify the function or functionality tested and its expected behavior, regardless of grouping style. Name missing observable contracts or regressions; do not demand coverage of every function or a percentage. Check semantic grouping, clear Arrange/Act/Assert blocks, fixtures, and existing shared helpers. Flag walls of repeated setup or interleaved actions/assertions that hide the behavior. Report executed checks and limits honestly.]
48686
48688
 
48687
- ## Repository Guidance
48689
+ ## Documentation
48688
48690
 
48689
- [List root/applicable nested AGENTS.md paths and material deviations in changed files. Cite actual rules, including code/test organization and helper placement where prescribed. If none applies or guidance could not be read, say so. Keep this assessment brief.]
48691
+ [Flag walls of text, complex language, and text that only restates the implementation. Require concise, simple-English explanations. Prefer diagrams when they clarify structures, flows, or relationships better than long prose.]
48690
48692
 
48691
48693
  ## Performance
48692
48694
 
@@ -48694,11 +48696,11 @@ var code_review_default = `# Review: [change or pull request]
48694
48696
 
48695
48697
  ## Security
48696
48698
 
48697
- [Report clear security defects, including exposed secrets or broken authorization/trust boundaries. Deepen the audit for an explicit security focus; avoid unrelated hardening requests. State SKIPPED with a short reason when a deeper audit is not warranted.]
48699
+ [Optional: run this dimension only when explicitly requested, including a security focus. Otherwise state that it was not selected. Report clear security defects discovered by other dimensions without claiming a security audit. Avoid unrelated hardening requests.]
48698
48700
 
48699
48701
  ## Change Requests
48700
48702
 
48701
- Use short comments in simple English. State the problem and its effect directly. Phrase recommendations as suggestions with \u201CLet's\u201D, \u201CI suggest\u201D, or \u201CI recommend\u201D, usually in one to three sentences total. Use the scope that fixes the problem, including a refactor when needed. Group repeated instances of one cause. Omit nitpicks, minor optimizations, and speculative findings. End each generated request and response with its model attribution quote. Preserve human text unchanged.
48703
+ Every generated comment and reply must use simple English and be as short as possible. Include a suggested change when a concrete fix is available. State the issue and its effect directly. Phrase recommendations with \u201CLet's\u201D, \u201CI suggest\u201D, or \u201CI recommend\u201D. Include a short snippet or suggested patch only when it clarifies the fix. Use the scope that fixes the problem, including a refactor when needed. Group repeated instances of one cause. Omit repeated context, nitpicks, minor optimizations, and speculative findings. End each generated request and response with its model attribution quote. Preserve human text unchanged.
48702
48704
 
48703
48705
  ### [file:line \u2014 request]
48704
48706
 
@@ -48724,10 +48726,185 @@ Use short comments in simple English. State the problem and its effect directly.
48724
48726
  ## Verification and Limits
48725
48727
 
48726
48728
  - **Checks run:** [command and result.]
48727
- - **Not verified:** [environment, path, or behavior not checked.]
48729
+ - **Not verified:** [environment, path, behavior, or applicable repository guidance that could not be checked.]
48730
+ - **Rubric:** [path to the copied YAML rubric with completed criterion results. Disclose missing, pending, skipped, or stale results.]
48728
48731
  `;
48729
48732
  var init_code_review = () => {};
48730
48733
 
48734
+ // templates/code-review-rubric.yaml
48735
+ var code_review_rubric_default = `version: 1
48736
+ worker_defaults:
48737
+ model: sol
48738
+ reasoning_effort: medium
48739
+ review:
48740
+ base_revision: null
48741
+ head_revision: null
48742
+ working_tree: null
48743
+ changed_files: []
48744
+ exclusions: []
48745
+ section_reviewers: []
48746
+ sections:
48747
+ - title: Intent Delivery
48748
+ criteria:
48749
+ - id: intent.objective
48750
+ scope: review
48751
+ default_severity: blocking
48752
+ issue: The change contradicts its stated intent or omits required behavior.
48753
+ results: []
48754
+ - id: intent.scope
48755
+ scope: review
48756
+ default_severity: consider
48757
+ issue: The change includes work outside its stated scope.
48758
+ results: []
48759
+ - title: Readability
48760
+ criteria:
48761
+ - id: readability.function-names
48762
+ scope: file
48763
+ default_severity: consider
48764
+ issue: >-
48765
+ Function or other names misrepresent behavior, hide side effects, or break established naming conventions.
48766
+ results: []
48767
+ - id: readability.structure
48768
+ scope: file
48769
+ default_severity: consider
48770
+ issue: The changed flow is materially hard to follow.
48771
+ results: []
48772
+ - title: Semantic Organization
48773
+ criteria:
48774
+ - id: organization.roles
48775
+ scope: file
48776
+ default_severity: consider
48777
+ issue: A module mixes responsibilities or its imports, exports, or public API obscure its role.
48778
+ results: []
48779
+ - id: organization.architecture
48780
+ scope: review
48781
+ default_severity: consider
48782
+ issue: Files or classes break the established architecture or module patterns.
48783
+ results: []
48784
+ - id: organization.api-ergonomics
48785
+ scope: applicable-file
48786
+ applies_when: Added or modified public APIs, exported types, methods, or classes.
48787
+ default_severity: consider
48788
+ issue: Public APIs expose types unrelated to the module role or are hard to discover and use.
48789
+ results: []
48790
+ - id: organization.new-files
48791
+ scope: applicable-file
48792
+ applies_when: Added source files that introduce a module or submodule. A rename alone does not qualify.
48793
+ default_severity: consider
48794
+ issue: >-
48795
+ A new file lacks a justified module boundary or contains functions that belong in an existing module.
48796
+ results: []
48797
+ - id: organization.file-structure
48798
+ scope: file
48799
+ default_severity: consider
48800
+ issue: A file breaks the project-prescribed structure or declaration order.
48801
+ results: []
48802
+ - title: Maintainability
48803
+ criteria:
48804
+ - id: maintainability.concepts
48805
+ scope: review
48806
+ default_severity: consider
48807
+ issue: >-
48808
+ New fields, types, wrappers, helpers, dependencies, or layers lack a justified use and add needless complexity.
48809
+ results: []
48810
+ - id: maintainability.complexity
48811
+ scope: applicable-file
48812
+ applies_when: >-
48813
+ Files with added or changed executable functions. For new functions, assess whether the introduced decision paths are justified.
48814
+ default_severity: consider
48815
+ issue: Cyclomatic complexity grows without justification from the required behavior.
48816
+ results: []
48817
+ - id: maintainability.utilities
48818
+ scope: review
48819
+ default_severity: consider
48820
+ issue: Duplicated state or behavior, or inline work, makes a function harder to read or maintain.
48821
+ results: []
48822
+ - id: maintainability.packages
48823
+ scope: review
48824
+ default_severity: consider
48825
+ issue: >-
48826
+ Custom code recreates functionality that an established, widely used package suitably provides.
48827
+ results: []
48828
+ - title: Reliability/Testing
48829
+ criteria:
48830
+ - id: testing.correctness
48831
+ scope: file
48832
+ default_severity: blocking
48833
+ issue: The changed code produces incorrect behavior.
48834
+ results: []
48835
+ - id: testing.application
48836
+ scope: review
48837
+ default_severity: consider
48838
+ issue: Required behavior or a meaningful regression lacks test evidence.
48839
+ results: []
48840
+ - id: testing.relevance
48841
+ scope: applicable-file
48842
+ applies_when: Added or modified test files.
48843
+ default_severity: consider
48844
+ issue: >-
48845
+ A test verifies external dependency behavior without establishing behavior of the repository's own source code.
48846
+ results: []
48847
+ - id: testing.names
48848
+ scope: applicable-file
48849
+ applies_when: Added or modified test files.
48850
+ default_severity: consider
48851
+ issue: >-
48852
+ A test name does not identify the function or functionality tested and its expected behavior.
48853
+ results: []
48854
+ - id: testing.arrange-act-assert
48855
+ scope: applicable-file
48856
+ applies_when: Added or modified test files.
48857
+ default_severity: consider
48858
+ issue: >-
48859
+ Test grouping or interleaved setup, actions, and assertions hide the scenario or expected result.
48860
+ results: []
48861
+ - id: testing.fixtures
48862
+ scope: applicable-file
48863
+ applies_when: Added or modified tests, fixtures, test setup, or test utility files.
48864
+ default_severity: consider
48865
+ issue: >-
48866
+ Repeated setup, unsuitable fixtures, or recreated shared utilities obscure tests or duplicate existing helpers.
48867
+ results: []
48868
+ - title: Documentation
48869
+ criteria:
48870
+ - id: documentation.conciseness
48871
+ scope: applicable-file
48872
+ applies_when: Added or modified documentation, including documentation comments.
48873
+ default_severity: consider
48874
+ issue: Long, dense, or complex text makes documentation hard to understand.
48875
+ results: []
48876
+ - id: documentation.redundancy
48877
+ scope: applicable-file
48878
+ applies_when: Added or modified documentation, including documentation comments.
48879
+ default_severity: consider
48880
+ issue: Documentation repeats the implementation or other text without adding useful context.
48881
+ results: []
48882
+ - id: documentation.visuals
48883
+ scope: applicable-file
48884
+ applies_when: Added or modified documentation that explains structures, flows, or relationships.
48885
+ default_severity: consider
48886
+ issue: A long textual explanation obscures information that a diagram would make clearer.
48887
+ results: []
48888
+ - title: Performance
48889
+ criteria:
48890
+ - id: performance.regressions
48891
+ scope: review
48892
+ default_severity: consider
48893
+ issue: The change causes a material performance regression.
48894
+ results: []
48895
+ - title: Security
48896
+ optional: true
48897
+ criteria:
48898
+ - id: security.defects
48899
+ scope: review
48900
+ default_severity: blocking
48901
+ issue: The change exposes secrets or breaks authorization or a trust boundary.
48902
+ results: []
48903
+ worker:
48904
+ reasoning_effort: high
48905
+ `;
48906
+ var init_code_review_rubric = () => {};
48907
+
48731
48908
  // templates/planning-intent.md
48732
48909
  var planning_intent_default = `# Intent: [short name]
48733
48910
 
@@ -49748,6 +49925,7 @@ var init_source = __esm(() => {
49748
49925
  init_product_requirements_document();
49749
49926
  init_agents();
49750
49927
  init_code_review();
49928
+ init_code_review_rubric();
49751
49929
  init_planning_intent();
49752
49930
  init_ui_component_architecture();
49753
49931
  init_pull_request_description();
@@ -49774,6 +49952,7 @@ var init_source = __esm(() => {
49774
49952
  "product-requirements-document.md": product_requirements_document_default,
49775
49953
  "agents.md": agents_default,
49776
49954
  "code-review.md": code_review_default,
49955
+ "code-review-rubric.yaml": code_review_rubric_default,
49777
49956
  "planning-intent.md": planning_intent_default,
49778
49957
  "ui-component-architecture.md": ui_component_architecture_default,
49779
49958
  "pull-request-description.md": pull_request_description_default,
@@ -49801,6 +49980,11 @@ var init_source = __esm(() => {
49801
49980
  { name: "product-requirements-document", description: "Product requirements document" },
49802
49981
  { name: "agents", description: "Concise repository rules for AGENTS.md" },
49803
49982
  { name: "code-review", description: "Thorough code review" },
49983
+ {
49984
+ name: "code-review-rubric",
49985
+ description: "YAML code review criteria and per-file results",
49986
+ asset: "code-review-rubric.yaml"
49987
+ },
49804
49988
  { name: "planning-intent", description: "Planning intent for a user to fill in" },
49805
49989
  { name: "ui-component-architecture", description: "UI component design and implementation" },
49806
49990
  { name: "pull-request-description", description: "Draft pull request description" },
@@ -49844,7 +50028,8 @@ class TemplateService {
49844
50028
  return [...this.source.catalog];
49845
50029
  }
49846
50030
  async scaffoldFromTemplate(name, cwd, path, filename) {
49847
- if (!this.source.catalog.some((item) => item.name === name)) {
50031
+ const template = this.source.catalog.find((item) => item.name === name);
50032
+ if (!template) {
49848
50033
  throw new UnknownTemplateError(`Unknown template: ${name}`);
49849
50034
  }
49850
50035
  if (!path.trim() || isAbsolute7(path)) {
@@ -49854,8 +50039,8 @@ class TemplateService {
49854
50039
  throw new TemplateError("filename must be a single non-empty file name");
49855
50040
  }
49856
50041
  await this.installMissing();
49857
- const installed = await resolvePath(this.home, join6(".difflab", "templates", `${name}.md`));
49858
- const contents = await readMarkdown(installed);
50042
+ const installed = await resolvePath(this.home, join6(".difflab", "templates", template.asset ?? `${name}.md`));
50043
+ const contents = await readTemplate(installed);
49859
50044
  const destination = path.startsWith(".difflab/") ? await this.projectDestination(cwd, path.slice(".difflab/".length), filename) : await ensurePathDirsExist(join6(path, filename), cwd);
49860
50045
  try {
49861
50046
  await createExclusive(destination, contents);
@@ -49888,7 +50073,7 @@ class TemplateService {
49888
50073
  if ((await lstat7(destination)).isSymbolicLink()) {
49889
50074
  throw new TemplateSourceError(`Installed template asset is a symlink: ${destination}`);
49890
50075
  }
49891
- await readMarkdown(destination);
50076
+ await readTemplate(destination);
49892
50077
  } catch (error) {
49893
50078
  if (!hasErrorCode(error, "ENOENT"))
49894
50079
  throw error;
@@ -49898,7 +50083,7 @@ class TemplateService {
49898
50083
  } catch (writeError) {
49899
50084
  if (!hasErrorCode(writeError, "EEXIST"))
49900
50085
  throw writeError;
49901
- await readMarkdown(destination);
50086
+ await readTemplate(destination);
49902
50087
  }
49903
50088
  }
49904
50089
  }
@@ -49916,7 +50101,7 @@ async function readSource(source, asset) {
49916
50101
  throw new TemplateSourceError(`Cannot read template asset: ${asset}`, { cause: error });
49917
50102
  }
49918
50103
  }
49919
- async function readMarkdown(path) {
50104
+ async function readTemplate(path) {
49920
50105
  let handle;
49921
50106
  try {
49922
50107
  handle = await open3(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
@@ -49974,7 +50159,8 @@ var init_tools4 = __esm(() => {
49974
50159
  init_service();
49975
50160
  templateInfo = object({
49976
50161
  name: string2(),
49977
- description: string2()
50162
+ description: string2(),
50163
+ asset: string2().optional()
49978
50164
  });
49979
50165
  templateListOutput = object({ result: array(templateInfo) });
49980
50166
  scaffoldOutput = object({
@@ -52366,7 +52552,7 @@ function createProgram(write = console.log, version = "0.1.0", options = {}) {
52366
52552
 
52367
52553
  // src/index.ts
52368
52554
  init_errors3();
52369
- var version2 = "0.10.0";
52555
+ var version2 = "0.11.0";
52370
52556
  try {
52371
52557
  await createProgram(console.log, version2).parseAsync(process.argv);
52372
52558
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@difflab/difflab-cli",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "description": "A minimal Bun CLI starter built with Commander",
6
6
  "license": "Apache-2.0",