@lumenflow/cli 2.4.0 → 2.5.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.
- package/README.md +11 -8
- package/dist/__tests__/init-config-lanes.test.js +131 -0
- package/dist/__tests__/init-docs-structure.test.js +119 -0
- package/dist/__tests__/init-lane-inference.test.js +125 -0
- package/dist/__tests__/init-onboarding-docs.test.js +132 -0
- package/dist/__tests__/init-quick-ref.test.js +145 -0
- package/dist/__tests__/init-scripts.test.js +207 -0
- package/dist/__tests__/init-template-portability.test.js +97 -0
- package/dist/__tests__/init.test.js +7 -2
- package/dist/__tests__/initiative-add-wu.test.js +420 -0
- package/dist/__tests__/initiative-plan-replacement.test.js +162 -0
- package/dist/__tests__/initiative-remove-wu.test.js +458 -0
- package/dist/__tests__/onboarding-smoke-test.test.js +211 -0
- package/dist/__tests__/path-centralization-cli.test.js +234 -0
- package/dist/__tests__/plan-create.test.js +126 -0
- package/dist/__tests__/plan-edit.test.js +157 -0
- package/dist/__tests__/plan-link.test.js +239 -0
- package/dist/__tests__/plan-promote.test.js +181 -0
- package/dist/__tests__/templates-sync.test.js +219 -0
- package/dist/__tests__/wu-create-strict.test.js +118 -0
- package/dist/__tests__/wu-edit-strict.test.js +109 -0
- package/dist/__tests__/wu-validate-strict.test.js +113 -0
- package/dist/flow-bottlenecks.js +4 -2
- package/dist/gates.js +22 -0
- package/dist/init.js +670 -87
- package/dist/initiative-add-wu.js +112 -16
- package/dist/initiative-remove-wu.js +248 -0
- package/dist/onboarding-smoke-test.js +400 -0
- package/dist/orchestrate-init-status.js +37 -9
- package/dist/orchestrate-initiative.js +10 -4
- package/dist/plan-create.js +199 -0
- package/dist/plan-edit.js +235 -0
- package/dist/plan-link.js +233 -0
- package/dist/plan-promote.js +231 -0
- package/dist/sync-templates.js +137 -5
- package/dist/wu-block.js +16 -5
- package/dist/wu-claim.js +15 -9
- package/dist/wu-create.js +50 -2
- package/dist/wu-deps.js +3 -1
- package/dist/wu-done.js +14 -5
- package/dist/wu-edit.js +35 -0
- package/dist/wu-prep.js +131 -8
- package/dist/wu-spawn.js +14 -1
- package/dist/wu-unblock.js +34 -2
- package/dist/wu-validate.js +25 -17
- package/package.json +11 -7
- package/templates/core/.lumenflow/constraints.md.template +61 -3
- package/templates/core/AGENTS.md.template +2 -2
- package/templates/core/LUMENFLOW.md.template +85 -23
- package/templates/core/ai/onboarding/agent-invocation-guide.md.template +157 -0
- package/templates/core/ai/onboarding/agent-safety-card.md.template +227 -0
- package/templates/core/ai/onboarding/docs-generation.md.template +277 -0
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +49 -7
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +343 -110
- package/templates/core/ai/onboarding/release-process.md.template +8 -2
- package/templates/core/ai/onboarding/starting-prompt.md.template +407 -0
- package/templates/core/ai/onboarding/test-ratchet.md.template +131 -0
- package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +91 -38
- package/templates/core/ai/onboarding/vendor-support.md.template +219 -0
- package/templates/vendors/claude/.claude/skills/context-management/SKILL.md.template +13 -1
- package/templates/vendors/claude/.claude/skills/execution-memory/SKILL.md.template +14 -16
- package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +48 -4
- package/templates/vendors/claude/.claude/skills/worktree-discipline/SKILL.md.template +5 -1
- package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +19 -8
- package/dist/__tests__/init-plan.test.js +0 -340
- package/dist/agent-issues-query.d.ts +0 -16
- package/dist/agent-log-issue.d.ts +0 -10
- package/dist/agent-session-end.d.ts +0 -10
- package/dist/agent-session.d.ts +0 -10
- package/dist/backlog-prune.d.ts +0 -84
- package/dist/cli-entry-point.d.ts +0 -8
- package/dist/deps-add.d.ts +0 -91
- package/dist/deps-remove.d.ts +0 -17
- package/dist/docs-sync.d.ts +0 -50
- package/dist/file-delete.d.ts +0 -84
- package/dist/file-edit.d.ts +0 -82
- package/dist/file-read.d.ts +0 -92
- package/dist/file-write.d.ts +0 -90
- package/dist/flow-bottlenecks.d.ts +0 -16
- package/dist/flow-report.d.ts +0 -16
- package/dist/gates.d.ts +0 -94
- package/dist/git-branch.d.ts +0 -65
- package/dist/git-diff.d.ts +0 -58
- package/dist/git-log.d.ts +0 -69
- package/dist/git-status.d.ts +0 -58
- package/dist/guard-locked.d.ts +0 -62
- package/dist/guard-main-branch.d.ts +0 -50
- package/dist/guard-worktree-commit.d.ts +0 -59
- package/dist/index.d.ts +0 -10
- package/dist/init-plan.d.ts +0 -80
- package/dist/init-plan.js +0 -337
- package/dist/init.d.ts +0 -46
- package/dist/initiative-add-wu.d.ts +0 -22
- package/dist/initiative-bulk-assign-wus.d.ts +0 -16
- package/dist/initiative-create.d.ts +0 -28
- package/dist/initiative-edit.d.ts +0 -34
- package/dist/initiative-list.d.ts +0 -12
- package/dist/initiative-status.d.ts +0 -11
- package/dist/lumenflow-upgrade.d.ts +0 -103
- package/dist/mem-checkpoint.d.ts +0 -16
- package/dist/mem-cleanup.d.ts +0 -29
- package/dist/mem-create.d.ts +0 -17
- package/dist/mem-export.d.ts +0 -10
- package/dist/mem-inbox.d.ts +0 -35
- package/dist/mem-init.d.ts +0 -15
- package/dist/mem-ready.d.ts +0 -16
- package/dist/mem-signal.d.ts +0 -16
- package/dist/mem-start.d.ts +0 -16
- package/dist/mem-summarize.d.ts +0 -22
- package/dist/mem-triage.d.ts +0 -22
- package/dist/metrics-cli.d.ts +0 -90
- package/dist/metrics-snapshot.d.ts +0 -18
- package/dist/orchestrate-init-status.d.ts +0 -11
- package/dist/orchestrate-initiative.d.ts +0 -12
- package/dist/orchestrate-monitor.d.ts +0 -11
- package/dist/release.d.ts +0 -117
- package/dist/rotate-progress.d.ts +0 -48
- package/dist/session-coordinator.d.ts +0 -74
- package/dist/spawn-list.d.ts +0 -16
- package/dist/state-bootstrap.d.ts +0 -92
- package/dist/sync-templates.d.ts +0 -52
- package/dist/trace-gen.d.ts +0 -84
- package/dist/validate-agent-skills.d.ts +0 -50
- package/dist/validate-agent-sync.d.ts +0 -36
- package/dist/validate-backlog-sync.d.ts +0 -37
- package/dist/validate-skills-spec.d.ts +0 -40
- package/dist/validate.d.ts +0 -60
- package/dist/wu-block.d.ts +0 -16
- package/dist/wu-claim.d.ts +0 -74
- package/dist/wu-cleanup.d.ts +0 -35
- package/dist/wu-create.d.ts +0 -69
- package/dist/wu-delete.d.ts +0 -21
- package/dist/wu-deps.d.ts +0 -13
- package/dist/wu-done.d.ts +0 -225
- package/dist/wu-edit.d.ts +0 -63
- package/dist/wu-infer-lane.d.ts +0 -17
- package/dist/wu-preflight.d.ts +0 -47
- package/dist/wu-prune.d.ts +0 -16
- package/dist/wu-recover.d.ts +0 -37
- package/dist/wu-release.d.ts +0 -19
- package/dist/wu-repair.d.ts +0 -60
- package/dist/wu-spawn-completion.d.ts +0 -10
- package/dist/wu-spawn.d.ts +0 -192
- package/dist/wu-status.d.ts +0 -25
- package/dist/wu-unblock.d.ts +0 -16
- package/dist/wu-unlock-lane.d.ts +0 -19
- package/dist/wu-validate.d.ts +0 -16
package/dist/git-status.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Git Status CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Provides WU-aware git status with:
|
|
6
|
-
* - Porcelain and short output formats
|
|
7
|
-
* - Parsed file status (staged, modified, untracked)
|
|
8
|
-
* - Clean/dirty state detection
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* node git-status.js [path] [--porcelain] [--short]
|
|
12
|
-
*
|
|
13
|
-
* WU-1109: INIT-003 Phase 4b - Migrate git operations
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Arguments for git status operation
|
|
17
|
-
*/
|
|
18
|
-
export interface GitStatusArgs {
|
|
19
|
-
/** Base directory for git operations */
|
|
20
|
-
baseDir?: string;
|
|
21
|
-
/** Path to filter status */
|
|
22
|
-
path?: string;
|
|
23
|
-
/** Use porcelain output format */
|
|
24
|
-
porcelain?: boolean;
|
|
25
|
-
/** Use short output format */
|
|
26
|
-
short?: boolean;
|
|
27
|
-
/** Show help */
|
|
28
|
-
help?: boolean;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Result of git status operation
|
|
32
|
-
*/
|
|
33
|
-
export interface GitStatusResult {
|
|
34
|
-
/** Whether operation succeeded */
|
|
35
|
-
success: boolean;
|
|
36
|
-
/** Error message (if failed) */
|
|
37
|
-
error?: string;
|
|
38
|
-
/** Whether working tree is clean */
|
|
39
|
-
isClean?: boolean;
|
|
40
|
-
/** List of staged files */
|
|
41
|
-
staged?: string[];
|
|
42
|
-
/** List of modified files (unstaged) */
|
|
43
|
-
modified?: string[];
|
|
44
|
-
/** List of untracked files */
|
|
45
|
-
untracked?: string[];
|
|
46
|
-
/** List of deleted files */
|
|
47
|
-
deleted?: string[];
|
|
48
|
-
/** Raw output (for porcelain mode) */
|
|
49
|
-
output?: string;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Parse command line arguments for git-status
|
|
53
|
-
*/
|
|
54
|
-
export declare function parseGitStatusArgs(argv: string[]): GitStatusArgs;
|
|
55
|
-
/**
|
|
56
|
-
* Get git status with audit logging
|
|
57
|
-
*/
|
|
58
|
-
export declare function getGitStatus(args: GitStatusArgs): Promise<GitStatusResult>;
|
package/dist/guard-locked.d.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* @file guard-locked.ts
|
|
4
|
-
* @description Guard that prevents changes to locked WUs (WU-1111)
|
|
5
|
-
*
|
|
6
|
-
* Validates that a WU is not locked before allowing modifications.
|
|
7
|
-
* Used by git hooks and wu: commands to enforce workflow discipline.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* guard-locked WU-123 # Check if WU-123 is locked
|
|
11
|
-
* guard-locked --wu WU-123 # Same with explicit flag
|
|
12
|
-
*
|
|
13
|
-
* Exit codes:
|
|
14
|
-
* 0 - WU is not locked (safe to proceed)
|
|
15
|
-
* 1 - WU is locked (block operation)
|
|
16
|
-
*
|
|
17
|
-
* @see {@link docs/04-operations/_frameworks/lumenflow/lumenflow-complete.md} - WU lifecycle
|
|
18
|
-
*/
|
|
19
|
-
/**
|
|
20
|
-
* Check if a WU is locked
|
|
21
|
-
*
|
|
22
|
-
* @param wuPath - Path to WU YAML file
|
|
23
|
-
* @returns true if WU has locked: true, false otherwise
|
|
24
|
-
* @throws Error if WU file does not exist or cannot be parsed
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* if (isWULocked('/path/to/WU-123.yaml')) {
|
|
28
|
-
* console.log('WU is locked, cannot modify');
|
|
29
|
-
* }
|
|
30
|
-
*/
|
|
31
|
-
export declare function isWULocked(wuPath: string): boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Assert that a WU is not locked
|
|
34
|
-
*
|
|
35
|
-
* @param wuPath - Path to WU YAML file
|
|
36
|
-
* @throws Error if WU is locked, with actionable fix instructions
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* try {
|
|
40
|
-
* assertWUNotLocked('/path/to/WU-123.yaml');
|
|
41
|
-
* // Safe to modify
|
|
42
|
-
* } catch (error) {
|
|
43
|
-
* console.error(error.message);
|
|
44
|
-
* process.exit(1);
|
|
45
|
-
* }
|
|
46
|
-
*/
|
|
47
|
-
export declare function assertWUNotLocked(wuPath: string): void;
|
|
48
|
-
/**
|
|
49
|
-
* Check if a WU ID is locked by looking up the YAML file
|
|
50
|
-
*
|
|
51
|
-
* @param wuId - WU ID (e.g., "WU-123")
|
|
52
|
-
* @returns true if WU has locked: true, false otherwise
|
|
53
|
-
* @throws Error if WU file does not exist
|
|
54
|
-
*/
|
|
55
|
-
export declare function isWUIdLocked(wuId: string): boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Assert that a WU ID is not locked
|
|
58
|
-
*
|
|
59
|
-
* @param wuId - WU ID (e.g., "WU-123")
|
|
60
|
-
* @throws Error if WU is locked
|
|
61
|
-
*/
|
|
62
|
-
export declare function assertWUIdNotLocked(wuId: string): void;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Guard Main Branch CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Provides branch protection checks for WU workflow:
|
|
6
|
-
* - Blocks operations on main/master branches
|
|
7
|
-
* - Blocks operations on lane branches (require worktree)
|
|
8
|
-
* - Optionally allows agent branches
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* node guard-main-branch.js [--allow-agent-branch] [--strict]
|
|
12
|
-
*
|
|
13
|
-
* WU-1109: INIT-003 Phase 4b - Migrate git operations
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Arguments for guard-main-branch operation
|
|
17
|
-
*/
|
|
18
|
-
export interface GuardMainBranchArgs {
|
|
19
|
-
/** Base directory for git operations */
|
|
20
|
-
baseDir?: string;
|
|
21
|
-
/** Allow agent branches (e.g., claude/session-123) */
|
|
22
|
-
allowAgentBranch?: boolean;
|
|
23
|
-
/** Strict mode - fail on any protected branch */
|
|
24
|
-
strict?: boolean;
|
|
25
|
-
/** Show help */
|
|
26
|
-
help?: boolean;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Result of guard-main-branch operation
|
|
30
|
-
*/
|
|
31
|
-
export interface GuardMainBranchResult {
|
|
32
|
-
/** Whether operation succeeded */
|
|
33
|
-
success: boolean;
|
|
34
|
-
/** Error message (if failed) */
|
|
35
|
-
error?: string;
|
|
36
|
-
/** Whether current branch is protected */
|
|
37
|
-
isProtected: boolean;
|
|
38
|
-
/** Current branch name */
|
|
39
|
-
currentBranch?: string;
|
|
40
|
-
/** Reason for protection */
|
|
41
|
-
reason?: string;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Parse command line arguments for guard-main-branch
|
|
45
|
-
*/
|
|
46
|
-
export declare function parseGuardMainBranchArgs(argv: string[]): GuardMainBranchArgs;
|
|
47
|
-
/**
|
|
48
|
-
* Guard against operations on protected branches
|
|
49
|
-
*/
|
|
50
|
-
export declare function guardMainBranch(args: GuardMainBranchArgs): Promise<GuardMainBranchResult>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* @file guard-worktree-commit.ts
|
|
4
|
-
* @description Guard that prevents WU commits from main checkout (WU-1111)
|
|
5
|
-
*
|
|
6
|
-
* Validates that WU-related commits are only made from worktrees, not main.
|
|
7
|
-
* Used by git commit-msg hooks to enforce worktree discipline.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* guard-worktree-commit "commit message"
|
|
11
|
-
* guard-worktree-commit --message "commit message"
|
|
12
|
-
*
|
|
13
|
-
* Exit codes:
|
|
14
|
-
* 0 - Commit allowed
|
|
15
|
-
* 1 - Commit blocked (WU commit from main)
|
|
16
|
-
*
|
|
17
|
-
* @see {@link docs/04-operations/_frameworks/lumenflow/lumenflow-complete.md} - Worktree discipline
|
|
18
|
-
*/
|
|
19
|
-
/**
|
|
20
|
-
* Result of commit block check
|
|
21
|
-
*/
|
|
22
|
-
export interface CommitBlockResult {
|
|
23
|
-
/** Whether the commit should be blocked */
|
|
24
|
-
blocked: boolean;
|
|
25
|
-
/** Reason for blocking (if blocked) */
|
|
26
|
-
reason?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Check if a commit should be blocked
|
|
30
|
-
*
|
|
31
|
-
* @param options - Check options
|
|
32
|
-
* @param options.commitMessage - The commit message
|
|
33
|
-
* @param options.isMainCheckout - Whether in main checkout
|
|
34
|
-
* @param options.isInWorktree - Whether in a worktree
|
|
35
|
-
* @returns Whether commit should be blocked and why
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* const result = shouldBlockCommit({
|
|
39
|
-
* commitMessage: 'wu(WU-123): add feature',
|
|
40
|
-
* isMainCheckout: true,
|
|
41
|
-
* isInWorktree: false,
|
|
42
|
-
* });
|
|
43
|
-
* if (result.blocked) {
|
|
44
|
-
* console.error(result.reason);
|
|
45
|
-
* process.exit(1);
|
|
46
|
-
* }
|
|
47
|
-
*/
|
|
48
|
-
export declare function shouldBlockCommit(options: {
|
|
49
|
-
commitMessage: string;
|
|
50
|
-
isMainCheckout: boolean;
|
|
51
|
-
isInWorktree: boolean;
|
|
52
|
-
}): CommitBlockResult;
|
|
53
|
-
/**
|
|
54
|
-
* Check if a commit message is WU-related
|
|
55
|
-
*
|
|
56
|
-
* @param message - Commit message to check
|
|
57
|
-
* @returns true if message indicates WU work
|
|
58
|
-
*/
|
|
59
|
-
export declare function isWUCommitMessage(message: string): boolean;
|
package/dist/index.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @lumenflow/cli - Command-line interface for LumenFlow workflow framework
|
|
3
|
-
*
|
|
4
|
-
* This package provides CLI commands for the LumenFlow workflow framework.
|
|
5
|
-
* Most functionality is exposed via bin commands, but the cli-entry-point
|
|
6
|
-
* helper is exported for use in custom CLI wrappers.
|
|
7
|
-
*
|
|
8
|
-
* @see https://lumenflow.dev/reference/cli
|
|
9
|
-
*/
|
|
10
|
-
export { runCLI } from './cli-entry-point.js';
|
package/dist/init-plan.d.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Init Plan Command (WU-1105)
|
|
4
|
-
*
|
|
5
|
-
* Links plan files to initiatives by setting the `related_plan` field
|
|
6
|
-
* in the initiative YAML.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* pnpm init:plan --initiative INIT-001 --plan docs/04-operations/plans/my-plan.md
|
|
10
|
-
* pnpm init:plan --initiative INIT-001 --create # Create new plan template
|
|
11
|
-
*
|
|
12
|
-
* Features:
|
|
13
|
-
* - Validates initiative exists before modifying
|
|
14
|
-
* - Formats plan path as lumenflow:// URI
|
|
15
|
-
* - Idempotent: no error if same plan already linked
|
|
16
|
-
* - Warns if replacing existing plan link
|
|
17
|
-
* - Can create plan templates with --create
|
|
18
|
-
*
|
|
19
|
-
* Context: WU-1105 (INIT-003 Phase 3a: Migrate init:plan command)
|
|
20
|
-
*/
|
|
21
|
-
import { readInitiative } from '@lumenflow/initiatives/dist/initiative-yaml.js';
|
|
22
|
-
/** Log prefix for console output */
|
|
23
|
-
export declare const LOG_PREFIX: string;
|
|
24
|
-
/**
|
|
25
|
-
* Validate Initiative ID format
|
|
26
|
-
* @param id - Initiative ID to validate
|
|
27
|
-
* @throws Error if format is invalid
|
|
28
|
-
*/
|
|
29
|
-
export declare function validateInitIdFormat(id: string): void;
|
|
30
|
-
/**
|
|
31
|
-
* Validate plan file path
|
|
32
|
-
* @param planPath - Path to plan file
|
|
33
|
-
* @throws Error if path is invalid or file doesn't exist
|
|
34
|
-
*/
|
|
35
|
-
export declare function validatePlanPath(planPath: string): void;
|
|
36
|
-
/**
|
|
37
|
-
* Format plan path as lumenflow:// URI
|
|
38
|
-
*
|
|
39
|
-
* Extracts the filename (and any subdirectory within plans/) and creates
|
|
40
|
-
* a standardized URI for the plan reference.
|
|
41
|
-
*
|
|
42
|
-
* @param planPath - Path to plan file (can be relative or absolute)
|
|
43
|
-
* @returns lumenflow://plans/<filename> URI
|
|
44
|
-
*/
|
|
45
|
-
export declare function formatPlanUri(planPath: string): string;
|
|
46
|
-
/**
|
|
47
|
-
* Check if initiative exists and return the document
|
|
48
|
-
* @param initId - Initiative ID to check
|
|
49
|
-
* @returns Initiative document
|
|
50
|
-
* @throws Error if initiative not found
|
|
51
|
-
*/
|
|
52
|
-
export declare function checkInitiativeExists(initId: string): ReturnType<typeof readInitiative>;
|
|
53
|
-
/**
|
|
54
|
-
* Update initiative with plan reference in micro-worktree
|
|
55
|
-
*
|
|
56
|
-
* Uses raw YAML parsing to preserve unknown fields like related_plan
|
|
57
|
-
* that are not in the strict initiative schema.
|
|
58
|
-
*
|
|
59
|
-
* @param worktreePath - Path to micro-worktree
|
|
60
|
-
* @param initId - Initiative ID
|
|
61
|
-
* @param planUri - Plan URI to set
|
|
62
|
-
* @returns True if changes were made, false if already linked
|
|
63
|
-
*/
|
|
64
|
-
export declare function updateInitiativeWithPlan(worktreePath: string, initId: string, planUri: string): boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Create a plan template file
|
|
67
|
-
*
|
|
68
|
-
* @param worktreePath - Path to repo root or worktree
|
|
69
|
-
* @param initId - Initiative ID
|
|
70
|
-
* @param title - Initiative title
|
|
71
|
-
* @returns Path to created file
|
|
72
|
-
* @throws Error if file already exists
|
|
73
|
-
*/
|
|
74
|
-
export declare function createPlanTemplate(worktreePath: string, initId: string, title: string): string;
|
|
75
|
-
/**
|
|
76
|
-
* Generate commit message for plan link operation
|
|
77
|
-
*/
|
|
78
|
-
export declare function getCommitMessage(initId: string, planUri: string): string;
|
|
79
|
-
declare function main(): Promise<void>;
|
|
80
|
-
export { main };
|
package/dist/init-plan.js
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
3
|
-
/**
|
|
4
|
-
* Init Plan Command (WU-1105)
|
|
5
|
-
*
|
|
6
|
-
* Links plan files to initiatives by setting the `related_plan` field
|
|
7
|
-
* in the initiative YAML.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* pnpm init:plan --initiative INIT-001 --plan docs/04-operations/plans/my-plan.md
|
|
11
|
-
* pnpm init:plan --initiative INIT-001 --create # Create new plan template
|
|
12
|
-
*
|
|
13
|
-
* Features:
|
|
14
|
-
* - Validates initiative exists before modifying
|
|
15
|
-
* - Formats plan path as lumenflow:// URI
|
|
16
|
-
* - Idempotent: no error if same plan already linked
|
|
17
|
-
* - Warns if replacing existing plan link
|
|
18
|
-
* - Can create plan templates with --create
|
|
19
|
-
*
|
|
20
|
-
* Context: WU-1105 (INIT-003 Phase 3a: Migrate init:plan command)
|
|
21
|
-
*/
|
|
22
|
-
import { getGitForCwd } from '@lumenflow/core/dist/git-adapter.js';
|
|
23
|
-
import { die } from '@lumenflow/core/dist/error-handler.js';
|
|
24
|
-
import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
25
|
-
import { join, basename } from 'node:path';
|
|
26
|
-
import { createWUParser, WU_OPTIONS } from '@lumenflow/core/dist/arg-parser.js';
|
|
27
|
-
import { INIT_PATHS } from '@lumenflow/initiatives/dist/initiative-paths.js';
|
|
28
|
-
import { INIT_PATTERNS } from '@lumenflow/initiatives/dist/initiative-constants.js';
|
|
29
|
-
import { ensureOnMain } from '@lumenflow/core/dist/wu-helpers.js';
|
|
30
|
-
import { withMicroWorktree } from '@lumenflow/core/dist/micro-worktree.js';
|
|
31
|
-
import { readInitiative } from '@lumenflow/initiatives/dist/initiative-yaml.js';
|
|
32
|
-
import { parseYAML, stringifyYAML } from '@lumenflow/core/dist/wu-yaml.js';
|
|
33
|
-
import { LOG_PREFIX as CORE_LOG_PREFIX } from '@lumenflow/core/dist/wu-constants.js';
|
|
34
|
-
/** Log prefix for console output */
|
|
35
|
-
export const LOG_PREFIX = CORE_LOG_PREFIX.INIT_PLAN;
|
|
36
|
-
/** Micro-worktree operation name */
|
|
37
|
-
const OPERATION_NAME = 'init-plan';
|
|
38
|
-
/** Standard plans directory relative to repo root */
|
|
39
|
-
const PLANS_DIR = 'docs/04-operations/plans';
|
|
40
|
-
/** LumenFlow URI scheme for plan references */
|
|
41
|
-
const PLAN_URI_SCHEME = 'lumenflow://plans/';
|
|
42
|
-
/**
|
|
43
|
-
* Custom option for plan file path
|
|
44
|
-
*/
|
|
45
|
-
const PLAN_OPTION = {
|
|
46
|
-
name: 'plan',
|
|
47
|
-
flags: '--plan <path>',
|
|
48
|
-
description: 'Path to plan file (markdown)',
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Custom option for creating new plan template
|
|
52
|
-
*/
|
|
53
|
-
const CREATE_OPTION = {
|
|
54
|
-
name: 'create',
|
|
55
|
-
flags: '--create',
|
|
56
|
-
description: 'Create a new plan template instead of linking existing file',
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Validate Initiative ID format
|
|
60
|
-
* @param id - Initiative ID to validate
|
|
61
|
-
* @throws Error if format is invalid
|
|
62
|
-
*/
|
|
63
|
-
export function validateInitIdFormat(id) {
|
|
64
|
-
if (!INIT_PATTERNS.INIT_ID.test(id)) {
|
|
65
|
-
die(`Invalid Initiative ID format: "${id}"\n\n` +
|
|
66
|
-
`Expected format: INIT-<number> or INIT-NAME (e.g., INIT-001, INIT-TOOLING)`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Validate plan file path
|
|
71
|
-
* @param planPath - Path to plan file
|
|
72
|
-
* @throws Error if path is invalid or file doesn't exist
|
|
73
|
-
*/
|
|
74
|
-
export function validatePlanPath(planPath) {
|
|
75
|
-
if (!planPath.endsWith('.md')) {
|
|
76
|
-
die(`Invalid plan file format: "${planPath}"\n\nPlan files must be markdown (.md)`);
|
|
77
|
-
}
|
|
78
|
-
if (!existsSync(planPath)) {
|
|
79
|
-
die(`Plan file not found: "${planPath}"\n\nUse --create to create a new plan template`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Format plan path as lumenflow:// URI
|
|
84
|
-
*
|
|
85
|
-
* Extracts the filename (and any subdirectory within plans/) and creates
|
|
86
|
-
* a standardized URI for the plan reference.
|
|
87
|
-
*
|
|
88
|
-
* @param planPath - Path to plan file (can be relative or absolute)
|
|
89
|
-
* @returns lumenflow://plans/<filename> URI
|
|
90
|
-
*/
|
|
91
|
-
export function formatPlanUri(planPath) {
|
|
92
|
-
// Try to extract path relative to plans directory
|
|
93
|
-
const plansMarker = '/plans/';
|
|
94
|
-
const plansIndex = planPath.indexOf(plansMarker);
|
|
95
|
-
if (plansIndex !== -1) {
|
|
96
|
-
// Extract everything after /plans/
|
|
97
|
-
const relativePath = planPath.substring(plansIndex + plansMarker.length);
|
|
98
|
-
return `${PLAN_URI_SCHEME}${relativePath}`;
|
|
99
|
-
}
|
|
100
|
-
// Fallback: just use the filename
|
|
101
|
-
const filename = basename(planPath);
|
|
102
|
-
return `${PLAN_URI_SCHEME}${filename}`;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Check if initiative exists and return the document
|
|
106
|
-
* @param initId - Initiative ID to check
|
|
107
|
-
* @returns Initiative document
|
|
108
|
-
* @throws Error if initiative not found
|
|
109
|
-
*/
|
|
110
|
-
export function checkInitiativeExists(initId) {
|
|
111
|
-
const initPath = INIT_PATHS.INITIATIVE(initId);
|
|
112
|
-
if (!existsSync(initPath)) {
|
|
113
|
-
die(`Initiative not found: ${initId}\n\nFile does not exist: ${initPath}`);
|
|
114
|
-
}
|
|
115
|
-
return readInitiative(initPath, initId);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Update initiative with plan reference in micro-worktree
|
|
119
|
-
*
|
|
120
|
-
* Uses raw YAML parsing to preserve unknown fields like related_plan
|
|
121
|
-
* that are not in the strict initiative schema.
|
|
122
|
-
*
|
|
123
|
-
* @param worktreePath - Path to micro-worktree
|
|
124
|
-
* @param initId - Initiative ID
|
|
125
|
-
* @param planUri - Plan URI to set
|
|
126
|
-
* @returns True if changes were made, false if already linked
|
|
127
|
-
*/
|
|
128
|
-
export function updateInitiativeWithPlan(worktreePath, initId, planUri) {
|
|
129
|
-
const initRelPath = INIT_PATHS.INITIATIVE(initId);
|
|
130
|
-
const initAbsPath = join(worktreePath, initRelPath);
|
|
131
|
-
// Read raw YAML to preserve unknown fields like related_plan
|
|
132
|
-
// (readInitiative strips them via zod schema validation)
|
|
133
|
-
const rawText = readFileSync(initAbsPath, { encoding: 'utf-8' });
|
|
134
|
-
const doc = parseYAML(rawText);
|
|
135
|
-
// Validate ID matches
|
|
136
|
-
if (doc.id !== initId) {
|
|
137
|
-
die(`Initiative YAML id mismatch. Expected ${initId}, found ${doc.id}`);
|
|
138
|
-
}
|
|
139
|
-
// Check for existing plan link
|
|
140
|
-
const existingPlan = doc.related_plan;
|
|
141
|
-
if (existingPlan === planUri) {
|
|
142
|
-
// Already linked to same plan - idempotent
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
if (existingPlan && existingPlan !== planUri) {
|
|
146
|
-
// Different plan already linked - warn but proceed
|
|
147
|
-
console.warn(`${LOG_PREFIX} Replacing existing related_plan: ${existingPlan} -> ${planUri}`);
|
|
148
|
-
}
|
|
149
|
-
// Update related_plan field
|
|
150
|
-
doc.related_plan = planUri;
|
|
151
|
-
const out = stringifyYAML(doc);
|
|
152
|
-
writeFileSync(initAbsPath, out, { encoding: 'utf-8' });
|
|
153
|
-
console.log(`${LOG_PREFIX} Updated ${initId} with related_plan: ${planUri}`);
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Create a plan template file
|
|
158
|
-
*
|
|
159
|
-
* @param worktreePath - Path to repo root or worktree
|
|
160
|
-
* @param initId - Initiative ID
|
|
161
|
-
* @param title - Initiative title
|
|
162
|
-
* @returns Path to created file
|
|
163
|
-
* @throws Error if file already exists
|
|
164
|
-
*/
|
|
165
|
-
export function createPlanTemplate(worktreePath, initId, title) {
|
|
166
|
-
const slug = title
|
|
167
|
-
.toLowerCase()
|
|
168
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
169
|
-
.replace(/^-|-$/g, '')
|
|
170
|
-
.substring(0, 30);
|
|
171
|
-
const filename = `${initId}-${slug}.md`;
|
|
172
|
-
const plansDir = join(worktreePath, PLANS_DIR);
|
|
173
|
-
const planPath = join(plansDir, filename);
|
|
174
|
-
if (existsSync(planPath)) {
|
|
175
|
-
die(`Plan file already exists: ${planPath}\n\nUse --plan to link an existing file`);
|
|
176
|
-
}
|
|
177
|
-
// Ensure plans directory exists
|
|
178
|
-
if (!existsSync(plansDir)) {
|
|
179
|
-
mkdirSync(plansDir, { recursive: true });
|
|
180
|
-
}
|
|
181
|
-
const template = `# ${initId} Plan - ${title}
|
|
182
|
-
|
|
183
|
-
## Goal
|
|
184
|
-
|
|
185
|
-
<!-- What is the primary objective of this initiative? -->
|
|
186
|
-
|
|
187
|
-
## Scope
|
|
188
|
-
|
|
189
|
-
<!-- What is in scope and out of scope? -->
|
|
190
|
-
|
|
191
|
-
## Approach
|
|
192
|
-
|
|
193
|
-
<!-- How will you achieve the goal? Key phases or milestones? -->
|
|
194
|
-
|
|
195
|
-
## Success Criteria
|
|
196
|
-
|
|
197
|
-
<!-- How will you know when this is complete? Measurable outcomes? -->
|
|
198
|
-
|
|
199
|
-
## Risks
|
|
200
|
-
|
|
201
|
-
<!-- What could go wrong? How will you mitigate? -->
|
|
202
|
-
|
|
203
|
-
## References
|
|
204
|
-
|
|
205
|
-
- Initiative: ${initId}
|
|
206
|
-
- Created: ${new Date().toISOString().split('T')[0]}
|
|
207
|
-
`;
|
|
208
|
-
writeFileSync(planPath, template, { encoding: 'utf-8' });
|
|
209
|
-
console.log(`${LOG_PREFIX} Created plan template: ${planPath}`);
|
|
210
|
-
return planPath;
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Generate commit message for plan link operation
|
|
214
|
-
*/
|
|
215
|
-
export function getCommitMessage(initId, planUri) {
|
|
216
|
-
const filename = planUri.replace(PLAN_URI_SCHEME, '');
|
|
217
|
-
return `docs: link plan ${filename} to ${initId.toLowerCase()}`;
|
|
218
|
-
}
|
|
219
|
-
async function main() {
|
|
220
|
-
const args = createWUParser({
|
|
221
|
-
name: 'init-plan',
|
|
222
|
-
description: 'Link a plan file to an initiative',
|
|
223
|
-
options: [WU_OPTIONS.initiative, PLAN_OPTION, CREATE_OPTION],
|
|
224
|
-
required: ['initiative'],
|
|
225
|
-
allowPositionalId: false,
|
|
226
|
-
});
|
|
227
|
-
const initId = args.initiative;
|
|
228
|
-
const planPath = args.plan;
|
|
229
|
-
const shouldCreate = args.create;
|
|
230
|
-
// Validate inputs
|
|
231
|
-
validateInitIdFormat(initId);
|
|
232
|
-
// Check initiative exists first (before any mutations)
|
|
233
|
-
const initDoc = checkInitiativeExists(initId);
|
|
234
|
-
const initTitle = initDoc.title;
|
|
235
|
-
// Determine plan path and URI
|
|
236
|
-
let targetPlanPath;
|
|
237
|
-
let planUri;
|
|
238
|
-
if (shouldCreate) {
|
|
239
|
-
// Create mode - will create template and link it
|
|
240
|
-
console.log(`${LOG_PREFIX} Creating plan template for ${initId}...`);
|
|
241
|
-
// Ensure on main for micro-worktree operations
|
|
242
|
-
await ensureOnMain(getGitForCwd());
|
|
243
|
-
try {
|
|
244
|
-
await withMicroWorktree({
|
|
245
|
-
operation: OPERATION_NAME,
|
|
246
|
-
id: initId,
|
|
247
|
-
logPrefix: LOG_PREFIX,
|
|
248
|
-
pushOnly: true,
|
|
249
|
-
execute: async ({ worktreePath }) => {
|
|
250
|
-
// Create plan template
|
|
251
|
-
targetPlanPath = createPlanTemplate(worktreePath, initId, initTitle);
|
|
252
|
-
planUri = formatPlanUri(targetPlanPath);
|
|
253
|
-
// Update initiative with plan link
|
|
254
|
-
updateInitiativeWithPlan(worktreePath, initId, planUri);
|
|
255
|
-
// Return files to commit
|
|
256
|
-
const planRelPath = targetPlanPath.replace(worktreePath + '/', '');
|
|
257
|
-
return {
|
|
258
|
-
commitMessage: getCommitMessage(initId, planUri),
|
|
259
|
-
files: [planRelPath, INIT_PATHS.INITIATIVE(initId)],
|
|
260
|
-
};
|
|
261
|
-
},
|
|
262
|
-
});
|
|
263
|
-
console.log(`\n${LOG_PREFIX} Transaction complete!`);
|
|
264
|
-
console.log(`\nPlan Linked:`);
|
|
265
|
-
console.log(` Initiative: ${initId}`);
|
|
266
|
-
console.log(` Plan URI: ${planUri}`);
|
|
267
|
-
console.log(` File: ${targetPlanPath}`);
|
|
268
|
-
console.log(`\nNext steps:`);
|
|
269
|
-
console.log(` 1. Edit the plan file with your goals and approach`);
|
|
270
|
-
console.log(` 2. View initiative: pnpm initiative:status ${initId}`);
|
|
271
|
-
}
|
|
272
|
-
catch (error) {
|
|
273
|
-
die(`Transaction failed: ${error.message}\n\n` +
|
|
274
|
-
`Micro-worktree cleanup was attempted automatically.\n` +
|
|
275
|
-
`If issue persists, check for orphaned branches: git branch | grep tmp/${OPERATION_NAME}`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
else if (planPath) {
|
|
279
|
-
// Link existing file mode
|
|
280
|
-
validatePlanPath(planPath);
|
|
281
|
-
planUri = formatPlanUri(planPath);
|
|
282
|
-
console.log(`${LOG_PREFIX} Linking plan to ${initId}...`);
|
|
283
|
-
// Check for idempotent case before micro-worktree
|
|
284
|
-
const existingPlan = initDoc.related_plan;
|
|
285
|
-
if (existingPlan === planUri) {
|
|
286
|
-
console.log(`${LOG_PREFIX} Plan already linked (idempotent - no changes needed)`);
|
|
287
|
-
console.log(`\n${LOG_PREFIX} ${initId} already has related_plan: ${planUri}`);
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
// Ensure on main for micro-worktree operations
|
|
291
|
-
await ensureOnMain(getGitForCwd());
|
|
292
|
-
try {
|
|
293
|
-
await withMicroWorktree({
|
|
294
|
-
operation: OPERATION_NAME,
|
|
295
|
-
id: initId,
|
|
296
|
-
logPrefix: LOG_PREFIX,
|
|
297
|
-
pushOnly: true,
|
|
298
|
-
execute: async ({ worktreePath }) => {
|
|
299
|
-
// Update initiative with plan link
|
|
300
|
-
const changed = updateInitiativeWithPlan(worktreePath, initId, planUri);
|
|
301
|
-
if (!changed) {
|
|
302
|
-
console.log(`${LOG_PREFIX} No changes detected (concurrent link operation)`);
|
|
303
|
-
}
|
|
304
|
-
return {
|
|
305
|
-
commitMessage: getCommitMessage(initId, planUri),
|
|
306
|
-
files: [INIT_PATHS.INITIATIVE(initId)],
|
|
307
|
-
};
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
console.log(`\n${LOG_PREFIX} Transaction complete!`);
|
|
311
|
-
console.log(`\nPlan Linked:`);
|
|
312
|
-
console.log(` Initiative: ${initId}`);
|
|
313
|
-
console.log(` Plan URI: ${planUri}`);
|
|
314
|
-
console.log(` File: ${planPath}`);
|
|
315
|
-
console.log(`\nNext steps:`);
|
|
316
|
-
console.log(` - View initiative: pnpm initiative:status ${initId}`);
|
|
317
|
-
}
|
|
318
|
-
catch (error) {
|
|
319
|
-
die(`Transaction failed: ${error.message}\n\n` +
|
|
320
|
-
`Micro-worktree cleanup was attempted automatically.\n` +
|
|
321
|
-
`If issue persists, check for orphaned branches: git branch | grep tmp/${OPERATION_NAME}`);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
die('Either --plan or --create is required\n\n' +
|
|
326
|
-
'Usage:\n' +
|
|
327
|
-
' pnpm init:plan --initiative INIT-001 --plan docs/04-operations/plans/my-plan.md\n' +
|
|
328
|
-
' pnpm init:plan --initiative INIT-001 --create');
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
// Guard main() for testability - use import.meta.main (WU-1071)
|
|
332
|
-
import { runCLI } from './cli-entry-point.js';
|
|
333
|
-
if (import.meta.main) {
|
|
334
|
-
runCLI(main);
|
|
335
|
-
}
|
|
336
|
-
// Export for testing
|
|
337
|
-
export { main };
|