refacil-sdd-ai 4.5.5 → 4.5.8
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 +2 -2
- package/lib/commands/sdd.js +111 -18
- package/package.json +1 -1
- package/skills/archive/SKILL.md +31 -17
- package/skills/prereqs/METHODOLOGY-CONTRACT.md +2 -0
- package/skills/up-code/SKILL.md +8 -6
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ All invoked as `/refacil:<name>` in Claude Code, Cursor, or OpenCode.
|
|
|
153
153
|
| `/refacil:test` | Generate unit tests from the artifacts |
|
|
154
154
|
| `/refacil:verify` | Validate implementation vs specs (with optional autofix) |
|
|
155
155
|
| `/refacil:review` | Quality checklist, emits `.review-passed` if approved |
|
|
156
|
-
| `/refacil:archive` | Archive the completed change + sync specs (requests
|
|
156
|
+
| `/refacil:archive` | Archive the completed change + sync specs (requests task references) |
|
|
157
157
|
| `/refacil:up-code` | Commit + push + PR (runs review if missing) |
|
|
158
158
|
| `/refacil:bug` | Full bugfix flow with regression tests |
|
|
159
159
|
| `/refacil:update` | Detect and apply pending methodology migrations to the current repo |
|
|
@@ -259,7 +259,7 @@ From there, the full cycle is:
|
|
|
259
259
|
- For features/improvements: the CLI moves artifacts to `archive/` and extracts `.review-passed` fields to `review.yaml` inside each affected spec.
|
|
260
260
|
- For bugs: manual archiving, creates `refacil-sdd/specs/fix-*/spec.md` in standard format + `review.yaml`.
|
|
261
261
|
- A single branch can accumulate multiple bugs, each in its own independent `fix-*/` folder.
|
|
262
|
-
- `/refacil:archive` always requests one or more **
|
|
262
|
+
- `/refacil:archive` always requests one or more **task references** associated with the change before proceeding. Accepted formats: URL, ticket/issue identifier, or task name. References are stored in `review.yaml` under the `taskReferences` field (YAML list). This field is mandatory — archiving does not proceed until the user provides at least one reference.
|
|
263
263
|
|
|
264
264
|
---
|
|
265
265
|
|
package/lib/commands/sdd.js
CHANGED
|
@@ -62,6 +62,47 @@ function validateChangeName(name) {
|
|
|
62
62
|
return { valid: true };
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
function resolveExistingChangeName(projectRoot, inputName) {
|
|
66
|
+
if (!inputName || typeof inputName !== 'string') {
|
|
67
|
+
return { ok: false, reason: 'El nombre del cambio no puede estar vacío.' };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const normalizedInput = inputName.trim();
|
|
71
|
+
const lowerInput = normalizedInput.toLowerCase();
|
|
72
|
+
const changesDir = path.join(projectRoot, 'refacil-sdd', 'changes');
|
|
73
|
+
|
|
74
|
+
// Keep backward-compatible behavior when directory doesn't exist yet.
|
|
75
|
+
if (!fs.existsSync(changesDir)) {
|
|
76
|
+
return { ok: true, name: lowerInput };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const entries = fs.readdirSync(changesDir, { withFileTypes: true })
|
|
80
|
+
.filter((e) => e.isDirectory() && e.name !== 'archive')
|
|
81
|
+
.map((e) => e.name);
|
|
82
|
+
|
|
83
|
+
if (entries.includes(normalizedInput)) {
|
|
84
|
+
return { ok: true, name: normalizedInput };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (entries.includes(lowerInput)) {
|
|
88
|
+
return { ok: true, name: lowerInput };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const ciMatches = entries.filter((n) => n.toLowerCase() === lowerInput);
|
|
92
|
+
if (ciMatches.length === 1) {
|
|
93
|
+
return { ok: true, name: ciMatches[0] };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (ciMatches.length > 1) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
reason: `Nombre de cambio ambiguo: '${inputName}'. Coincidencias: ${ciMatches.join(', ')}`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { ok: true, name: lowerInput };
|
|
104
|
+
}
|
|
105
|
+
|
|
65
106
|
function autoMigrateOpenspec(root) {
|
|
66
107
|
const oldDir = path.join(root, 'openspec');
|
|
67
108
|
const newDir = path.join(root, 'refacil-sdd');
|
|
@@ -180,7 +221,15 @@ function cmdNewChange(argv, projectRoot) {
|
|
|
180
221
|
|
|
181
222
|
function cmdArchive(argv, projectRoot) {
|
|
182
223
|
const args = parseArgs(argv);
|
|
183
|
-
const
|
|
224
|
+
const rawName = args._positional[0];
|
|
225
|
+
|
|
226
|
+
autoMigrateOpenspec(projectRoot);
|
|
227
|
+
const resolved = resolveExistingChangeName(projectRoot, rawName);
|
|
228
|
+
if (!resolved.ok) {
|
|
229
|
+
console.error(resolved.reason);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const name = resolved.name;
|
|
184
233
|
|
|
185
234
|
const validation = validateChangeName(name);
|
|
186
235
|
if (!validation.valid) {
|
|
@@ -188,8 +237,6 @@ function cmdArchive(argv, projectRoot) {
|
|
|
188
237
|
process.exit(1);
|
|
189
238
|
}
|
|
190
239
|
|
|
191
|
-
autoMigrateOpenspec(projectRoot);
|
|
192
|
-
|
|
193
240
|
const sourceDir = path.join(projectRoot, 'refacil-sdd', 'changes', name);
|
|
194
241
|
if (!fs.existsSync(sourceDir)) {
|
|
195
242
|
console.error(`No existe el cambio '${name}' en refacil-sdd/changes/${name}/`);
|
|
@@ -222,14 +269,21 @@ function cmdArchive(argv, projectRoot) {
|
|
|
222
269
|
|
|
223
270
|
function cmdSetMemory(argv, projectRoot) {
|
|
224
271
|
const args = parseArgs(argv);
|
|
225
|
-
const
|
|
272
|
+
const rawName = args._positional[0];
|
|
226
273
|
|
|
227
|
-
if (!
|
|
274
|
+
if (!rawName) {
|
|
228
275
|
console.error('Uso: refacil-sdd-ai sdd set-memory <nombre-cambio> [--last-step <value>] [--stack-detected <value>] [--touched-files <csv>] [--commands-run <value>] [--criteria-run <csv>]');
|
|
229
276
|
process.exit(1);
|
|
230
277
|
}
|
|
231
278
|
|
|
232
279
|
const root = projectRoot;
|
|
280
|
+
autoMigrateOpenspec(root);
|
|
281
|
+
const resolved = resolveExistingChangeName(root, rawName);
|
|
282
|
+
if (!resolved.ok) {
|
|
283
|
+
console.error(resolved.reason);
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
const name = resolved.name;
|
|
233
287
|
|
|
234
288
|
// Guard: ensure the change directory exists before any file operation
|
|
235
289
|
const changeDir = path.join(root, 'refacil-sdd', 'changes', name);
|
|
@@ -274,15 +328,22 @@ function cmdSetMemory(argv, projectRoot) {
|
|
|
274
328
|
|
|
275
329
|
function cmdGetMemory(argv, projectRoot) {
|
|
276
330
|
const args = parseArgs(argv);
|
|
277
|
-
const
|
|
331
|
+
const rawName = args._positional[0];
|
|
278
332
|
const wantJson = args.json === true;
|
|
279
333
|
|
|
280
|
-
if (!
|
|
334
|
+
if (!rawName) {
|
|
281
335
|
console.error('Uso: refacil-sdd-ai sdd get-memory <nombre-cambio> [--json]');
|
|
282
336
|
process.exit(1);
|
|
283
337
|
}
|
|
284
338
|
|
|
285
339
|
const root = projectRoot;
|
|
340
|
+
autoMigrateOpenspec(root);
|
|
341
|
+
const resolved = resolveExistingChangeName(root, rawName);
|
|
342
|
+
if (!resolved.ok) {
|
|
343
|
+
console.error(resolved.reason);
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
const name = resolved.name;
|
|
286
347
|
const memoryPath = path.join(root, 'refacil-sdd', 'changes', name, 'memory.yaml');
|
|
287
348
|
|
|
288
349
|
if (!fs.existsSync(memoryPath)) {
|
|
@@ -309,14 +370,21 @@ function cmdGetMemory(argv, projectRoot) {
|
|
|
309
370
|
|
|
310
371
|
function cmdSetReviewFails(argv, projectRoot) {
|
|
311
372
|
const args = parseArgs(argv);
|
|
312
|
-
const
|
|
373
|
+
const rawName = args._positional[0];
|
|
313
374
|
|
|
314
|
-
if (!
|
|
375
|
+
if (!rawName) {
|
|
315
376
|
console.error('Uso: refacil-sdd-ai sdd set-review-fails <nombre-cambio> --files <csv>');
|
|
316
377
|
process.exit(1);
|
|
317
378
|
}
|
|
318
379
|
|
|
319
380
|
const root = projectRoot;
|
|
381
|
+
autoMigrateOpenspec(root);
|
|
382
|
+
const resolved = resolveExistingChangeName(root, rawName);
|
|
383
|
+
if (!resolved.ok) {
|
|
384
|
+
console.error(resolved.reason);
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
const name = resolved.name;
|
|
320
388
|
const changeDir = path.join(root, 'refacil-sdd', 'changes', name);
|
|
321
389
|
if (!fs.existsSync(changeDir)) {
|
|
322
390
|
console.error(`No existe el cambio '${name}' en refacil-sdd/changes/${name}/`);
|
|
@@ -334,14 +402,21 @@ function cmdSetReviewFails(argv, projectRoot) {
|
|
|
334
402
|
|
|
335
403
|
function cmdClearReviewFails(argv, projectRoot) {
|
|
336
404
|
const args = parseArgs(argv);
|
|
337
|
-
const
|
|
405
|
+
const rawName = args._positional[0];
|
|
338
406
|
|
|
339
|
-
if (!
|
|
407
|
+
if (!rawName) {
|
|
340
408
|
console.error('Uso: refacil-sdd-ai sdd clear-review-fails <nombre-cambio>');
|
|
341
409
|
process.exit(1);
|
|
342
410
|
}
|
|
343
411
|
|
|
344
412
|
const root = projectRoot;
|
|
413
|
+
autoMigrateOpenspec(root);
|
|
414
|
+
const resolved = resolveExistingChangeName(root, rawName);
|
|
415
|
+
if (!resolved.ok) {
|
|
416
|
+
console.error(resolved.reason);
|
|
417
|
+
process.exit(1);
|
|
418
|
+
}
|
|
419
|
+
const name = resolved.name;
|
|
345
420
|
const reviewFailsPath = path.join(root, 'refacil-sdd', 'changes', name, '.review-last-fails.json');
|
|
346
421
|
|
|
347
422
|
if (fs.existsSync(reviewFailsPath)) {
|
|
@@ -392,15 +467,21 @@ function cmdList(argv, projectRoot) {
|
|
|
392
467
|
|
|
393
468
|
function cmdStatus(argv, projectRoot) {
|
|
394
469
|
const args = parseArgs(argv);
|
|
395
|
-
const
|
|
470
|
+
const rawName = args._positional[0];
|
|
396
471
|
const wantJson = args.json === true;
|
|
397
472
|
|
|
398
|
-
if (!
|
|
473
|
+
if (!rawName) {
|
|
399
474
|
console.error('Uso: refacil-sdd-ai sdd status <nombre-cambio> [--json]');
|
|
400
475
|
process.exit(1);
|
|
401
476
|
}
|
|
402
477
|
|
|
403
478
|
autoMigrateOpenspec(projectRoot);
|
|
479
|
+
const resolved = resolveExistingChangeName(projectRoot, rawName);
|
|
480
|
+
if (!resolved.ok) {
|
|
481
|
+
console.error(resolved.reason);
|
|
482
|
+
process.exit(1);
|
|
483
|
+
}
|
|
484
|
+
const name = resolved.name;
|
|
404
485
|
|
|
405
486
|
const changeDir = path.join(projectRoot, 'refacil-sdd', 'changes', name);
|
|
406
487
|
if (!fs.existsSync(changeDir)) {
|
|
@@ -481,9 +562,9 @@ function cmdStatus(argv, projectRoot) {
|
|
|
481
562
|
|
|
482
563
|
function cmdMarkReviewed(argv, projectRoot) {
|
|
483
564
|
const args = parseArgs(argv);
|
|
484
|
-
const
|
|
565
|
+
const rawName = args._positional[0];
|
|
485
566
|
|
|
486
|
-
if (!
|
|
567
|
+
if (!rawName) {
|
|
487
568
|
console.error('Uso: refacil-sdd-ai sdd mark-reviewed <nombre-cambio> --verdict <verdict> --summary "<resumen>" [--fail-count N] [--preexisting-count N] [--blockers]');
|
|
488
569
|
process.exit(1);
|
|
489
570
|
}
|
|
@@ -499,6 +580,12 @@ function cmdMarkReviewed(argv, projectRoot) {
|
|
|
499
580
|
}
|
|
500
581
|
|
|
501
582
|
autoMigrateOpenspec(projectRoot);
|
|
583
|
+
const resolved = resolveExistingChangeName(projectRoot, rawName);
|
|
584
|
+
if (!resolved.ok) {
|
|
585
|
+
console.error(resolved.reason);
|
|
586
|
+
process.exit(1);
|
|
587
|
+
}
|
|
588
|
+
const name = resolved.name;
|
|
502
589
|
|
|
503
590
|
const changeDir = path.join(projectRoot, 'refacil-sdd', 'changes', name);
|
|
504
591
|
if (!fs.existsSync(changeDir)) {
|
|
@@ -522,9 +609,9 @@ function cmdMarkReviewed(argv, projectRoot) {
|
|
|
522
609
|
|
|
523
610
|
function cmdTasksUpdate(argv, projectRoot) {
|
|
524
611
|
const args = parseArgs(argv);
|
|
525
|
-
const
|
|
612
|
+
const rawName = args._positional[0];
|
|
526
613
|
|
|
527
|
-
if (!
|
|
614
|
+
if (!rawName) {
|
|
528
615
|
console.error('Uso: refacil-sdd-ai sdd tasks-update <nombre-cambio> --task N --done');
|
|
529
616
|
process.exit(1);
|
|
530
617
|
}
|
|
@@ -541,6 +628,12 @@ function cmdTasksUpdate(argv, projectRoot) {
|
|
|
541
628
|
}
|
|
542
629
|
|
|
543
630
|
autoMigrateOpenspec(projectRoot);
|
|
631
|
+
const resolved = resolveExistingChangeName(projectRoot, rawName);
|
|
632
|
+
if (!resolved.ok) {
|
|
633
|
+
console.error(resolved.reason);
|
|
634
|
+
process.exit(1);
|
|
635
|
+
}
|
|
636
|
+
const name = resolved.name;
|
|
544
637
|
|
|
545
638
|
const tasksFile = path.join(projectRoot, 'refacil-sdd', 'changes', name, 'tasks.md');
|
|
546
639
|
if (!fs.existsSync(tasksFile)) {
|
|
@@ -661,4 +754,4 @@ function handleSdd(sub, argv, projectRoot) {
|
|
|
661
754
|
}
|
|
662
755
|
}
|
|
663
756
|
|
|
664
|
-
module.exports = { handleSdd, parseArgs, autoMigrateOpenspec, validateChangeName, findProjectRoot };
|
|
757
|
+
module.exports = { handleSdd, parseArgs, autoMigrateOpenspec, validateChangeName, resolveExistingChangeName, findProjectRoot };
|
package/package.json
CHANGED
package/skills/archive/SKILL.md
CHANGED
|
@@ -22,7 +22,7 @@ Verify the change is truly complete:
|
|
|
22
22
|
|
|
23
23
|
2. **Tests pass**: Resolve and run the test command according to `refacil-prereqs/METHODOLOGY-CONTRACT.md`. If there are failing tests, inform and ask if they want to continue.
|
|
24
24
|
|
|
25
|
-
3. **
|
|
25
|
+
3. **Working tree scope hygiene**: Run `git status` and check whether there are files unrelated to the current change scope. It is expected to have uncommitted changes in this step. If unrelated files are detected, warn the user and ask whether to continue archiving anyway. Do not suggest commit in this step; commit/push decisions are handled in `refacil:up-code`.
|
|
26
26
|
|
|
27
27
|
4. **Review approved (blocking)**: Verify that the `.review-passed` file exists in the change folder (`refacil-sdd/changes/[change-name]/.review-passed`) following **`METHODOLOGY-CONTRACT.md` §8** (dotfile; do not conclude by listings without dotfiles). If it does NOT exist, **stop the archiving** and inform the user:
|
|
28
28
|
```
|
|
@@ -34,23 +34,33 @@ Verify the change is truly complete:
|
|
|
34
34
|
If any of checks 1-3 fail, inform the user but allow them to decide whether to continue.
|
|
35
35
|
If check 4 fails, archiving cannot continue.
|
|
36
36
|
|
|
37
|
-
### Step 1.5: Request
|
|
37
|
+
### Step 1.5: Request task reference(s) (traceability — mandatory)
|
|
38
38
|
|
|
39
|
-
Before proceeding to archiving, ask the user for the
|
|
39
|
+
Before proceeding to archiving, ask the user for the task reference(s) associated with the change (URL, issue/ticket number, or short task name):
|
|
40
40
|
|
|
41
41
|
```
|
|
42
|
-
|
|
42
|
+
Task reference(s) associated with this change (URL, ticket number, or task name; if multiple, separate with commas):
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
**Rules:**
|
|
46
|
-
- The user may enter one or multiple
|
|
47
|
-
-
|
|
46
|
+
- The user may enter one or multiple references separated by commas in a single message.
|
|
47
|
+
- Accepted formats: URL (`https://tracker.company.com/TASK-123`), identifier (`TASK-123`, `INC-9001`), or short descriptive name (`ajuste checkout`).
|
|
48
|
+
- Minimum validation rule for each reference (operational and mandatory):
|
|
49
|
+
- `URL`: starts with `http://` or `https://` and has at least one non-space character after the protocol.
|
|
50
|
+
- `identifier`: matches `^[A-Za-z][A-Za-z0-9_-]*-\d+$` (examples: `BP-4610`, `INC-9001`).
|
|
51
|
+
- `short name`: 3-80 characters, includes at least one letter, and is not only symbols/spaces.
|
|
52
|
+
- If the user provides no reference (answers empty, "n", "no", "none", blank Enter), **block the archiving** and ask again:
|
|
48
53
|
```
|
|
49
|
-
Cannot archive without at least one
|
|
50
|
-
Provide the
|
|
54
|
+
Cannot archive without at least one task reference.
|
|
55
|
+
Provide the task URL, identifier, or name that originated this change to continue.
|
|
51
56
|
```
|
|
52
|
-
-
|
|
53
|
-
|
|
57
|
+
- If the user provides a non-empty but invalid value (for example: `---`, `???`, `123`, `_`), **reject it** and ask again:
|
|
58
|
+
```
|
|
59
|
+
Invalid task reference format.
|
|
60
|
+
Use one of: URL (https://...), identifier (ABC-123), or short task name (3-80 chars, includes letters).
|
|
61
|
+
```
|
|
62
|
+
- Repeat until at least one valid reference is received.
|
|
63
|
+
- Save the references in `taskReferences` to use when writing `review.yaml` in the following steps.
|
|
54
64
|
|
|
55
65
|
### Step 2: Determine change type
|
|
56
66
|
|
|
@@ -75,7 +85,7 @@ Bug fixes only contain `summary.md` (and optionally `.review-passed`). The CLI `
|
|
|
75
85
|
|
|
76
86
|
2. **Document in specs**: using the content read in step 0, create an individual spec at `$(git rev-parse --show-toplevel)/refacil-sdd/specs/[descriptive-name]/spec.md`.
|
|
77
87
|
|
|
78
|
-
**Spec folder name**: Use a short, clear kebab-case description of the bug (e.g. `fix-session-timeout-redis`, `fix-null-pointer-payment-callback`). **Do NOT use ticket IDs** (REF-123,
|
|
88
|
+
**Spec folder name**: Use a short, clear kebab-case description of the bug (e.g. `fix-session-timeout-redis`, `fix-null-pointer-payment-callback`). **Do NOT use ticket IDs** (REF-123, TASK-456, etc.) — the name must be descriptive so `/refacil:explore` can find and understand the fix without external context.
|
|
79
89
|
|
|
80
90
|
Content of `spec.md` (Refacil SDD spec layout):
|
|
81
91
|
```markdown
|
|
@@ -97,7 +107,7 @@ Bug fixes only contain `summary.md` (and optionally `.review-passed`). The CLI `
|
|
|
97
107
|
- **THEN** the system SHALL [normal behavior without regression]
|
|
98
108
|
```
|
|
99
109
|
|
|
100
|
-
3. **Persist review metadata separately**: create `$(git rev-parse --show-toplevel)/refacil-sdd/specs/[descriptive-name]/review.yaml` with the fields from `.review-passed` plus the
|
|
110
|
+
3. **Persist review metadata separately**: create `$(git rev-parse --show-toplevel)/refacil-sdd/specs/[descriptive-name]/review.yaml` with the fields from `.review-passed` plus the task references from Step 1.5:
|
|
101
111
|
```yaml
|
|
102
112
|
verdict: APROBADO|APROBADO CON OBSERVACIONES
|
|
103
113
|
date: 2026-04-10T00:00:00.000Z
|
|
@@ -105,8 +115,9 @@ Bug fixes only contain `summary.md` (and optionally `.review-passed`). The CLI `
|
|
|
105
115
|
summary: "..."
|
|
106
116
|
failCount: 0
|
|
107
117
|
blockers: false
|
|
108
|
-
|
|
109
|
-
- https://
|
|
118
|
+
taskReferences:
|
|
119
|
+
- https://tracker.company.com/TASK-123
|
|
120
|
+
- TASK-123
|
|
110
121
|
```
|
|
111
122
|
|
|
112
123
|
4. Continue to **Step 3**.
|
|
@@ -115,6 +126,8 @@ Bug fixes only contain `summary.md` (and optionally `.review-passed`). The CLI `
|
|
|
115
126
|
|
|
116
127
|
The spec and review evidence are written **before** running the CLI archive command, while the artifacts are still at their original paths. The CLI only moves the folder — it never syncs specs.
|
|
117
128
|
|
|
129
|
+
`refacil-sdd-ai sdd archive` normalizes the provided `changeName` to lowercase before validation/path resolution. Prefer lowercase names for consistency across commands and records.
|
|
130
|
+
|
|
118
131
|
1. **Sync spec to `refacil-sdd/specs/` (before archiving)**:
|
|
119
132
|
- Read `refacil-sdd/changes/<changeName>/specs.md` (and all `.md` under `specs/` if that subfolder exists).
|
|
120
133
|
- Determine the spec folder name: use `<changeName>` unless a more descriptive name is clearly better.
|
|
@@ -123,7 +136,7 @@ The spec and review evidence are written **before** running the CLI archive comm
|
|
|
123
136
|
|
|
124
137
|
2. **Persist review evidence (before archiving)**:
|
|
125
138
|
- Read `refacil-sdd/changes/<changeName>/.review-passed` (dotfile — use `ls -la` or read by explicit path, not directory listing).
|
|
126
|
-
- Create/update `refacil-sdd/specs/<specName>/review.yaml` with its fields plus `
|
|
139
|
+
- Create/update `refacil-sdd/specs/<specName>/review.yaml` with its fields plus `taskReferences` from Step 1.5:
|
|
127
140
|
```yaml
|
|
128
141
|
verdict: APROBADO|APROBADO CON OBSERVACIONES
|
|
129
142
|
date: 2026-04-10T00:00:00.000Z
|
|
@@ -131,8 +144,9 @@ The spec and review evidence are written **before** running the CLI archive comm
|
|
|
131
144
|
summary: "..."
|
|
132
145
|
failCount: 0
|
|
133
146
|
blockers: false
|
|
134
|
-
|
|
135
|
-
- https://
|
|
147
|
+
taskReferences:
|
|
148
|
+
- https://tracker.company.com/TASK-123
|
|
149
|
+
- TASK-123
|
|
136
150
|
```
|
|
137
151
|
- If `review.yaml` already exists, update only the fields that changed without removing others.
|
|
138
152
|
|
|
@@ -127,6 +127,8 @@ If the user does not request detail, use concise mode.
|
|
|
127
127
|
|
|
128
128
|
- `archive` requires `.review-passed` as a blocking precondition (verify existence according to **§8**).
|
|
129
129
|
- When archiving regular changes (proposal-driven flow), the `.review-passed` metadata must be persisted in `refacil-sdd/specs/`.
|
|
130
|
+
- `archive` must request and persist at least one task reference for traceability. Accepted formats: URL, ticket/issue identifier, or short task name.
|
|
131
|
+
- The recommended field in `review.yaml` is `taskReferences` (YAML list). Do not enforce provider-specific fields such as `jiraTasks`.
|
|
130
132
|
- The recommended format is `review.yaml` inside each affected spec folder.
|
|
131
133
|
- If it cannot be reliably mapped to specific specs, record the evidence in `refacil-sdd/specs/review-metadata.yaml`.
|
|
132
134
|
|
package/skills/up-code/SKILL.md
CHANGED
|
@@ -83,15 +83,17 @@ Run `git push -u origin [current-branch]` to push the changes.
|
|
|
83
83
|
Which branch do you want to create the PR to? (recommended: testing)
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
If the user indicates a different branch than `testing`, verify it exists on the remote by inspecting `git branch -r` output before generating the link. If it does not exist, inform the user and ask them to confirm or correct the name.
|
|
87
87
|
|
|
88
|
-
3. Get the remote repository URL with `git remote get-url origin` and
|
|
88
|
+
3. Get the remote repository URL with `git remote get-url origin` and detect the VCS hosting used by this repository to generate the correct PR/MR link:
|
|
89
89
|
- **GitHub** (url contains `github.com`): `https://github.com/[owner]/[repo]/compare/[target-branch]...[current-branch]?expand=1`
|
|
90
|
-
- **Bitbucket** (url contains `bitbucket.org`): `https://bitbucket.org/[workspace]/[repo]/pull-requests/new?source=[current-branch]&dest=[target-branch]`
|
|
91
|
-
-
|
|
92
|
-
-
|
|
90
|
+
- **Bitbucket Cloud** (url contains `bitbucket.org`): `https://bitbucket.org/[workspace]/[repo]/pull-requests/new?source=[current-branch]&dest=[target-branch]`
|
|
91
|
+
- **GitLab** (url contains `gitlab.` or `gitlab.com`): `https://[gitlab-host]/[group]/[repo]/-/merge_requests/new?merge_request[source_branch]=[current-branch]&merge_request[target_branch]=[target-branch]`
|
|
92
|
+
- **Azure DevOps** (url contains `dev.azure.com` or `visualstudio.com`): build the "create PR" URL for the detected project/repo using source and target branches.
|
|
93
|
+
- For SSH remotes (`git@host:group/repo.git`), extract host/namespace/repo from the segment after `:`.
|
|
94
|
+
- If hosting cannot be determined, do not assume a provider: show the detected remote URL and ask the user which platform is used before generating the final PR/MR link.
|
|
93
95
|
|
|
94
|
-
4. Show the link to the user and recommend PR to `testing`:
|
|
96
|
+
4. Show the generated link (provider-specific) to the user and recommend PR to `testing`:
|
|
95
97
|
```
|
|
96
98
|
Create your PR here: [link]
|
|
97
99
|
|