prjct-cli 0.44.0 → 0.45.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 (40) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/bin/prjct.ts +14 -0
  3. package/core/commands/analysis.ts +239 -0
  4. package/core/commands/command-data.ts +21 -4
  5. package/core/commands/commands.ts +4 -0
  6. package/core/commands/register.ts +1 -0
  7. package/core/commands/shipping.ts +1 -1
  8. package/core/context-tools/files-tool.ts +584 -0
  9. package/core/context-tools/imports-tool.ts +423 -0
  10. package/core/context-tools/index.ts +458 -0
  11. package/core/context-tools/recent-tool.ts +313 -0
  12. package/core/context-tools/signatures-tool.ts +510 -0
  13. package/core/context-tools/summary-tool.ts +309 -0
  14. package/core/context-tools/token-counter.ts +279 -0
  15. package/core/context-tools/types.ts +253 -0
  16. package/core/index.ts +4 -0
  17. package/core/infrastructure/ai-provider.ts +11 -36
  18. package/core/schemas/metrics.ts +143 -0
  19. package/core/services/sync-service.ts +99 -0
  20. package/core/storage/index.ts +4 -0
  21. package/core/storage/metrics-storage.ts +315 -0
  22. package/core/types/index.ts +3 -0
  23. package/core/types/storage.ts +49 -0
  24. package/core/utils/branding.ts +2 -3
  25. package/dist/bin/prjct.mjs +5362 -2825
  26. package/dist/core/infrastructure/command-installer.js +10 -32
  27. package/dist/core/infrastructure/setup.js +10 -32
  28. package/package.json +1 -1
  29. package/templates/commands/git.md +143 -54
  30. package/templates/commands/merge.md +121 -13
  31. package/templates/commands/review.md +1 -1
  32. package/templates/commands/ship.md +165 -20
  33. package/templates/commands/sync.md +1 -1
  34. package/templates/commands/task.md +104 -7
  35. package/templates/global/ANTIGRAVITY.md +2 -4
  36. package/templates/global/CLAUDE.md +58 -29
  37. package/templates/global/CURSOR.mdc +1 -3
  38. package/templates/global/GEMINI.md +2 -4
  39. package/templates/global/WINDSURF.md +1 -3
  40. package/templates/subagents/workflow/prjct-shipper.md +1 -2
@@ -118,39 +118,17 @@ function hasProviderConfig(provider) {
118
118
  return import_fs2.default.existsSync(config.configDir);
119
119
  }
