@difflab/difflab-cli 0.5.0 → 0.7.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.
- package/README.md +21 -2
- package/dist/index.js +100 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,17 @@ Clients are selected explicitly. Supported names: `pi`, `cursor`, `codex`, `clau
|
|
|
46
46
|
|
|
47
47
|
MCP clients launch `npx -y @difflab/difflab-cli mcp serve` over stdio, so no daemon or port is needed. Bun must be on the client's PATH.
|
|
48
48
|
|
|
49
|
+
## MCP todo tools
|
|
50
|
+
|
|
51
|
+
`mcp setup` does **not** create a todo file. Use `todo_init` to create a list. Each todo call requires an absolute `cwd` pointing to an existing directory and a relative `path` to a JSON todo file inside it. For example:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
todo_init({"cwd":"/home/alex","path":"todos.json"})
|
|
55
|
+
todo_add({"cwd":"/home/alex","path":"todos.json","text":"Review PR"})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`todo_list`, `todo_complete`, and `todo_remove` also require both fields; the latter two require a task `id` returned by `todo_list` or `todo_add`. Call `todo_init` before other operations on a new file. Parent traversal outside `cwd`, absolute `path` values, and symlinked paths are rejected. Keep personal todo files outside the repository or add their paths to `.gitignore`. Concurrent writes to the same file are not yet coordinated. Agents can load `skills/difflab-todo/SKILL.md` for usage instructions.
|
|
59
|
+
|
|
49
60
|
## Document templates
|
|
50
61
|
|
|
51
62
|
List the available templates or scaffold a new document from one:
|
|
@@ -55,11 +66,19 @@ difflab-cli templates list
|
|
|
55
66
|
difflab-cli templates scaffold spec-driven-plan docs/plans first-plan.md --cwd /absolute/project/path
|
|
56
67
|
```
|
|
57
68
|
|
|
58
|
-
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`, `code-review`, `planning-intent`, `ui-component-architecture`,
|
|
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`, `code-review`, `planning-intent`, `ui-component-architecture`, `pull-request-description` (adapted from Diffpi's PR template), `flow-definition`, and `flow-instance`.
|
|
59
70
|
|
|
60
71
|
On first use, missing bundled templates and filled examples are copied to `~/.difflab/templates` and `~/.difflab/templates/examples`. Edit the installed templates to customize future documents. Later runs add missing files but never replace existing ones, even after an upgrade. Examples are for reference, not selectable templates. Copying is literal: prompts and placeholders are not substituted. An unknown name, missing or invalid source, unsafe path, symlink, or existing destination causes an error; destination files are never overwritten. The target directory must remain inside `cwd` and the filename must be a single file name without separators. The one symlink exception is an initialized repository's `.difflab` link to its own user project store: `templates scaffold spec-driven-plan .difflab/plans/YYMMDD-name PLAN.md --cwd /absolute/repo` works in Git worktrees as well. To restore a bundled default, move your installed copy aside before listing again.
|
|
61
72
|
|
|
62
|
-
The portable `skills/difflab-plan` and `skills/difflab-
|
|
73
|
+
The portable `skills/difflab-plan`, `skills/difflab-review`, and `skills/difflab-flow` directories contain natural-language agent workflows for these templates. Install each skill in your client's Agent Skills directory. The MCP-only `log_append({"path":"/absolute/physical/project-store/plans/YYMMDD-name/logs.txt","message":"Phase started"})` tool creates an append-only progress log on first use; pass the physical path, not the `.difflab` symlink. There is no log CLI command.
|
|
74
|
+
|
|
75
|
+
## Flow definitions and runs
|
|
76
|
+
|
|
77
|
+
`flow new <name>` and `flow go <name>` are Agent Skill requests, not CLI subcommands. The agent creates a definition once at `~/.difflab/flows/<name>.md`. It calls MCP `scaffold` with `cwd=<absolute home>/.difflab`, `path="flows"`, and `filename="<name>.md"`. Do not use `cwd=<home>,path=".difflab/flows"`: that route is for a repository project store. You can edit a definition before another run. A new run uses a fresh snapshot and does not alter old runs.
|
|
78
|
+
|
|
79
|
+
From an initialized repository, ask “flow go autospec with input 'Export monthly sales' --local”. The agent selects one branch and creates `.difflab/flows/YYMMDD-autospec/FLOW.md`. It keeps inputs, selected permissions, step checkboxes, and verified outputs for later steps in that file. A same-day path requires an explicit resume choice or a distinct run ID. The first unchecked step is the resume point. The physical project-store path to the sibling `logs.txt` receives timestamped entries through MCP `log_append` only. The definition remains unchanged.
|
|
80
|
+
|
|
81
|
+
`--local` removes remote steps before creating the run. `--commit` permits only an explicitly declared local commit step when passed, and never permits a push. Remote review needs separate permission and the review skill's forge checks. Plan and review skills still control their own operations; a flow cannot override them. Merge is not supported as a flow step. Example definitions live in `skills/difflab-flow/examples/`.
|
|
63
82
|
|
|
64
83
|
## Develop
|
|
65
84
|
|
package/dist/index.js
CHANGED
|
@@ -48712,6 +48712,97 @@ var pull_request_description_default = `## Intent
|
|
|
48712
48712
|
`;
|
|
48713
48713
|
var init_pull_request_description = () => {};
|
|
48714
48714
|
|
|
48715
|
+
// templates/flow-definition.md
|
|
48716
|
+
var flow_definition_default = `# {{name}}
|
|
48717
|
+
|
|
48718
|
+
## Intent
|
|
48719
|
+
|
|
48720
|
+
{{intent}}
|
|
48721
|
+
|
|
48722
|
+
## Inputs
|
|
48723
|
+
|
|
48724
|
+
| Name | Required | Default | Description |
|
|
48725
|
+
| ----- | -------- | ------- | ------------------------------------------ |
|
|
48726
|
+
| input | yes | \u2014 | Free-form user request; bind as one value. |
|
|
48727
|
+
|
|
48728
|
+
## Flags
|
|
48729
|
+
|
|
48730
|
+
| Flag | Default | Capability | Effect |
|
|
48731
|
+
| --------------- | ------- | ------------- | ---------------------------------------------------------------------------------- |
|
|
48732
|
+
| --local | false | local | Omit steps with \`unless: --local\`; never forward to every skill. |
|
|
48733
|
+
| --commit | false | local-commit | Permit only explicitly commit-capable selected steps to make scoped local commits. |
|
|
48734
|
+
| --remote-review | false | remote-review | Opt in to remote review with independent forge authorization. |
|
|
48735
|
+
|
|
48736
|
+
## Steps
|
|
48737
|
+
|
|
48738
|
+
### 1. {{step-id}}
|
|
48739
|
+
|
|
48740
|
+
- Handler: \`plan new\`
|
|
48741
|
+
- When: always
|
|
48742
|
+
- Unless: never
|
|
48743
|
+
- Requires: local
|
|
48744
|
+
- Receives: \`{{input}}\`
|
|
48745
|
+
- Produces: \`plan_path\` (verified path to the created plan)
|
|
48746
|
+
- Instructions: {{step-instructions}}
|
|
48747
|
+
|
|
48748
|
+
### 2. {{next-step-id}}
|
|
48749
|
+
|
|
48750
|
+
- Handler: \`review new\`
|
|
48751
|
+
- When: \`--remote-review\`
|
|
48752
|
+
- Unless: \`--local\`
|
|
48753
|
+
- Requires: remote-review
|
|
48754
|
+
- Receives: \`{{steps.step-id.plan_path}}\`
|
|
48755
|
+
- Produces: \`review_path\` (verified review artifact)
|
|
48756
|
+
- Instructions: {{step-instructions}}
|
|
48757
|
+
|
|
48758
|
+
## Contract
|
|
48759
|
+
|
|
48760
|
+
Replace example rows and steps when creating a definition. Use stable unique lower-case hyphenated input and step IDs; output names may also contain underscores (\`^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$\`). Declare every input, flag, capability, output and condition. \`When\` and \`Unless\` accept only \`always\`, \`never\`, or one declared flag; no expressions, shell interpolation or implicit flags. The only tokens are \`{{input-name}}\` and \`{{steps.step-id.output-name}}\`. A later step can consume only an earlier declared output, verified when that step finishes. Define any remote or commit capability explicitly and require its independent opt-in flag. This file is reusable and has no run state; editing it affects future runs only.
|
|
48761
|
+
`;
|
|
48762
|
+
var init_flow_definition = () => {};
|
|
48763
|
+
|
|
48764
|
+
// templates/flow-instance.md
|
|
48765
|
+
var flow_instance_default = `# Flow run: {{name}}
|
|
48766
|
+
|
|
48767
|
+
- **Status:** in progress
|
|
48768
|
+
- **Definition:** {{absolute-definition-path}}
|
|
48769
|
+
- **Definition SHA-256:** {{definition-sha256}}
|
|
48770
|
+
- **Repository:** {{absolute-repository-root}}
|
|
48771
|
+
- **Run ID:** {{run-id}}
|
|
48772
|
+
|
|
48773
|
+
## Resolved inputs
|
|
48774
|
+
|
|
48775
|
+
| Input | Value |
|
|
48776
|
+
| ----- | --------- |
|
|
48777
|
+
| input | {{input}} |
|
|
48778
|
+
|
|
48779
|
+
## Selected flags and permissions
|
|
48780
|
+
|
|
48781
|
+
{{flags-and-capabilities}}
|
|
48782
|
+
|
|
48783
|
+
## Selection provenance
|
|
48784
|
+
|
|
48785
|
+
{{omitted-step-ids-and-reasons-only-no-instructions}}
|
|
48786
|
+
|
|
48787
|
+
## Steps
|
|
48788
|
+
|
|
48789
|
+
- [ ] 1. {{selected-step-id}} \u2014 {{resolved-handler}}
|
|
48790
|
+
- Requires: {{authorized-capability}}
|
|
48791
|
+
- Instructions: {{resolved-instructions}}
|
|
48792
|
+
- Receives: {{concrete-input-or-prior-step-handoff}}
|
|
48793
|
+
- Expected output: {{declared-output-name}}
|
|
48794
|
+
- Result/handoff: pending
|
|
48795
|
+
|
|
48796
|
+
## Blocker
|
|
48797
|
+
|
|
48798
|
+
None.
|
|
48799
|
+
|
|
48800
|
+
## Contract
|
|
48801
|
+
|
|
48802
|
+
This is the frozen execution snapshot. Include only selected executable steps; never copy unselected instructions here. Resolve all declared inputs before creating this file. References to earlier step outputs are typed handoff slots, filled only from verified results when those steps complete. Check a step only after success; on failure leave it unchecked, record the blocker and stop. Resume this exact instance at its first unchecked step without rereading the global definition.
|
|
48803
|
+
`;
|
|
48804
|
+
var init_flow_instance = () => {};
|
|
48805
|
+
|
|
48715
48806
|
// templates/examples/plan-feature.md
|
|
48716
48807
|
var plan_feature_default = `# Invite teammates to a project
|
|
48717
48808
|
|
|
@@ -49227,6 +49318,8 @@ var init_source = __esm(() => {
|
|
|
49227
49318
|
init_planning_intent();
|
|
49228
49319
|
init_ui_component_architecture();
|
|
49229
49320
|
init_pull_request_description();
|
|
49321
|
+
init_flow_definition();
|
|
49322
|
+
init_flow_instance();
|
|
49230
49323
|
init_plan_feature();
|
|
49231
49324
|
init_plan_migration();
|
|
49232
49325
|
init_design_service();
|
|
@@ -49245,7 +49338,9 @@ var init_source = __esm(() => {
|
|
|
49245
49338
|
{ name: "code-review", description: "Thorough code review" },
|
|
49246
49339
|
{ name: "planning-intent", description: "Planning intent for a user to fill in" },
|
|
49247
49340
|
{ name: "ui-component-architecture", description: "UI component design and implementation" },
|
|
49248
|
-
{ name: "pull-request-description", description: "Draft pull request description" }
|
|
49341
|
+
{ name: "pull-request-description", description: "Draft pull request description" },
|
|
49342
|
+
{ name: "flow-definition", description: "Reusable global Agent Skill flow definition" },
|
|
49343
|
+
{ name: "flow-instance", description: "Frozen repository-local flow run" }
|
|
49249
49344
|
];
|
|
49250
49345
|
contents = {
|
|
49251
49346
|
"spec-driven-plan.md": spec_driven_plan_default,
|
|
@@ -49256,6 +49351,8 @@ var init_source = __esm(() => {
|
|
|
49256
49351
|
"planning-intent.md": planning_intent_default,
|
|
49257
49352
|
"ui-component-architecture.md": ui_component_architecture_default,
|
|
49258
49353
|
"pull-request-description.md": pull_request_description_default,
|
|
49354
|
+
"flow-definition.md": flow_definition_default,
|
|
49355
|
+
"flow-instance.md": flow_instance_default,
|
|
49259
49356
|
"examples/plan-feature.md": plan_feature_default,
|
|
49260
49357
|
"examples/plan-migration.md": plan_migration_default,
|
|
49261
49358
|
"examples/design-service.md": design_service_default,
|
|
@@ -49438,7 +49535,7 @@ var init_tools4 = __esm(() => {
|
|
|
49438
49535
|
});
|
|
49439
49536
|
templateTools = [
|
|
49440
49537
|
defineTool("template_list", {
|
|
49441
|
-
description: "List
|
|
49538
|
+
description: "List document templates, including flow definitions and instances; install any missing defaults and examples in the user templates directory without overwriting local edits.",
|
|
49442
49539
|
inputSchema: strictObject({}),
|
|
49443
49540
|
outputSchema: templateListOutput,
|
|
49444
49541
|
annotations: { openWorldHint: false }
|
|
@@ -51816,7 +51913,7 @@ function createProgram(write = console.log, version = "0.1.0", options = {}) {
|
|
|
51816
51913
|
|
|
51817
51914
|
// src/index.ts
|
|
51818
51915
|
init_errors3();
|
|
51819
|
-
var version2 = "0.
|
|
51916
|
+
var version2 = "0.7.0";
|
|
51820
51917
|
try {
|
|
51821
51918
|
await createProgram(console.log, version2).parseAsync(process.argv);
|
|
51822
51919
|
} catch (error) {
|