@fledge/workflow 0.5.0 → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { i as runMain, n as writeFrontmatter, r as defineCommand, t as parseFrontmatter } from "./frontmatter-BUnjSmTA.js";
3
- import { cwd, env, stdout } from "node:process";
3
+ import { cwd, stdout } from "node:process";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  Object.freeze({ status: "aborted" });
@@ -3679,90 +3679,98 @@ const tasksFrontmatter = object({ tasks: array(object({
3679
3679
  //#region ../cli/dist/brief.js
3680
3680
  const BRIEFS_DIRECTORY = path.join(".fledge", "briefs");
3681
3681
  /**
3682
- * Returns the project root directory.
3683
- * Uses the `FLEDGE_PROJECT_DIR` environment variable if set, otherwise falls back to `cwd()`.
3682
+ * Creates a BriefContext from a project directory path or falls back to `cwd()`.
3684
3683
  *
3685
- * @returns The absolute path to the project root.
3684
+ * @param projectDirectory - Optional project root override.
3685
+ * @returns A BriefContext with the resolved project root.
3686
3686
  */
3687
- function getProjectRoot() {
3688
- return env.FLEDGE_PROJECT_DIR || cwd();
3687
+ function createBriefContext(projectDirectory) {
3688
+ return { projectRoot: projectDirectory ? path.resolve(projectDirectory) : cwd() };
3689
3689
  }
3690
3690
  /**
3691
- * Returns the absolute path to the briefs directory for the current project.
3691
+ * Returns the absolute path to the briefs directory for the given context.
3692
3692
  *
3693
+ * @param context - The brief context.
3693
3694
  * @returns The absolute path to `.fledge/briefs/` in the project root.
3694
3695
  */
3695
- function getBriefsDirectory() {
3696
- return path.join(getProjectRoot(), BRIEFS_DIRECTORY);
3696
+ function getBriefsDirectory(context) {
3697
+ return path.join(context.projectRoot, BRIEFS_DIRECTORY);
3697
3698
  }
3698
3699
  /**
3699
3700
  * Returns the absolute path to a specific brief's directory.
3700
3701
  *
3702
+ * @param context - The brief context.
3701
3703
  * @param name - The brief name (used as directory name).
3702
3704
  * @returns The absolute path to the brief directory.
3703
3705
  */
3704
- function getBriefDirectory(name) {
3705
- return path.join(getBriefsDirectory(), name);
3706
+ function getBriefDirectory(context, name) {
3707
+ return path.join(getBriefsDirectory(context), name);
3706
3708
  }
3707
3709
  /**
3708
3710
  * Returns the absolute path to a brief's `brief.md` file.
3709
3711
  *
3712
+ * @param context - The brief context.
3710
3713
  * @param name - The brief name.
3711
3714
  * @returns The absolute path to `brief.md`.
3712
3715
  */
3713
- function getBriefFile(name) {
3714
- return path.join(getBriefDirectory(name), "brief.md");
3716
+ function getBriefFile(context, name) {
3717
+ return path.join(getBriefDirectory(context, name), "brief.md");
3715
3718
  }
3716
3719
  /**
3717
3720
  * Returns the absolute path to a brief's `tasks.md` file.
3718
3721
  *
3722
+ * @param context - The brief context.
3719
3723
  * @param name - The brief name.
3720
3724
  * @returns The absolute path to `tasks.md`.
3721
3725
  */
3722
- function getTasksFile(name) {
3723
- return path.join(getBriefDirectory(name), "tasks.md");
3726
+ function getTasksFile(context, name) {
3727
+ return path.join(getBriefDirectory(context, name), "tasks.md");
3724
3728
  }
3725
3729
  /**
3726
3730
  * Checks whether a brief directory exists.
3727
3731
  *
3732
+ * @param context - The brief context.
3728
3733
  * @param name - The brief name.
3729
3734
  * @returns `true` if the brief directory exists.
3730
3735
  */
3731
- function briefExists(name) {
3732
- return fs.existsSync(getBriefDirectory(name));
3736
+ function briefExists(context, name) {
3737
+ return fs.existsSync(getBriefDirectory(context, name));
3733
3738
  }
3734
3739
  /**
3735
3740
  * Reads and validates the frontmatter of a brief's `brief.md` file.
3736
3741
  *
3742
+ * @param context - The brief context.
3737
3743
  * @param name - The brief name.
3738
3744
  * @returns The validated brief frontmatter.
3739
3745
  * @throws If the file does not exist or frontmatter fails validation.
3740
3746
  */
3741
- function readBriefFrontmatter(name) {
3742
- const content = fs.readFileSync(getBriefFile(name), "utf8");
3747
+ function readBriefFrontmatter(context, name) {
3748
+ const content = fs.readFileSync(getBriefFile(context, name), "utf8");
3743
3749
  return briefFrontmatter.parse(parseFrontmatter(content));
3744
3750
  }
3745
3751
  /**
3746
3752
  * Reads and validates the frontmatter of a brief's `tasks.md` file.
3747
3753
  *
3754
+ * @param context - The brief context.
3748
3755
  * @param name - The brief name.
3749
3756
  * @returns The validated tasks frontmatter.
3750
3757
  * @throws If the file does not exist or frontmatter fails validation.
3751
3758
  */
3752
- function readTasksFrontmatter(name) {
3753
- const content = fs.readFileSync(getTasksFile(name), "utf8");
3759
+ function readTasksFrontmatter(context, name) {
3760
+ const content = fs.readFileSync(getTasksFile(context, name), "utf8");
3754
3761
  return tasksFrontmatter.parse(parseFrontmatter(content));
3755
3762
  }
3756
3763
  /**
3757
3764
  * Updates the frontmatter of a brief's `brief.md` file while preserving its body content.
3758
3765
  *
3766
+ * @param context - The brief context.
3759
3767
  * @param name - The brief name.
3760
3768
  * @param data - The new frontmatter data to write.
3761
3769
  */
3762
- function updateBriefFrontmatter(name, data) {
3763
- const briefFile = getBriefFile(name);
3764
- const content = fs.readFileSync(briefFile, "utf8");
3765
- fs.writeFileSync(briefFile, writeFrontmatter(data, content));
3770
+ function updateBriefFrontmatter(context, name, data) {
3771
+ const file = getBriefFile(context, name);
3772
+ const content = fs.readFileSync(file, "utf8");
3773
+ fs.writeFileSync(file, writeFrontmatter(data, content));
3766
3774
  }
3767
3775
  /**
3768
3776
  * Validates that a state transition is allowed and throws a descriptive error if not.
@@ -3789,37 +3797,52 @@ function formatDate() {
3789
3797
  /**
3790
3798
  * Lists all brief directories in the project.
3791
3799
  *
3800
+ * @param context - The brief context.
3792
3801
  * @returns An array of brief names (directory names).
3793
3802
  */
3794
- function listBriefs() {
3795
- const directory = getBriefsDirectory();
3803
+ function listBriefs(context) {
3804
+ const directory = getBriefsDirectory(context);
3796
3805
  if (!fs.existsSync(directory)) return [];
3797
3806
  return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
3798
3807
  }
3799
3808
  //#endregion
3809
+ //#region ../cli/dist/commands/brief/shared.js
3810
+ /**
3811
+ * Shared argument definition for the `--project-dir` flag used by all brief subcommands.
3812
+ */
3813
+ const projectDirectory = {
3814
+ required: false,
3815
+ alias: "project-dir",
3816
+ description: "Project root directory. Overrides cwd() for locating .fledge/briefs/."
3817
+ };
3818
+ //#endregion
3800
3819
  //#region ../cli/dist/commands/brief/complete.js
3801
3820
  var complete_default = defineCommand({
3802
3821
  meta: {
3803
3822
  name: "complete",
3804
3823
  description: "Transition a brief from active to completed"
3805
3824
  },
3806
- args: { name: {
3807
- type: "positional",
3808
- required: true,
3809
- description: "The name of the brief to complete"
3810
- } },
3825
+ args: {
3826
+ name: {
3827
+ type: "positional",
3828
+ required: true,
3829
+ description: "The name of the brief to complete"
3830
+ },
3831
+ projectDirectory
3832
+ },
3811
3833
  run(context) {
3834
+ const ctx = createBriefContext(context.args.projectDirectory);
3812
3835
  const { name } = context.args;
3813
- if (!briefExists(name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(name)}"`);
3814
- const brief = readBriefFrontmatter(name);
3836
+ if (!briefExists(ctx, name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(ctx, name)}"`);
3837
+ const brief = readBriefFrontmatter(ctx, name);
3815
3838
  validateTransition(brief.status, "completed");
3816
3839
  if (!brief.summary) throw new Error("Brief must have a summary before completing. Add a \"summary\" field to the brief.md frontmatter.");
3817
- const incomplete = readTasksFrontmatter(name).tasks.filter((task) => !task.done);
3840
+ const incomplete = readTasksFrontmatter(ctx, name).tasks.filter((task) => !task.done);
3818
3841
  if (incomplete.length > 0) {
3819
3842
  const names = incomplete.map((task) => ` - ${task.name}`).join("\n");
3820
3843
  throw new Error(`Cannot complete brief with ${incomplete.length} incomplete task(s):\n${names}`);
3821
3844
  }
3822
- updateBriefFrontmatter(name, {
3845
+ updateBriefFrontmatter(ctx, name, {
3823
3846
  ...brief,
3824
3847
  status: "completed",
3825
3848
  updated: formatDate()
@@ -3834,24 +3857,28 @@ var create_default = defineCommand({
3834
3857
  name: "create",
3835
3858
  description: "Create a new brief with stub files"
3836
3859
  },
3837
- args: { name: {
3838
- type: "positional",
3839
- required: true,
3840
- description: "The name of the brief to create (used as directory name)"
3841
- } },
3860
+ args: {
3861
+ name: {
3862
+ type: "positional",
3863
+ required: true,
3864
+ description: "The name of the brief to create (used as directory name)"
3865
+ },
3866
+ projectDirectory
3867
+ },
3842
3868
  run(context) {
3869
+ const ctx = createBriefContext(context.args.projectDirectory);
3843
3870
  const { name } = context.args;
3844
- if (briefExists(name)) throw new Error(`Brief "${name}" already exists at "${getBriefDirectory(name)}"`);
3845
- const directory = getBriefDirectory(name);
3871
+ if (briefExists(ctx, name)) throw new Error(`Brief "${name}" already exists at "${getBriefDirectory(ctx, name)}"`);
3872
+ const directory = getBriefDirectory(ctx, name);
3846
3873
  fs.mkdirSync(directory, { recursive: true });
3847
3874
  const date = formatDate();
3848
- fs.writeFileSync(getBriefFile(name), writeFrontmatter({
3875
+ fs.writeFileSync(getBriefFile(ctx, name), writeFrontmatter({
3849
3876
  name,
3850
3877
  status: "draft",
3851
3878
  created: date,
3852
3879
  updated: date
3853
3880
  }));
3854
- fs.writeFileSync(getTasksFile(name), writeFrontmatter({ tasks: [] }));
3881
+ fs.writeFileSync(getTasksFile(ctx, name), writeFrontmatter({ tasks: [] }));
3855
3882
  stdout.write(`Created brief "${name}" at "${directory}"\n`);
3856
3883
  }
3857
3884
  });
@@ -3862,20 +3889,24 @@ var list_default = defineCommand({
3862
3889
  name: "list",
3863
3890
  description: "List all briefs with their status and progress"
3864
3891
  },
3865
- args: { status: {
3866
- type: "string",
3867
- required: false,
3868
- description: "Filter by brief status (draft, active, completed)"
3869
- } },
3892
+ args: {
3893
+ status: {
3894
+ type: "string",
3895
+ required: false,
3896
+ description: "Filter by brief status (draft, active, completed)"
3897
+ },
3898
+ projectDirectory
3899
+ },
3870
3900
  run(context) {
3871
- const names = listBriefs();
3901
+ const ctx = createBriefContext(context.args.projectDirectory);
3902
+ const names = listBriefs(ctx);
3872
3903
  if (names.length === 0) {
3873
3904
  stdout.write("No briefs found\n");
3874
3905
  return;
3875
3906
  }
3876
3907
  let briefs = names.map((name) => {
3877
- const brief = readBriefFrontmatter(name);
3878
- const { tasks } = readTasksFrontmatter(name);
3908
+ const brief = readBriefFrontmatter(ctx, name);
3909
+ const { tasks } = readTasksFrontmatter(ctx, name);
3879
3910
  const done = tasks.filter((task) => task.done).length;
3880
3911
  return {
3881
3912
  ...brief,
@@ -3925,18 +3956,22 @@ var start_default = defineCommand({
3925
3956
  name: "start",
3926
3957
  description: "Transition a brief from draft to active"
3927
3958
  },
3928
- args: { name: {
3929
- type: "positional",
3930
- required: true,
3931
- description: "The name of the brief to start"
3932
- } },
3959
+ args: {
3960
+ name: {
3961
+ type: "positional",
3962
+ required: true,
3963
+ description: "The name of the brief to start"
3964
+ },
3965
+ projectDirectory
3966
+ },
3933
3967
  run(context) {
3968
+ const ctx = createBriefContext(context.args.projectDirectory);
3934
3969
  const { name } = context.args;
3935
- if (!briefExists(name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(name)}"`);
3936
- const brief = readBriefFrontmatter(name);
3970
+ if (!briefExists(ctx, name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(ctx, name)}"`);
3971
+ const brief = readBriefFrontmatter(ctx, name);
3937
3972
  validateTransition(brief.status, "active");
3938
- if (readTasksFrontmatter(name).tasks.length === 0) throw new Error("Brief must have at least one task before starting");
3939
- updateBriefFrontmatter(name, {
3973
+ if (readTasksFrontmatter(ctx, name).tasks.length === 0) throw new Error("Brief must have at least one task before starting");
3974
+ updateBriefFrontmatter(ctx, name, {
3940
3975
  ...brief,
3941
3976
  status: "active",
3942
3977
  updated: formatDate()
@@ -3989,24 +4024,28 @@ runMain(defineCommand({
3989
4024
  name: "status",
3990
4025
  description: "Show the status and task progress of a brief"
3991
4026
  },
3992
- args: { name: {
3993
- type: "positional",
3994
- required: true,
3995
- description: "The name of the brief to show status for"
3996
- } },
4027
+ args: {
4028
+ name: {
4029
+ type: "positional",
4030
+ required: true,
4031
+ description: "The name of the brief to show status for"
4032
+ },
4033
+ projectDirectory
4034
+ },
3997
4035
  run(context) {
4036
+ const ctx = createBriefContext(context.args.projectDirectory);
3998
4037
  const { name } = context.args;
3999
- if (!briefExists(name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(name)}"`);
4000
- const brief = readBriefFrontmatter(name);
4001
- const { tasks } = readTasksFrontmatter(name);
4038
+ if (!briefExists(ctx, name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(ctx, name)}"`);
4039
+ const brief = readBriefFrontmatter(ctx, name);
4040
+ const { tasks } = readTasksFrontmatter(ctx, name);
4002
4041
  const done = tasks.filter((task) => task.done).length;
4003
4042
  const lines = [];
4004
4043
  lines.push(`${name} [${brief.status}] ${done}/${tasks.length} tasks done`);
4005
4044
  lines.push("");
4006
4045
  const groups = groupTasks(tasks);
4007
- for (const [group, groupTasks] of groups) {
4046
+ for (const [group, groupedTasks] of groups) {
4008
4047
  if (group) lines.push(group);
4009
- for (const task of groupTasks) lines.push(formatTask(task));
4048
+ for (const task of groupedTasks) lines.push(formatTask(task));
4010
4049
  }
4011
4050
  stdout.write(`${lines.join("\n")}\n`);
4012
4051
  }
@@ -4016,19 +4055,23 @@ runMain(defineCommand({
4016
4055
  name: "validate",
4017
4056
  description: "Validate brief and tasks files against their schemas"
4018
4057
  },
4019
- args: { name: {
4020
- type: "positional",
4021
- required: true,
4022
- description: "The name of the brief to validate"
4023
- } },
4058
+ args: {
4059
+ name: {
4060
+ type: "positional",
4061
+ required: true,
4062
+ description: "The name of the brief to validate"
4063
+ },
4064
+ projectDirectory
4065
+ },
4024
4066
  run(context) {
4067
+ const ctx = createBriefContext(context.args.projectDirectory);
4025
4068
  const { name } = context.args;
4026
- if (!briefExists(name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(name)}"`);
4069
+ if (!briefExists(ctx, name)) throw new Error(`Brief "${name}" does not exist at "${getBriefDirectory(ctx, name)}"`);
4027
4070
  const errors = [];
4028
- const briefContent = fs.readFileSync(getBriefFile(name), "utf8");
4071
+ const briefContent = fs.readFileSync(getBriefFile(ctx, name), "utf8");
4029
4072
  const briefResult = briefFrontmatter.safeParse(parseFrontmatter(briefContent));
4030
4073
  if (!briefResult.success) for (const issue of briefResult.error.issues) errors.push(`brief.md: ${issue.path.join(".")}: ${issue.message}`);
4031
- const tasksContent = fs.readFileSync(getTasksFile(name), "utf8");
4074
+ const tasksContent = fs.readFileSync(getTasksFile(ctx, name), "utf8");
4032
4075
  const tasksResult = tasksFrontmatter.safeParse(parseFrontmatter(tasksContent));
4033
4076
  if (!tasksResult.success) for (const issue of tasksResult.error.issues) errors.push(`tasks.md: ${issue.path.join(".")}: ${issue.message}`);
4034
4077
  if (errors.length > 0) throw new Error(`Validation failed for "${name}":\n${errors.map((error) => ` - ${error}`).join("\n")}`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fledge/workflow",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.6.1",
5
5
  "author": "René Schapka",
6
6
  "license": "MIT",
7
7
  "files": [
@@ -15,7 +15,7 @@
15
15
  "node": ">=24"
16
16
  },
17
17
  "dependencies": {
18
- "@fledge/cli": "^0.8.0"
18
+ "@fledge/cli": "^0.9.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@antfu/eslint-config": "7.7.3",
@@ -5,28 +5,19 @@ description: >-
5
5
  Invoked directly via /fledge-brief, not auto-triggered.
6
6
  metadata:
7
7
  type: workflow
8
+ allowed-tools: Bash(scripts/brief.js *), Bash(node *)
8
9
  ---
9
10
 
10
- ## Setup
11
-
12
- Before running any script, set the `FLEDGE_PROJECT_DIR` environment variable to the project root so scripts know where to find and create briefs:
13
-
14
- ```bash
15
- export FLEDGE_PROJECT_DIR="$(pwd)"
16
- ```
17
-
18
- Set this once at the start of the conversation. All scripts below assume it is set.
19
-
20
11
  ## Available scripts
21
12
 
22
- Self-contained executable scripts bundled with this skill:
13
+ **Important:** All scripts have a shebang and are executable. Run them directly (e.g. `scripts/brief.js list`), never prefix with `node`. Always pass `--project-dir` pointing to the project root.
23
14
 
24
- - **`scripts/brief.js create <name>`** -- Create a new brief with stub files
25
- - **`scripts/brief.js start <name>`** -- Transition a brief from draft to active
26
- - **`scripts/brief.js complete <name>`** -- Transition a brief from active to completed
27
- - **`scripts/brief.js status <name>`** -- Show status and task progress
28
- - **`scripts/brief.js list [--status <status>]`** -- List all briefs with progress and summary
29
- - **`scripts/brief.js validate <name>`** -- Validate brief files against schemas
15
+ - **`scripts/brief.js create <name> --project-dir <path>`** -- Create a new brief with stub files
16
+ - **`scripts/brief.js start <name> --project-dir <path>`** -- Transition a brief from draft to active
17
+ - **`scripts/brief.js complete <name> --project-dir <path>`** -- Transition a brief from active to completed
18
+ - **`scripts/brief.js status <name> --project-dir <path>`** -- Show status and task progress
19
+ - **`scripts/brief.js list [--status <status>] --project-dir <path>`** -- List all briefs with progress and summary
20
+ - **`scripts/brief.js validate <name> --project-dir <path>`** -- Validate brief files against schemas
30
21
  - **`scripts/brief.js schema`** -- Output JSON Schema for brief and tasks frontmatter
31
22
 
32
23
  ## Step 0: Determine intent
@@ -37,7 +28,7 @@ Ask what the user wants to do, or infer from context. Present these options:
37
28
  2. **Continue a brief** -- pick up an existing brief. Proceed to Step 4.
38
29
  3. **Complete a brief** -- wrap up a finished feature. Proceed to Step 5.
39
30
 
40
- If unclear, run `scripts/brief.js list` to show current briefs and ask.
31
+ If unclear, run `scripts/brief.js list --project-dir <path>` to show current briefs and ask.
41
32
 
42
33
  ---
43
34
 
@@ -45,7 +36,7 @@ If unclear, run `scripts/brief.js list` to show current briefs and ask.
45
36
 
46
37
  Before writing anything, build an understanding of what exists.
47
38
 
48
- 1. Run `scripts/brief.js list --status completed` to read summaries of completed features. Note anything relevant to the new feature.
39
+ 1. Run `scripts/brief.js list --status completed --project-dir <path>` to read summaries of completed features. Note anything relevant to the new feature.
49
40
  2. Ask the user what they want to build. Keep it conversational, not a form. Aim to understand:
50
41
  - What is the user-facing change?
51
42
  - Why does it matter?
@@ -60,7 +51,7 @@ Proceed to Step 2.
60
51
 
61
52
  ## Step 2: Draft the brief
62
53
 
63
- Run `scripts/brief.js create <name>` to create the brief directory.
54
+ Run `scripts/brief.js create <name> --project-dir <path>` to create the brief directory.
64
55
 
65
56
  Write the brief content into `brief.md`. The frontmatter is managed by the scripts. The markdown body should capture:
66
57
 
@@ -96,7 +87,7 @@ tasks:
96
87
 
97
88
  Order tasks by dependency: tasks that others depend on come first within their group.
98
89
 
99
- After writing tasks, run `scripts/brief.js validate <name>` to confirm the brief is valid, then run `scripts/brief.js start <name>` to transition to active.
90
+ After writing tasks, run `scripts/brief.js validate <name> --project-dir <path>` to confirm the brief is valid, then run `scripts/brief.js start <name> --project-dir <path>` to transition to active.
100
91
 
101
92
  Present the complete brief and task list to the user for review before starting.
102
93
 
@@ -104,22 +95,22 @@ Present the complete brief and task list to the user for review before starting.
104
95
 
105
96
  ## Step 4: Continue a brief
106
97
 
107
- Run `scripts/brief.js list` to show all briefs. If the user does not specify which brief, ask them to pick one.
98
+ Run `scripts/brief.js list --project-dir <path>` to show all briefs. If the user does not specify which brief, ask them to pick one.
108
99
 
109
- Run `scripts/brief.js status <name>` to show progress. Read the brief and tasks files to understand the full context.
100
+ Run `scripts/brief.js status <name> --project-dir <path>` to show progress. Read the brief and tasks files to understand the full context.
110
101
 
111
102
  From here, the user may want to:
112
103
  - **Discuss a task** -- talk through approach before implementing
113
104
  - **Update tasks** -- mark tasks as done, add new tasks, reorder
114
105
  - **Revise the brief** -- update scope or design decisions based on what was learned during implementation
115
106
 
116
- When updating task status, modify the `tasks.md` frontmatter directly, then run `scripts/brief.js status <name>` to confirm the update.
107
+ When updating task status, modify the `tasks.md` frontmatter directly, then run `scripts/brief.js status <name> --project-dir <path>` to confirm the update.
117
108
 
118
109
  ---
119
110
 
120
111
  ## Step 5: Complete a brief
121
112
 
122
- Run `scripts/brief.js status <name>` to verify all tasks are done.
113
+ Run `scripts/brief.js status <name> --project-dir <path>` to verify all tasks are done.
123
114
 
124
115
  If there are incomplete tasks, ask the user whether to:
125
116
  1. Mark remaining tasks as done (if they were completed outside this conversation)
@@ -130,4 +121,4 @@ Write a summary into the `brief.md` frontmatter `summary` field. The summary sho
130
121
  - What was built
131
122
  - Key decisions or patterns established that future features should know about
132
123
 
133
- Run `scripts/brief.js complete <name>` to transition to completed. The script validates that all tasks are done and the summary is present.
124
+ Run `scripts/brief.js complete <name> --project-dir <path>` to transition to completed. The script validates that all tasks are done and the summary is present.