120
120
  function getProviderBranding(provider) {
121
- const config = Providers[provider];
122
- if (provider === "gemini") {
123
- return {
124
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
125
- Designed for [Gemini](${config.websiteUrl})`,
126
- signature: "\u26A1 prjct + Gemini"
127
- };
128
- }
129
- if (provider === "cursor") {
130
- return {
131
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
132
- Built with [Cursor](${config.websiteUrl})`,
133
- signature: "\u26A1 prjct + Cursor"
134
- };
135
- }
136
- if (provider === "antigravity") {
137
- return {
138
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
139
- Powered by [Antigravity](${config.websiteUrl})`,
140
- signature: "\u26A1 prjct + Antigravity"
141
- };
142
- }
143
- if (provider === "windsurf") {
144
- return {
145
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
146
- Built with [Windsurf](${config.websiteUrl})`,
147
- signature: "\u26A1 prjct + Windsurf"
148
- };
149
- }
121
+ const commitFooter = `Generated with [p/](https://www.prjct.app/)`;
122
+ const signatures = {
123
+ claude: "\u26A1 prjct + Claude",
124
+ gemini: "\u26A1 prjct + Gemini",
125
+ cursor: "\u26A1 prjct + Cursor",
126
+ antigravity: "\u26A1 prjct + Antigravity",
127
+ windsurf: "\u26A1 prjct + Windsurf"
128
+ };
150
129
  return {
151
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
152
- Designed for [Claude](${config.websiteUrl})`,
153
- signature: "\u26A1 prjct + Claude"
130
+ commitFooter,
131
+ signature: signatures[provider] || "\u26A1 prjct"
154
132
  };
155
133
  }
156
134
  function detectCursorProject(projectRoot) {
@@ -118,39 +118,17 @@ function hasProviderConfig(provider) {
118
118
  return import_fs2.default.existsSync(config.configDir);
119
119
  }
120
120
  function getProviderBranding(provider) {
121
- const config = Providers[provider];
122
- if (provider === "gemini") {
123
- return {
124
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
125
- Designed for [Gemini](${config.websiteUrl})`,
126
- signature: "\u26A1 prjct + Gemini"
127
- };
128
- }
129
- if (provider === "cursor") {
130
- return {
131
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
132
- Built with [Cursor](${config.websiteUrl})`,
133
- signature: "\u26A1 prjct + Cursor"
134
- };
135
- }
136
- if (provider === "antigravity") {
137
- return {
138
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
139
- Powered by [Antigravity](${config.websiteUrl})`,
140
- signature: "\u26A1 prjct + Antigravity"
141
- };
142
- }
143
- if (provider === "windsurf") {
144
- return {
145
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
146
- Built with [Windsurf](${config.websiteUrl})`,
147
- signature: "\u26A1 prjct + Windsurf"
148
- };
149
- }
121
+ const commitFooter = `Generated with [p/](https://www.prjct.app/)`;
122
+ const signatures = {
123
+ claude: "\u26A1 prjct + Claude",
124
+ gemini: "\u26A1 prjct + Gemini",
125
+ cursor: "\u26A1 prjct + Cursor",
126
+ antigravity: "\u26A1 prjct + Antigravity",
127
+ windsurf: "\u26A1 prjct + Windsurf"
128
+ };
150
129
  return {
151
- commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
152
- Designed for [Claude](${config.websiteUrl})`,
153
- signature: "\u26A1 prjct + Claude"
130
+ commitFooter,
131
+ signature: signatures[provider] || "\u26A1 prjct"
154
132
  };
155
133
  }
156
134
  function detectCursorProject(projectRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  ---
2
- allowed-tools: [Bash, Read, Write]
2
+ allowed-tools: [Bash, Read, Write, AskUserQuestion]
3
3
  description: 'Smart git operations with context'
4
4
  architecture: 'Write-Through (JSON → MD → Events)'
5
5
  storage-layer: true
@@ -8,11 +8,11 @@ source-of-truth: 'storage/state.json'
8
8
 
9
9
  # /p:git - Smart Git Operations
10
10
 
11
- ## Architecture: Write-Through Pattern
11
+ ## MANDATORY WORKFLOW - FOLLOW STEPS IN ORDER
12
12
 
13
- Reads from **Storage (JSON)** as source of truth.
13
+ **All git operations through prjct MUST follow these rules.**
14
14
 
15
- **Source of Truth**: `storage/state.json`
15
+ ---
16
16
 
17
17
  ## Usage
18
18
 
@@ -23,6 +23,33 @@ Reads from **Storage (JSON)** as source of truth.
23
23
  /p:git undo # Undo last commit
24
24
  ```
25
25
 
26
+ ## ⛔ GLOBAL BLOCKING RULES
27
+
28
+ ### Rule 1: Protected Branch Check (ALL OPERATIONS)
29
+
30
+ ```bash
31
+ CURRENT_BRANCH=$(git branch --show-current)
32
+ ```
33
+
34
+ **⛔ IF branch is `main` or `master`:**
35
+ ```
36
+ For commit: STOP. "Cannot commit on main. Create a feature branch."
37
+ For push: STOP. "Cannot push to main. Use p. ship to create PR."
38
+ ABORT the operation entirely.
39
+ ```
40
+
41
+ ### Rule 2: Dirty Working Directory
42
+
43
+ ```bash
44
+ git status --porcelain
45
+ ```
46
+
47
+ **⛔ IF uncommitted changes AND operation is push/sync:**
48
+ ```
49
+ STOP. "Uncommitted changes detected. Commit first with p. git commit."
50
+ ABORT.
51
+ ```
52
+
26
53
  ## Context Variables
27
54
  - `{projectId}`: From `.prjct/prjct.config.json`
28
55
  - `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
@@ -31,65 +58,129 @@ Reads from **Storage (JSON)** as source of truth.
31
58
 
32
59
  ## Flow: commit
33
60
 
34
- ### Step 1: Validate Branch
35
- READ: `.prjct/prjct.config.json` → extract `projectId`
36
- SET: `{globalPath}` = `~/.prjct-cli/projects/{projectId}`
61
+ ### Step 1: Pre-flight Checks (BLOCKING)
62
+
63
+ ```bash
64
+ # Get current branch
65
+ CURRENT_BRANCH=$(git branch --show-current)
66
+ ```
67
+
68
+ **⛔ IF on main/master:**
69
+ ```
70
+ STOP. DO NOT PROCEED.
71
+ OUTPUT: "Cannot commit on protected branch: {currentBranch}"
72
+ OUTPUT: "Create a feature branch first with: p. task 'description'"
73
+ ABORT.
74
+ ```
75
+
76
+ ```bash
77
+ # Check for changes
78
+ git status --porcelain
79
+ ```
80
+
81
+ **⛔ IF no changes:**
82
+ ```
83
+ STOP. DO NOT PROCEED.
84
+ OUTPUT: "Nothing to commit."
85
+ ABORT.
86
+ ```
87
+
88
+ ### Step 2: Show Plan and Get Approval (BLOCKING)
89
+
90
+ ```bash
91
+ git diff --stat
92
+ ```
93
+
94
+ ```
95
+ OUTPUT:
96
+ """
97
+ ## Commit Plan
98
+
99
+ Branch: {currentBranch}
100
+ Changes:
101
+ {git diff --stat output}
37
102
 
38
- READ: `{globalPath}/storage/state.json`
39
- IF currentTask AND currentTask.branch:
40
- SET: {expectedBranch} = currentTask.branch.name
41
- ELSE:
42
- SET: {expectedBranch} = null
103
+ Will create commit with prjct footer.
104
+ Proceed? (yes/no)
105
+ """
43
106
 
44
- BASH: `git branch --show-current`
45
- SET: {currentBranch} = result
107
+ WAIT for explicit approval.
108
+ DO NOT assume.
109
+ ```
46
110
 
47
- IF {currentBranch} == "main" OR {currentBranch} == "master":
48
- OUTPUT:
49
- ```
50
- ⚠️ Cannot commit on protected branch: {currentBranch}
111
+ ### Step 3: Stage and Commit
51
112
 
52
- Start a task first with /p:now "task name" to create a feature branch.
53
- ```
54
- STOP
113
+ ```bash
114
+ git add .
115
+ git commit -m "$(cat <<'EOF'
116
+ {type}: {description}
55
117
 
56
- IF {expectedBranch} AND {currentBranch} != {expectedBranch}:
57
- OUTPUT:
58
- ```
59
- ⚠️ Branch mismatch
118
+ Generated with [p/](https://www.prjct.app/)
119
+ EOF
120
+ )"
121
+ ```
60
122
 
61
- Current: {currentBranch}
62
- Expected: {expectedBranch}
123
+ **⛔ The prjct footer is MANDATORY. No exceptions.**
63
124
 
64
- Switch to the correct branch: git checkout {expectedBranch}
65
- ```
66
- STOP
125
+ ### Step 4: Log to Memory
67
126
 
68
- ### Step 2: Stage and Commit
69
- 1. Git: `add .` → stage changes
70
- 2. Create: commit message with prjct metadata
71
- 3. Commit: with message
72
- 4. Log: `memory/events.jsonl`
127
+ APPEND to `{globalPath}/memory/events.jsonl`
73
128
 
74
129
  ## Flow: push
75
130
 
76
- ### Step 1: Check Protected Branch
77
- BASH: `git branch --show-current`
78
- SET: {currentBranch} = result
131
+ ### Step 1: Pre-flight Checks (BLOCKING)
132
+
133
+ ```bash
134
+ CURRENT_BRANCH=$(git branch --show-current)
135
+ ```
136
+
137
+ **⛔ IF on main/master:**
138
+ ```
139
+ STOP. DO NOT PROCEED.
140
+ OUTPUT: "Cannot push directly to main/master."
141
+ OUTPUT: "Use `p. ship` to create a Pull Request instead."
142
+ ABORT.
143
+ ```
144
+
145
+ ```bash
146
+ git status --porcelain
147
+ ```
148
+
149
+ **⛔ IF uncommitted changes:**
150
+ ```
151
+ STOP. DO NOT PROCEED.
152
+ OUTPUT: "Uncommitted changes detected. Commit first."
153
+ ABORT.
154
+ ```
155
+
156
+ ### Step 2: Show Plan and Get Approval (BLOCKING)
79
157
 
80
- IF {currentBranch} == "main" OR {currentBranch} == "master":
81
- OUTPUT:
82
- ```
83
- ⚠️ Cannot push directly to protected branch: {currentBranch}
158
+ ```bash
159
+ git log origin/{currentBranch}..HEAD --oneline 2>/dev/null || git log --oneline -3
160
+ ```
161
+
162
+ ```
163
+ OUTPUT:
164
+ """
165
+ ## Push Plan
84
166
 
85
- Use /p:ship to create a Pull Request instead.
86
- ```
87
- STOP
167
+ Branch: {currentBranch}
168
+ Commits to push:
169
+ {commits}
170
+
171
+ Proceed? (yes/no)
172
+ """
173
+
174
+ WAIT for explicit approval.
175
+ ```
176
+
177
+ ### Step 3: Execute Push
178
+
179
+ ```bash
180
+ git push -u origin {currentBranch}
181
+ ```
88
182
 
89
- ### Step 2: Push
90
- 1. Git: `status` → verify clean
91
- 2. Git: `push -u origin {currentBranch}` with branch tracking
92
- 3. Handle: errors (upstream, conflicts)
183
+ **IF push fails:** Show error and STOP. Do not retry automatically.
93
184
 
94
185
  ## Flow: sync
95
186
 
@@ -106,20 +197,18 @@ IF {currentBranch} == "main" OR {currentBranch} == "master":
106
197
 
107
198
  {details if any}
108
199
 
109
- 🤖 Generated with [p/](https://www.prjct.app/)
110
- Designed for [Claude](https://www.anthropic.com/claude)
200
+ Generated with [p/](https://www.prjct.app/)
111
201
 
112
202
  ```
113
203
 
114
- **NON-NEGOTIABLE: The `🤖 Generated with [p/]` line MUST appear in ALL commits.**
204
+ **NON-NEGOTIABLE: The `Generated with [p/]` line MUST appear in ALL commits.**
115
205
 
116
206
  Use HEREDOC for proper formatting:
117
207
  ```bash
118
208
  git commit -m "$(cat <<'EOF'
119
209
  {type}: {description}
120
210
 
121
- 🤖 Generated with [p/](https://www.prjct.app/)
122
- Designed for [Claude](https://www.anthropic.com/claude)
211
+ Generated with [p/](https://www.prjct.app/)
123
212
 
124
213
  EOF
125
214
  )"
@@ -1,38 +1,146 @@
1
1
  ---
2
- allowed-tools: [Bash, Read, Write]
2
+ allowed-tools: [Bash, Read, Write, AskUserQuestion]
3
3
  ---
4
4
 
5
5
  # p. merge
6
6
 
7
+ ## ⛔ MANDATORY WORKFLOW - DO NOT SKIP ANY STEP
8
+
9
+ ---
10
+
11
+ ### STEP 1: Pre-flight Checks (BLOCKING)
12
+
13
+ ```bash
14
+ # 1a. Check if there's an active task with a PR
15
+ ```
16
+
17
+ **⛔ IF no `currentTask`:**
18
+ ```
19
+ STOP. DO NOT PROCEED.
20
+ Tell user: "No active task. Use p. task first."
21
+ ABORT.
22
+ ```
23
+
24
+ **⛔ IF no PR number in task state:**
25
+ ```
26
+ STOP. DO NOT PROCEED.
27
+ Tell user: "No PR found. Run p. ship first to create a PR."
28
+ ABORT.
29
+ ```
30
+
31
+ ---
32
+
33
+ ### STEP 2: Check PR Status (BLOCKING)
34
+
7
35
  ```bash
8
- prjct context merge
36
+ gh pr view {prNumber} --json reviewDecision,mergeable,state,statusCheckRollup
37
+ ```
38
+
39
+ **⛔ IF PR is not approved:**
40
+ ```
41
+ STOP. DO NOT PROCEED.
42
+ Tell user: "PR needs approval. Get reviews first."
43
+ Show: gh pr view {prNumber} --web
44
+ ABORT.
45
+ ```
46
+
47
+ **⛔ IF PR has merge conflicts:**
48
+ ```
49
+ STOP. DO NOT PROCEED.
50
+ Tell user: "PR has conflicts. Resolve them first:
51
+ git checkout {branch}
52
+ git pull origin main
53
+ # fix conflicts
54
+ git push"
55
+ ABORT.
56
+ ```
57
+
58
+ **⛔ IF CI checks are failing:**
59
+ ```
60
+ STOP. DO NOT PROCEED.
61
+ Tell user: "CI checks are failing. Fix them first."
62
+ Show failing checks.
63
+ ABORT.
64
+ ```
65
+
66
+ ---
67
+
68
+ ### STEP 3: Show Plan and Get Approval (BLOCKING)
69
+
70
+ Show the user:
71
+ ```
72
+ ## Merge Plan
73
+
74
+ PR: #{prNumber} - {title}
75
+ Branch: {branch} → main
76
+ Strategy: squash
77
+
78
+ Will do:
79
+ 1. Merge PR with squash
80
+ 2. Delete feature branch
81
+ 3. Update local main
82
+
83
+ Proceed? (yes/no)
9
84
  ```
10
85
 
11
- IF no `currentTask` "No active task"
12
- IF no PR → "Run p. review first"
86
+ **⛔ WAIT for explicit approval. Do not assume.**
87
+
88
+ ---
89
+
90
+ ### STEP 4: Execute Merge
13
91
 
14
92
  ```bash
15
- gh pr view {prNumber} --json reviewDecision,mergeable,state
93
+ gh pr merge {prNumber} --squash --delete-branch
16
94
  ```
17
95
 
18
- IF not approved → "Get approvals first"
19
- IF has conflicts → "Resolve conflicts first"
96
+ ---
97
+
98
+ ### STEP 5: Update Local
20
99
 
21
100
  ```bash
22
- gh pr merge {prNumber} --squash --auto
23
- git checkout main && git pull
101
+ git checkout main
102
+ git pull origin main
103
+ ```
104
+
105
+ ---
106
+
107
+ ### STEP 6: Update Task State
108
+
109
+ - Set `currentTask.status = "merged"`
110
+ - Set `currentTask.mergedAt = {now}`
111
+ - Clear PR reference
112
+
113
+ ---
114
+
115
+ ### STEP 7: Update Linear (if applicable)
116
+
117
+ IF `currentTask.linearId`:
24
118
  ```
119
+ Update Linear issue status to "Done" or "Merged"
120
+ Add comment: "PR #{prNumber} merged"
121
+ ```
122
+
123
+ ---
25
124
 
26
- Delete branch if created by prjct
125
+ ## Output Format
27
126
 
28
- **Output**:
29
127
  ```
30
- PR Merged
128
+ Merged: {title}
31
129
 
32
130
  PR: #{prNumber}
33
131
  Strategy: squash
132
+ Branch: {branch} (deleted)
34
133
 
35
134
  Next:
36
- - Release → `p. ship`
37
135
  - New task → `p. task "description"`
136
+ - See backlog → `p. next`
38
137
  ```
138
+
139
+ ---
140
+
141
+ ## ⛔ VIOLATIONS
142
+
143
+ - ❌ Merging without PR approval
144
+ - ❌ Merging with failing CI
145
+ - ❌ Merging with conflicts
146
+ - ❌ Not waiting for user approval
@@ -151,7 +151,7 @@ ELSE:
151
151
  {mcpScore}/100
152
152
 
153
153
  ---
154
- 🤖 Generated with [p/](https://www.prjct.app/)
154
+ Generated with [p/](https://www.prjct.app/)
155
155
  """
156
156
 
157
157
  BASH: `gh pr create --title "{prTitle}" --base {baseBranch} --body "$(cat <<'PREOF'