prjct-cli 0.55.1 β 0.55.3
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/CHANGELOG.md +35 -3
- package/core/__tests__/services/project-index.test.ts +3 -1
- package/core/infrastructure/setup.ts +55 -0
- package/core/integrations/jira/index.ts +0 -15
- package/core/services/sync-service.ts +6 -0
- package/dist/bin/prjct.mjs +38 -2
- package/dist/core/infrastructure/setup.js +33 -0
- package/package.json +2 -2
- package/templates/commands/bug.md +143 -18
- package/templates/commands/dash.md +74 -18
- package/templates/commands/done.md +125 -26
- package/templates/commands/idea.md +64 -9
- package/templates/commands/jira.md +3 -1
- package/templates/commands/linear.md +16 -24
- package/templates/commands/next.md +49 -11
- package/templates/commands/p.md +30 -183
- package/templates/commands/pause.md +115 -18
- package/templates/commands/resume.md +151 -14
- package/templates/commands/sync.md +0 -10
- package/templates/commands/task.md +86 -38
- package/templates/commands/test.md +60 -17
- package/templates/commands/workflow.md +70 -70
- package/templates/mcp-config.json +4 -32
- package/core/integrations/jira/mcp-adapter.ts +0 -446
- package/templates/_bases/tracker-base.md +0 -321
- package/templates/commands/github.md +0 -298
- package/templates/commands/monday.md +0 -243
package/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.55.
|
|
3
|
+
## [0.55.3] - 2026-02-05
|
|
4
4
|
|
|
5
5
|
### Bug Fixes
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- ensure test isolation in IndexStorage tests
|
|
8
|
+
- remove MCP integrations, keep only Context7 (#87)
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
## [0.
|
|
11
|
+
## [0.56.0] - 2026-02-04
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
- **Removed MCP-based integrations** (Monday.com, GitHub Issues)
|
|
16
|
+
- Only Context7 remains as the sole MCP server (for library docs)
|
|
17
|
+
- Linear and JIRA use SDK/REST API directly (4x faster)
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- **Context7 auto-install**: Now automatically configured in `~/.claude/mcp.json` on `prjct init`
|
|
11
22
|
|
|
12
23
|
### Fixed
|
|
13
24
|
|
|
25
|
+
- Templates no longer reference non-existent CLI commands (`prjct context task`, etc.)
|
|
26
|
+
- All workflow templates (task, done, bug, pause, resume, next, dash) now use Read/Write directly
|
|
27
|
+
|
|
28
|
+
### Removed
|
|
29
|
+
|
|
30
|
+
- `templates/commands/monday.md` - MCP integration
|
|
31
|
+
- `templates/commands/github.md` - MCP integration
|
|
32
|
+
- `templates/_bases/tracker-base.md` - MCP base template
|
|
33
|
+
- `core/integrations/jira/mcp-adapter.ts` - Unused MCP adapter
|
|
34
|
+
|
|
35
|
+
## [0.55.2] - 2026-02-04
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
- make Linear/JIRA templates explicitly ignore MCP tools
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## [0.55.1] - 2026-02-04
|
|
43
|
+
|
|
44
|
+
### Bug Fixes
|
|
45
|
+
|
|
14
46
|
- **Linear/JIRA templates no longer inherit MCP-based tracker-base**
|
|
15
47
|
- Removed `extends: '_bases/tracker-base.md'` from `linear.md` and `jira.md`
|
|
16
48
|
- Both templates have complete SDK-based implementations (4x faster than MCP)
|
|
@@ -184,9 +184,11 @@ describe('FileScorer', () => {
|
|
|
184
184
|
})
|
|
185
185
|
|
|
186
186
|
describe('IndexStorage', () => {
|
|
187
|
-
|
|
187
|
+
let testProjectId: string
|
|
188
188
|
|
|
189
189
|
beforeEach(async () => {
|
|
190
|
+
// Generate unique project ID for each test to ensure isolation
|
|
191
|
+
testProjectId = `test-project-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
190
192
|
// Set up test directory
|
|
191
193
|
const testDir = path.join(os.tmpdir(), `prjct-test-${Date.now()}`)
|
|
192
194
|
pathManager.setGlobalBaseDir(testDir)
|
|
@@ -169,6 +169,9 @@ export async function run(): Promise<SetupResults> {
|
|
|
169
169
|
|
|
170
170
|
// Install status line (Claude only)
|
|
171
171
|
await installStatusLine()
|
|
172
|
+
|
|
173
|
+
// Install Context7 MCP (only MCP server prjct uses)
|
|
174
|
+
await installContext7MCP()
|
|
172
175
|
}
|
|
173
176
|
} else if (providerName === 'gemini') {
|
|
174
177
|
// Gemini provider - install router and global config
|
|
@@ -875,6 +878,58 @@ echo "prjct"
|
|
|
875
878
|
}
|
|
876
879
|
}
|
|
877
880
|
|
|
881
|
+
/**
|
|
882
|
+
* Install Context7 MCP server configuration
|
|
883
|
+
*
|
|
884
|
+
* Context7 is the ONLY MCP server prjct uses - for library documentation lookup.
|
|
885
|
+
* All issue tracker integrations (Linear, JIRA) use SDK/REST API directly.
|
|
886
|
+
*/
|
|
887
|
+
async function installContext7MCP(): Promise<void> {
|
|
888
|
+
try {
|
|
889
|
+
const claudeDir = path.join(os.homedir(), '.claude')
|
|
890
|
+
const mcpConfigPath = path.join(claudeDir, 'mcp.json')
|
|
891
|
+
|
|
892
|
+
// Ensure ~/.claude directory exists
|
|
893
|
+
if (!fs.existsSync(claudeDir)) {
|
|
894
|
+
fs.mkdirSync(claudeDir, { recursive: true })
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// Context7 MCP configuration
|
|
898
|
+
const context7Config = {
|
|
899
|
+
mcpServers: {
|
|
900
|
+
context7: {
|
|
901
|
+
command: 'npx',
|
|
902
|
+
args: ['-y', '@upstash/context7-mcp@latest'],
|
|
903
|
+
},
|
|
904
|
+
},
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Check if mcp.json exists
|
|
908
|
+
if (fs.existsSync(mcpConfigPath)) {
|
|
909
|
+
// Read existing config
|
|
910
|
+
const existingContent = fs.readFileSync(mcpConfigPath, 'utf-8')
|
|
911
|
+
const existingConfig = JSON.parse(existingContent)
|
|
912
|
+
|
|
913
|
+
// Check if context7 is already configured
|
|
914
|
+
if (existingConfig.mcpServers?.context7) {
|
|
915
|
+
// Already configured, skip
|
|
916
|
+
return
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// Add context7 to existing config
|
|
920
|
+
existingConfig.mcpServers = existingConfig.mcpServers || {}
|
|
921
|
+
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7
|
|
922
|
+
fs.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), 'utf-8')
|
|
923
|
+
} else {
|
|
924
|
+
// Create new mcp.json with context7
|
|
925
|
+
fs.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), 'utf-8')
|
|
926
|
+
}
|
|
927
|
+
} catch (error) {
|
|
928
|
+
// Non-fatal error, just log
|
|
929
|
+
console.error(`Context7 MCP setup warning: ${(error as Error).message}`)
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
878
933
|
/**
|
|
879
934
|
* Install statusline modules (lib/ or components/)
|
|
880
935
|
* Copies .sh files from source to destination, always overwriting for updates
|
|
@@ -19,20 +19,5 @@ export {
|
|
|
19
19
|
} from './cache'
|
|
20
20
|
// REST API client
|
|
21
21
|
export { type JiraAuthMode, JiraProvider, jiraProvider } from './client'
|
|
22
|
-
// MCP adapter (deprecated - will be removed)
|
|
23
|
-
export {
|
|
24
|
-
createCreateIssueInstruction,
|
|
25
|
-
createGetIssueInstruction,
|
|
26
|
-
// MCP instruction generators
|
|
27
|
-
createSearchInstruction,
|
|
28
|
-
createTransitionInstruction,
|
|
29
|
-
createUpdateInstruction,
|
|
30
|
-
getMCPSetupInstructions,
|
|
31
|
-
// Utilities
|
|
32
|
-
isMCPAvailable,
|
|
33
|
-
JiraMCPAdapter,
|
|
34
|
-
jiraMCPAdapter,
|
|
35
|
-
type MCPInstruction,
|
|
36
|
-
} from './mcp-adapter'
|
|
37
22
|
// Service layer with caching (preferred API)
|
|
38
23
|
export { JiraService, jiraService } from './service'
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
type ProjectContext,
|
|
27
27
|
resolveToolIds,
|
|
28
28
|
} from '../ai-tools'
|
|
29
|
+
import commandInstaller from '../infrastructure/command-installer'
|
|
29
30
|
import configManager from '../infrastructure/config-manager'
|
|
30
31
|
import pathManager from '../infrastructure/path-manager'
|
|
31
32
|
import { metricsStorage } from '../storage/metrics-storage'
|
|
@@ -232,6 +233,11 @@ class SyncService {
|
|
|
232
233
|
const duration = Date.now() - startTime
|
|
233
234
|
const syncMetrics = await this.recordSyncMetrics(stats, contextFiles, agents, duration)
|
|
234
235
|
|
|
236
|
+
// 10. Update global config and commands (CLI does EVERYTHING)
|
|
237
|
+
// This ensures `prjct sync` from terminal updates global CLAUDE.md and commands
|
|
238
|
+
await commandInstaller.installGlobalConfig()
|
|
239
|
+
await commandInstaller.syncCommands()
|
|
240
|
+
|
|
235
241
|
return {
|
|
236
242
|
success: true,
|
|
237
243
|
projectId: this.projectId,
|
package/dist/bin/prjct.mjs
CHANGED
|
@@ -19105,6 +19105,7 @@ var init_sync_service = __esm({
|
|
|
19105
19105
|
"core/services/sync-service.ts"() {
|
|
19106
19106
|
"use strict";
|
|
19107
19107
|
init_ai_tools();
|
|
19108
|
+
init_command_installer();
|
|
19108
19109
|
init_config_manager();
|
|
19109
19110
|
init_path_manager();
|
|
19110
19111
|
init_metrics_storage();
|
|
@@ -19203,6 +19204,8 @@ var init_sync_service = __esm({
|
|
|
19203
19204
|
]);
|
|
19204
19205
|
const duration = Date.now() - startTime;
|
|
19205
19206
|
const syncMetrics = await this.recordSyncMetrics(stats, contextFiles, agents, duration);
|
|
19207
|
+
await command_installer_default.installGlobalConfig();
|
|
19208
|
+
await command_installer_default.syncCommands();
|
|
19206
19209
|
return {
|
|
19207
19210
|
success: true,
|
|
19208
19211
|
projectId: this.projectId,
|
|
@@ -21231,6 +21234,7 @@ async function run() {
|
|
|
21231
21234
|
}
|
|
21232
21235
|
await command_installer_default.installDocs();
|
|
21233
21236
|
await installStatusLine();
|
|
21237
|
+
await installContext7MCP();
|
|
21234
21238
|
}
|
|
21235
21239
|
} else if (providerName === "gemini") {
|
|
21236
21240
|
const geminiInstalled = await installGeminiRouter();
|
|
@@ -21681,6 +21685,37 @@ echo "prjct"
|
|
|
21681
21685
|
}
|
|
21682
21686
|
}
|
|
21683
21687
|
}
|
|
21688
|
+
async function installContext7MCP() {
|
|
21689
|
+
try {
|
|
21690
|
+
const claudeDir = path44.join(os13.homedir(), ".claude");
|
|
21691
|
+
const mcpConfigPath = path44.join(claudeDir, "mcp.json");
|
|
21692
|
+
if (!fs41.existsSync(claudeDir)) {
|
|
21693
|
+
fs41.mkdirSync(claudeDir, { recursive: true });
|
|
21694
|
+
}
|
|
21695
|
+
const context7Config = {
|
|
21696
|
+
mcpServers: {
|
|
21697
|
+
context7: {
|
|
21698
|
+
command: "npx",
|
|
21699
|
+
args: ["-y", "@upstash/context7-mcp@latest"]
|
|
21700
|
+
}
|
|
21701
|
+
}
|
|
21702
|
+
};
|
|
21703
|
+
if (fs41.existsSync(mcpConfigPath)) {
|
|
21704
|
+
const existingContent = fs41.readFileSync(mcpConfigPath, "utf-8");
|
|
21705
|
+
const existingConfig = JSON.parse(existingContent);
|
|
21706
|
+
if (existingConfig.mcpServers?.context7) {
|
|
21707
|
+
return;
|
|
21708
|
+
}
|
|
21709
|
+
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
21710
|
+
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
21711
|
+
fs41.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
21712
|
+
} else {
|
|
21713
|
+
fs41.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
21714
|
+
}
|
|
21715
|
+
} catch (error) {
|
|
21716
|
+
console.error(`Context7 MCP setup warning: ${error.message}`);
|
|
21717
|
+
}
|
|
21718
|
+
}
|
|
21684
21719
|
function installStatusLineModules(sourceDir, destDir) {
|
|
21685
21720
|
if (!fs41.existsSync(sourceDir)) {
|
|
21686
21721
|
return;
|
|
@@ -21777,6 +21812,7 @@ var init_setup = __esm({
|
|
|
21777
21812
|
__name(migrateProjectsCliVersion, "migrateProjectsCliVersion");
|
|
21778
21813
|
__name(ensureStatusLineSettings, "ensureStatusLineSettings");
|
|
21779
21814
|
__name(installStatusLine, "installStatusLine");
|
|
21815
|
+
__name(installContext7MCP, "installContext7MCP");
|
|
21780
21816
|
__name(installStatusLineModules, "installStatusLineModules");
|
|
21781
21817
|
__name(ensureStatusLineSymlink, "ensureStatusLineSymlink");
|
|
21782
21818
|
__name(showResults, "showResults");
|
|
@@ -25161,7 +25197,7 @@ var require_package = __commonJS({
|
|
|
25161
25197
|
"package.json"(exports, module) {
|
|
25162
25198
|
module.exports = {
|
|
25163
25199
|
name: "prjct-cli",
|
|
25164
|
-
version: "0.55.
|
|
25200
|
+
version: "0.55.3",
|
|
25165
25201
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
25166
25202
|
main: "core/index.ts",
|
|
25167
25203
|
bin: {
|
|
@@ -25216,7 +25252,7 @@ var require_package = __commonJS({
|
|
|
25216
25252
|
chalk: "^4.1.2",
|
|
25217
25253
|
chokidar: "^5.0.0",
|
|
25218
25254
|
esbuild: "^0.25.0",
|
|
25219
|
-
glob: "^
|
|
25255
|
+
glob: "^13.0.1",
|
|
25220
25256
|
hono: "^4.11.3",
|
|
25221
25257
|
"jsonc-parser": "^3.3.1",
|
|
25222
25258
|
lightningcss: "^1.30.2",
|
|
@@ -1168,6 +1168,7 @@ async function run() {
|
|
|
1168
1168
|
}
|
|
1169
1169
|
await command_installer_default.installDocs();
|
|
1170
1170
|
await installStatusLine();
|
|
1171
|
+
await installContext7MCP();
|
|
1171
1172
|
}
|
|
1172
1173
|
} else if (providerName === "gemini") {
|
|
1173
1174
|
const geminiInstalled = await installGeminiRouter();
|
|
@@ -1635,6 +1636,38 @@ echo "prjct"
|
|
|
1635
1636
|
}
|
|
1636
1637
|
}
|
|
1637
1638
|
__name(installStatusLine, "installStatusLine");
|
|
1639
|
+
async function installContext7MCP() {
|
|
1640
|
+
try {
|
|
1641
|
+
const claudeDir = import_node_path5.default.join(import_node_os4.default.homedir(), ".claude");
|
|
1642
|
+
const mcpConfigPath = import_node_path5.default.join(claudeDir, "mcp.json");
|
|
1643
|
+
if (!import_node_fs3.default.existsSync(claudeDir)) {
|
|
1644
|
+
import_node_fs3.default.mkdirSync(claudeDir, { recursive: true });
|
|
1645
|
+
}
|
|
1646
|
+
const context7Config = {
|
|
1647
|
+
mcpServers: {
|
|
1648
|
+
context7: {
|
|
1649
|
+
command: "npx",
|
|
1650
|
+
args: ["-y", "@upstash/context7-mcp@latest"]
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
if (import_node_fs3.default.existsSync(mcpConfigPath)) {
|
|
1655
|
+
const existingContent = import_node_fs3.default.readFileSync(mcpConfigPath, "utf-8");
|
|
1656
|
+
const existingConfig = JSON.parse(existingContent);
|
|
1657
|
+
if (existingConfig.mcpServers?.context7) {
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
1661
|
+
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
1662
|
+
import_node_fs3.default.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
1663
|
+
} else {
|
|
1664
|
+
import_node_fs3.default.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
1665
|
+
}
|
|
1666
|
+
} catch (error) {
|
|
1667
|
+
console.error(`Context7 MCP setup warning: ${error.message}`);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
__name(installContext7MCP, "installContext7MCP");
|
|
1638
1671
|
function installStatusLineModules(sourceDir, destDir) {
|
|
1639
1672
|
if (!import_node_fs3.default.existsSync(sourceDir)) {
|
|
1640
1673
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prjct-cli",
|
|
3
|
-
"version": "0.55.
|
|
3
|
+
"version": "0.55.3",
|
|
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": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"chalk": "^4.1.2",
|
|
56
56
|
"chokidar": "^5.0.0",
|
|
57
57
|
"esbuild": "^0.25.0",
|
|
58
|
-
"glob": "^
|
|
58
|
+
"glob": "^13.0.1",
|
|
59
59
|
"hono": "^4.11.3",
|
|
60
60
|
"jsonc-parser": "^3.3.1",
|
|
61
61
|
"lightningcss": "^1.30.2",
|
|
@@ -4,35 +4,160 @@ allowed-tools: [Read, Write, Bash, Task, AskUserQuestion]
|
|
|
4
4
|
|
|
5
5
|
# p. bug "$ARGUMENTS"
|
|
6
6
|
|
|
7
|
+
## Step 1: Validate Arguments
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
IF $ARGUMENTS is empty:
|
|
11
|
+
ASK: "What bug do you want to report?"
|
|
12
|
+
WAIT for response
|
|
13
|
+
DO NOT proceed with empty description
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Step 2: Resolve Project Paths
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Get projectId from local config
|
|
20
|
+
cat .prjct/prjct.config.json | grep -o '"projectId"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Set `globalPath = ~/.prjct-cli/projects/{projectId}`
|
|
24
|
+
|
|
25
|
+
## Step 3: Parse Severity from Keywords
|
|
26
|
+
|
|
27
|
+
Analyze `$ARGUMENTS` for severity indicators:
|
|
28
|
+
- `crash`, `down`, `broken`, `production`, `critical` β **critical**
|
|
29
|
+
- `error`, `fail`, `exception`, `cannot` β **high**
|
|
30
|
+
- `bug`, `incorrect`, `wrong`, `issue` β **medium** (default)
|
|
31
|
+
- `minor`, `typo`, `cosmetic`, `ui` β **low**
|
|
32
|
+
|
|
33
|
+
## Step 4: Explore Codebase
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
USE Task(Explore) β find affected files, recent commits related to the bug
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Step 5: Check for Active Task
|
|
40
|
+
|
|
41
|
+
READ `{globalPath}/storage/state.json`
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
IF currentTask exists AND currentTask.status == "active":
|
|
45
|
+
AskUserQuestion:
|
|
46
|
+
question: "You have an active task. How should we handle this bug?"
|
|
47
|
+
header: "Bug"
|
|
48
|
+
options:
|
|
49
|
+
- label: "Pause current and fix bug (Recommended)"
|
|
50
|
+
description: "Save current task, start bug fix"
|
|
51
|
+
- label: "Queue bug for later"
|
|
52
|
+
description: "Add to queue, continue current task"
|
|
53
|
+
|
|
54
|
+
IF "Queue bug for later":
|
|
55
|
+
# Add to queue and stop
|
|
56
|
+
READ {globalPath}/storage/queue.json (or create empty array)
|
|
57
|
+
APPEND bug to queue:
|
|
58
|
+
{
|
|
59
|
+
"id": "{uuid}",
|
|
60
|
+
"type": "bug",
|
|
61
|
+
"description": "$ARGUMENTS",
|
|
62
|
+
"severity": "{severity}",
|
|
63
|
+
"createdAt": "{timestamp}",
|
|
64
|
+
"status": "queued"
|
|
65
|
+
}
|
|
66
|
+
WRITE {globalPath}/storage/queue.json
|
|
67
|
+
|
|
68
|
+
OUTPUT:
|
|
69
|
+
"""
|
|
70
|
+
π Queued: $ARGUMENTS [{severity}]
|
|
71
|
+
|
|
72
|
+
Continue with: {currentTask.description}
|
|
73
|
+
|
|
74
|
+
Later: `p. task` to work on queued bug
|
|
75
|
+
"""
|
|
76
|
+
STOP
|
|
77
|
+
|
|
78
|
+
IF "Pause current and fix bug":
|
|
79
|
+
# Move current task to pausedTasks
|
|
80
|
+
# Will be handled in Step 6
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Step 6: Create Bug Branch
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git branch --show-current
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
IF current branch == "main" OR "master":
|
|
91
|
+
# Create bug fix branch
|
|
92
|
+
slug = sanitize($ARGUMENTS) # lowercase, hyphens, max 50 chars
|
|
93
|
+
|
|
94
|
+
git checkout -b bug/{slug}
|
|
95
|
+
|
|
96
|
+
IF git command fails:
|
|
97
|
+
OUTPUT: "Failed to create branch. Check git status."
|
|
98
|
+
STOP
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Step 7: Write State
|
|
102
|
+
|
|
103
|
+
Generate UUID and timestamp:
|
|
7
104
|
```bash
|
|
8
|
-
|
|
105
|
+
node -e "console.log(require('crypto').randomUUID())"
|
|
106
|
+
node -e "console.log(new Date().toISOString())"
|
|
9
107
|
```
|
|
10
108
|
|
|
11
|
-
|
|
12
|
-
- crash/down/broken/production β critical
|
|
13
|
-
- error/fail β high
|
|
14
|
-
- bug/incorrect β medium (default)
|
|
15
|
-
- minor/typo β low
|
|
109
|
+
READ current state, then update:
|
|
16
110
|
|
|
17
|
-
|
|
111
|
+
```
|
|
112
|
+
# If there was an active task, move it to pausedTasks
|
|
113
|
+
IF state.currentTask exists:
|
|
114
|
+
interruptedTask = state.currentTask
|
|
115
|
+
interruptedTask.status = "interrupted"
|
|
116
|
+
interruptedTask.interruptedAt = "{timestamp}"
|
|
117
|
+
interruptedTask.interruptedBy = "{new bug task id}"
|
|
18
118
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
119
|
+
state.pausedTasks = state.pausedTasks || []
|
|
120
|
+
state.pausedTasks.push(interruptedTask)
|
|
121
|
+
```
|
|
22
122
|
|
|
23
|
-
|
|
123
|
+
WRITE `{globalPath}/storage/state.json`:
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"currentTask": {
|
|
127
|
+
"id": "{uuid}",
|
|
128
|
+
"description": "$ARGUMENTS",
|
|
129
|
+
"type": "bug",
|
|
130
|
+
"severity": "{severity}",
|
|
131
|
+
"status": "active",
|
|
132
|
+
"startedAt": "{timestamp}",
|
|
133
|
+
"branch": "bug/{slug}",
|
|
134
|
+
"affectedFiles": ["{files from exploration}"]
|
|
135
|
+
},
|
|
136
|
+
"pausedTasks": [{interruptedTask if any}]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
24
139
|
|
|
25
|
-
|
|
26
|
-
|
|
140
|
+
## Step 8: Log Event
|
|
141
|
+
|
|
142
|
+
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
143
|
+
```json
|
|
144
|
+
{"type":"bug_reported","taskId":"{uuid}","description":"$ARGUMENTS","severity":"{severity}","timestamp":"{timestamp}","branch":"bug/{slug}"}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Output
|
|
27
150
|
|
|
28
|
-
**Output**:
|
|
29
151
|
```
|
|
30
152
|
π [{severity}] $ARGUMENTS
|
|
31
153
|
|
|
32
|
-
Affected: {files}
|
|
33
|
-
Branch: {
|
|
154
|
+
Affected: {files from exploration}
|
|
155
|
+
Branch: bug/{slug}
|
|
156
|
+
|
|
157
|
+
{IF interruptedTask: "Paused: {interruptedTask.description}"}
|
|
34
158
|
|
|
35
159
|
Next:
|
|
36
|
-
- Fix the bug β
|
|
37
|
-
-
|
|
160
|
+
- Fix the bug β work on code
|
|
161
|
+
- When fixed β `p. done`
|
|
162
|
+
- Resume previous β `p. resume`
|
|
38
163
|
```
|
|
@@ -1,32 +1,61 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read]
|
|
2
|
+
allowed-tools: [Read, Bash]
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# p. dash
|
|
6
6
|
|
|
7
|
+
## Step 1: Resolve Project Paths
|
|
8
|
+
|
|
7
9
|
```bash
|
|
8
|
-
|
|
10
|
+
# Get projectId from local config
|
|
11
|
+
cat .prjct/prjct.config.json | grep -o '"projectId"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4
|
|
9
12
|
```
|
|
10
13
|
|
|
14
|
+
Set `globalPath = ~/.prjct-cli/projects/{projectId}`
|
|
15
|
+
|
|
16
|
+
## Step 2: Read All Storage Files
|
|
17
|
+
|
|
11
18
|
READ all storage files:
|
|
12
|
-
- `{globalPath}/storage/state.json` β current/paused
|
|
13
|
-
- `{globalPath}/storage/queue.json` β queue
|
|
14
|
-
- `{globalPath}/storage/shipped.json` β
|
|
15
|
-
- `{globalPath}/storage/ideas.json` β ideas
|
|
19
|
+
- `{globalPath}/storage/state.json` β current/paused tasks
|
|
20
|
+
- `{globalPath}/storage/queue.json` β queue (or empty array)
|
|
21
|
+
- `{globalPath}/storage/shipped.json` β shipped features (or empty array)
|
|
22
|
+
- `{globalPath}/storage/ideas.json` β ideas (or empty array)
|
|
23
|
+
|
|
24
|
+
## Step 3: Calculate Metrics
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
currentTask = state.currentTask
|
|
28
|
+
pausedTasks = state.pausedTasks || []
|
|
29
|
+
queueCount = queue.length
|
|
30
|
+
shippedCount = shipped.length
|
|
31
|
+
ideasCount = ideas.length
|
|
32
|
+
|
|
33
|
+
IF currentTask:
|
|
34
|
+
elapsed = time since currentTask.startedAt (or resumedAt)
|
|
35
|
+
|
|
36
|
+
IF shipped.length > 0:
|
|
37
|
+
lastShip = shipped[0]
|
|
38
|
+
daysSinceLastShip = days since lastShip.shippedAt
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Output (default)
|
|
16
44
|
|
|
17
|
-
**Output (default)**:
|
|
18
45
|
```
|
|
19
46
|
π DASHBOARD
|
|
20
47
|
|
|
21
|
-
π― Current: {
|
|
22
|
-
|
|
48
|
+
π― Current: {currentTask.parentDescription or currentTask.description} ({elapsed})
|
|
49
|
+
Subtask: {current subtask if exists}
|
|
50
|
+
βΈοΈ Paused: {pausedTasks[0].description or "None"}
|
|
23
51
|
|
|
24
|
-
π Queue ({
|
|
25
|
-
β’ {
|
|
26
|
-
β’ {
|
|
52
|
+
π Queue ({queueCount})
|
|
53
|
+
β’ {queue[0].description}
|
|
54
|
+
β’ {queue[1].description}
|
|
55
|
+
{... up to 5 items}
|
|
27
56
|
|
|
28
|
-
π Recent: {
|
|
29
|
-
π‘ Ideas: {
|
|
57
|
+
π Recent: {lastShip.description} ({daysSinceLastShip}d ago)
|
|
58
|
+
π‘ Ideas: {ideasCount}
|
|
30
59
|
|
|
31
60
|
Next:
|
|
32
61
|
- Finish β `p. done`
|
|
@@ -34,10 +63,37 @@ Next:
|
|
|
34
63
|
- Queue β `p. next`
|
|
35
64
|
```
|
|
36
65
|
|
|
37
|
-
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Compact View (`p. dash compact`)
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
π― {currentTask.description} | π {queueCount} | π {daysSinceLastShip}d ago
|
|
38
72
|
```
|
|
39
|
-
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Week View (`p. dash week`)
|
|
77
|
+
|
|
78
|
+
Calculate from events.jsonl:
|
|
79
|
+
- Tasks completed this week
|
|
80
|
+
- Time spent (sum of task durations)
|
|
81
|
+
- Velocity (tasks/day)
|
|
82
|
+
|
|
40
83
|
```
|
|
84
|
+
π This Week
|
|
85
|
+
|
|
86
|
+
Completed: {count} tasks
|
|
87
|
+
Time: {hours}h focused
|
|
88
|
+
Velocity: {tasks_per_day}/day
|
|
89
|
+
|
|
90
|
+
Top areas:
|
|
91
|
+
- {area_1}: {count} tasks
|
|
92
|
+
- {area_2}: {count} tasks
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Month View (`p. dash month`)
|
|
41
98
|
|
|
42
|
-
|
|
43
|
-
Show completed tasks, velocity, focus time
|
|
99
|
+
Same as week, but for last 30 days. Show weekly trends.
|