cueme 0.1.12 → 0.1.14
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/docs/how-to-submit-a-pr.md +85 -0
- package/package.json +1 -1
- package/src/cli.js +13 -1
- package/src/proto.js +78 -2
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# How to submit a PR
|
|
2
|
+
|
|
3
|
+
## 1. Prerequisites
|
|
4
|
+
|
|
5
|
+
- Make sure you have write access to the repository (or submit a PR from a fork).
|
|
6
|
+
- Use Node.js locally (recommended to match `package.json` `engines`).
|
|
7
|
+
|
|
8
|
+
## 2. Update `main` and create a branch
|
|
9
|
+
|
|
10
|
+
- Pull the latest `main`.
|
|
11
|
+
- Create a new branch (recommended naming):
|
|
12
|
+
- `feature/<short-desc>`
|
|
13
|
+
- `fix/<short-desc>`
|
|
14
|
+
- `chore/<short-desc>`
|
|
15
|
+
|
|
16
|
+
## 3. Development and local checks
|
|
17
|
+
|
|
18
|
+
- Make your changes.
|
|
19
|
+
- Run minimal local checks:
|
|
20
|
+
- `npm ci`
|
|
21
|
+
- `npm run prepare`
|
|
22
|
+
- Optional: run a quick manual validation relevant to your change.
|
|
23
|
+
|
|
24
|
+
## 4. Commit conventions
|
|
25
|
+
|
|
26
|
+
- Recommended commit message prefixes:
|
|
27
|
+
- `feat: ...`
|
|
28
|
+
- `fix: ...`
|
|
29
|
+
- `refactor: ...`
|
|
30
|
+
- `chore: ...`
|
|
31
|
+
|
|
32
|
+
- Keep the PR focused: ideally one PR addresses one category of change.
|
|
33
|
+
|
|
34
|
+
## 5. Push your branch and create a PR (recommended: gh)
|
|
35
|
+
|
|
36
|
+
- Push your branch:
|
|
37
|
+
- `git push -u origin <your-branch>`
|
|
38
|
+
|
|
39
|
+
- Create the PR:
|
|
40
|
+
- `gh pr create -R nmhjklnm/cue-command`
|
|
41
|
+
|
|
42
|
+
- Suggested PR description:
|
|
43
|
+
- Why (motivation)
|
|
44
|
+
- What (changes)
|
|
45
|
+
- How to test
|
|
46
|
+
- Risks / impact
|
|
47
|
+
|
|
48
|
+
## 6. CI and review
|
|
49
|
+
|
|
50
|
+
- Ensure all PR checks pass (CI runs on PRs).
|
|
51
|
+
- Address review feedback by pushing additional commits.
|
|
52
|
+
|
|
53
|
+
## 7. Merge policy
|
|
54
|
+
|
|
55
|
+
- This repository uses a ruleset: only `squash` / `rebase` merges are allowed.
|
|
56
|
+
- Generally, **squash merge** is recommended to keep `main` history clean.
|
|
57
|
+
|
|
58
|
+
## 8. Post-merge
|
|
59
|
+
|
|
60
|
+
- After merging, confirm `main` CI runs and succeeds.
|
|
61
|
+
- If a release is required, follow the repository release process.
|
|
62
|
+
|
|
63
|
+
## 9. Common pitfalls
|
|
64
|
+
|
|
65
|
+
- **CI did not run**
|
|
66
|
+
- Confirm your PR targets `main`, and check workflow triggers (`pull_request` / `push` branch filters).
|
|
67
|
+
- Use `gh pr checks <PR_NUMBER> -R nmhjklnm/cue-command` to see if checks are present.
|
|
68
|
+
|
|
69
|
+
- **CI fails (works locally but fails in CI)**
|
|
70
|
+
- Prefer `npm ci` (depends on the lockfile) and keep `package-lock.json` in sync with `package.json`.
|
|
71
|
+
- Use `gh run view <RUN_ID> -R nmhjklnm/cue-command` to inspect the failing step.
|
|
72
|
+
|
|
73
|
+
- **Merge button disabled / merge method rejected**
|
|
74
|
+
- The ruleset allows only `squash` / `rebase`; merge commits are not allowed.
|
|
75
|
+
- Selecting a disallowed merge method in the UI will be blocked by the rules.
|
|
76
|
+
|
|
77
|
+
- **Conflicts / need to sync with `main`**
|
|
78
|
+
- Update your branch with the latest `main` (rebase or merge per team preference).
|
|
79
|
+
- After resolving conflicts, push again and CI will rerun.
|
|
80
|
+
|
|
81
|
+
- **Useful gh commands**
|
|
82
|
+
- View PR: `gh pr view <PR_NUMBER> -R nmhjklnm/cue-command`
|
|
83
|
+
- View diff: `gh pr diff <PR_NUMBER> -R nmhjklnm/cue-command`
|
|
84
|
+
- View checks: `gh pr checks <PR_NUMBER> -R nmhjklnm/cue-command`
|
|
85
|
+
- List main runs: `gh run list -R nmhjklnm/cue-command --branch main`
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { readAllStdin } = require('./io');
|
|
2
2
|
const { handleCommand } = require('./handler');
|
|
3
3
|
const { parseTagBlocksEnvelope } = require('./envelope');
|
|
4
|
-
const { protoApply, protoInit, protoLs, protoPath, protoRender } = require('./proto');
|
|
4
|
+
const { protoApply, protoRemove, protoInit, protoLs, protoPath, protoRender } = require('./proto');
|
|
5
5
|
const pkg = require('../package.json');
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
@@ -99,6 +99,7 @@ async function main() {
|
|
|
99
99
|
' cueme -p|--protocol',
|
|
100
100
|
' cueme proto <agent>',
|
|
101
101
|
' cueme proto apply <agent>',
|
|
102
|
+
' cueme proto rm|remove <agent>',
|
|
102
103
|
' cueme proto init',
|
|
103
104
|
' cueme proto ls',
|
|
104
105
|
' cueme proto path <agent>',
|
|
@@ -258,6 +259,17 @@ async function main() {
|
|
|
258
259
|
return;
|
|
259
260
|
}
|
|
260
261
|
|
|
262
|
+
if (action === 'rm' || action === 'remove') {
|
|
263
|
+
const agent = pos[1];
|
|
264
|
+
if (!agent) {
|
|
265
|
+
process.stderr.write('error: missing <agent>\n');
|
|
266
|
+
process.exitCode = 2;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
process.stdout.write(protoRemove(String(agent)) + '\n');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
261
273
|
if (action === 'path') {
|
|
262
274
|
const agent = pos[1];
|
|
263
275
|
if (!agent) {
|
package/src/proto.js
CHANGED
|
@@ -91,6 +91,22 @@ function detectWindsurfCandidates({ platform }) {
|
|
|
91
91
|
return candidates;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
function detectKiroCandidates({ platform }) {
|
|
95
|
+
const candidates = [];
|
|
96
|
+
const home = os.homedir();
|
|
97
|
+
const userProfile = process.env.USERPROFILE || home;
|
|
98
|
+
|
|
99
|
+
// User-level only (no repo-local detection for Kiro)
|
|
100
|
+
// Kiro uses ~/.kiro/steering/ directory for global steering files
|
|
101
|
+
if (platform === 'macos') candidates.push(path.join(home, '.kiro', 'steering', 'cueme_proto.md'));
|
|
102
|
+
if (platform === 'linux') candidates.push(path.join(home, '.kiro', 'steering', 'cueme_proto.md'));
|
|
103
|
+
if (platform === 'windows') {
|
|
104
|
+
candidates.push(path.join(userProfile, '.kiro', 'steering', 'cueme_proto.md'));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return candidates;
|
|
108
|
+
}
|
|
109
|
+
|
|
94
110
|
function firstExistingPath(candidates) {
|
|
95
111
|
for (const p of candidates) {
|
|
96
112
|
if (typeof p === 'string' && p.trim().length > 0 && pathExists(p)) return p;
|
|
@@ -125,6 +141,11 @@ function defaultPathMapTemplate() {
|
|
|
125
141
|
out['windows.windsurf'] = path.join(userProfile, '.codeium', 'windsurf', 'memories', 'global_rules.md');
|
|
126
142
|
out['linux.windsurf'] = path.join(home, '.codeium', 'windsurf', 'memories', 'global_rules.md');
|
|
127
143
|
|
|
144
|
+
// Kiro
|
|
145
|
+
out['macos.kiro'] = path.join(home, '.kiro', 'steering', 'cueme_proto.md');
|
|
146
|
+
out['windows.kiro'] = path.join(userProfile, '.kiro', 'steering', 'cueme_proto.md');
|
|
147
|
+
out['linux.kiro'] = path.join(home, '.kiro', 'steering', 'cueme_proto.md');
|
|
148
|
+
|
|
128
149
|
return out;
|
|
129
150
|
}
|
|
130
151
|
|
|
@@ -135,6 +156,7 @@ function defaultConfigTemplate() {
|
|
|
135
156
|
'cueme.proto.prefix': {
|
|
136
157
|
windsurf: [],
|
|
137
158
|
vscode: ['---', 'applyTo: "**"', '---'],
|
|
159
|
+
kiro: [],
|
|
138
160
|
},
|
|
139
161
|
'cueme.proto.protocol_path': protocolPath,
|
|
140
162
|
};
|
|
@@ -144,9 +166,10 @@ function detectAndFillTemplatePaths(tpl) {
|
|
|
144
166
|
const platform = getPlatformKey();
|
|
145
167
|
const keyVscode = `${platform}.vscode`;
|
|
146
168
|
const keyWindsurf = `${platform}.windsurf`;
|
|
169
|
+
const keyKiro = `${platform}.kiro`;
|
|
147
170
|
|
|
148
171
|
const pathMap = tpl['cueme.proto.path'] || {};
|
|
149
|
-
const detected = { platform, vscode: '', windsurf: '' };
|
|
172
|
+
const detected = { platform, vscode: '', windsurf: '', kiro: '' };
|
|
150
173
|
|
|
151
174
|
if (typeof pathMap !== 'object' || Array.isArray(pathMap)) {
|
|
152
175
|
return { tpl, detected };
|
|
@@ -169,6 +192,14 @@ function detectAndFillTemplatePaths(tpl) {
|
|
|
169
192
|
}
|
|
170
193
|
}
|
|
171
194
|
|
|
195
|
+
if (typeof pathMap[keyKiro] !== 'string' || pathMap[keyKiro].trim().length === 0) {
|
|
196
|
+
const p = firstExistingPath(detectKiroCandidates({ platform }));
|
|
197
|
+
if (p) {
|
|
198
|
+
pathMap[keyKiro] = p;
|
|
199
|
+
detected.kiro = p;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
172
203
|
tpl['cueme.proto.path'] = pathMap;
|
|
173
204
|
return { tpl, detected };
|
|
174
205
|
}
|
|
@@ -368,15 +399,59 @@ function protoApply(agent) {
|
|
|
368
399
|
return `ok: applied to ${targetPath}`;
|
|
369
400
|
}
|
|
370
401
|
|
|
402
|
+
function protoRemove(agent) {
|
|
403
|
+
const cfg = readConfigOrThrow({ auto_init: true });
|
|
404
|
+
const targetPath = resolveTargetPath({ cfg, agent });
|
|
405
|
+
|
|
406
|
+
let existing = '';
|
|
407
|
+
try {
|
|
408
|
+
existing = fs.readFileSync(targetPath, 'utf8');
|
|
409
|
+
} catch {
|
|
410
|
+
return `ok: file does not exist: ${targetPath}`;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const beginMatch = existing.match(BEGIN_MARKER_RE);
|
|
414
|
+
const endMatch = existing.match(END_MARKER_RE);
|
|
415
|
+
|
|
416
|
+
if (!beginMatch || !endMatch || endMatch.index <= beginMatch.index) {
|
|
417
|
+
return `ok: no managed block found in: ${targetPath}`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const beginIdx = beginMatch.index;
|
|
421
|
+
const endIdx = endMatch.index;
|
|
422
|
+
const endLen = endMatch[0].length;
|
|
423
|
+
|
|
424
|
+
const before = existing.slice(0, beginIdx);
|
|
425
|
+
const after = existing.slice(endIdx + endLen);
|
|
426
|
+
|
|
427
|
+
const eol = detectEol(existing);
|
|
428
|
+
const afterTrim = after.startsWith(eol) ? after.slice(eol.length) : after;
|
|
429
|
+
const out = before + afterTrim;
|
|
430
|
+
|
|
431
|
+
if (out.trim().length === 0) {
|
|
432
|
+
try {
|
|
433
|
+
fs.unlinkSync(targetPath);
|
|
434
|
+
return `ok: removed managed block and deleted empty file: ${targetPath}`;
|
|
435
|
+
} catch (err) {
|
|
436
|
+
throw new Error(`error: failed to delete file after removing managed block: ${targetPath}: ${err.message}`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
fs.writeFileSync(targetPath, out, 'utf8');
|
|
441
|
+
return `ok: removed managed block from: ${targetPath}`;
|
|
442
|
+
}
|
|
443
|
+
|
|
371
444
|
function protoInit() {
|
|
372
445
|
const { created, path: p, detected } = initConfigIfMissing();
|
|
373
446
|
if (!created) return `ok: exists ${p}`;
|
|
374
447
|
const platform = detected && detected.platform ? detected.platform : getPlatformKey();
|
|
375
448
|
const keyVscode = `${platform}.vscode`;
|
|
376
449
|
const keyWindsurf = `${platform}.windsurf`;
|
|
450
|
+
const keyKiro = `${platform}.kiro`;
|
|
377
451
|
const vs = detected && detected.vscode ? 'detected' : 'empty';
|
|
378
452
|
const ws = detected && detected.windsurf ? 'detected' : 'empty';
|
|
379
|
-
|
|
453
|
+
const ks = detected && detected.kiro ? 'detected' : 'empty';
|
|
454
|
+
return `ok: initialized ${p} (auto-detect: ${keyVscode}=${vs}, ${keyWindsurf}=${ws}, ${keyKiro}=${ks})`;
|
|
380
455
|
}
|
|
381
456
|
|
|
382
457
|
module.exports = {
|
|
@@ -384,6 +459,7 @@ module.exports = {
|
|
|
384
459
|
END_MARKER,
|
|
385
460
|
getPlatformKey,
|
|
386
461
|
protoApply,
|
|
462
|
+
protoRemove,
|
|
387
463
|
protoInit,
|
|
388
464
|
protoLs,
|
|
389
465
|
protoPath,
|