this-is-enough 0.1.0 → 0.1.2
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/AGENTS.md +26 -16
- package/README.md +2 -2
- package/bin/cli.js +44 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -90,15 +90,15 @@ Run once when adopting this workflow in a new repository.
|
|
|
90
90
|
- `reqs/INTERRUPT.md` must not exist at bootstrap completion
|
|
91
91
|
|
|
92
92
|
4) First requirement starts only after bootstrap
|
|
93
|
-
- create `REQ-*` through lifecycle section `A) Create New Requirement`
|
|
94
|
-
- confirm via section `B) Confirm Requirement` (`full` or `mini` mode)
|
|
93
|
+
- create `REQ-*` through lifecycle section `A) Create New Requirement` (after first feedback gate)
|
|
94
|
+
- confirm via section `B) Confirm Requirement` (after codebase-informed second feedback gate, then `full` or `mini` mode)
|
|
95
95
|
|
|
96
96
|
---
|
|
97
97
|
|
|
98
98
|
## Status Model (Requirement-Level)
|
|
99
99
|
|
|
100
100
|
Allowed statuses:
|
|
101
|
-
- `DRAFT`: requirement exists and is being drafted (lock is active)
|
|
101
|
+
- `DRAFT`: requirement exists and is being drafted through layered feedback/specification (lock is active)
|
|
102
102
|
- `ACTIVE`: confirmed and currently being executed (lock is active)
|
|
103
103
|
- `PAUSED`: intentionally stopped to work on another requirement (lock not held)
|
|
104
104
|
- `BLOCKED`: cannot progress due to external dependency (lock not held)
|
|
@@ -149,6 +149,9 @@ Definitions:
|
|
|
149
149
|
- else announce no active requirement and that new creation is allowed
|
|
150
150
|
|
|
151
151
|
5) Requirement confirmation rule
|
|
152
|
+
- Before roadmap creation, two feedback gates are mandatory:
|
|
153
|
+
- Gate 1 (alignment): summarize user request and receive explicit confirmation that understanding is correct
|
|
154
|
+
- Gate 2 (specification): after codebase exploration and requirement concretization, receive explicit confirmation again
|
|
152
155
|
- Requirement is confirmed by one of:
|
|
153
156
|
- Full mode: `ROADMAP.md` exists.
|
|
154
157
|
- Mini mode: `REQUEST.md` contains a `Mini Roadmap` section and all criteria below are `yes/no`-exactly satisfied:
|
|
@@ -266,24 +269,29 @@ Precondition:
|
|
|
266
269
|
- `reqs/ACTIVE.md` does not exist
|
|
267
270
|
|
|
268
271
|
Steps:
|
|
269
|
-
1.
|
|
270
|
-
2.
|
|
271
|
-
3.
|
|
272
|
-
4. create `reqs/
|
|
273
|
-
5.
|
|
272
|
+
1. summarize the incoming requirement in plain language and list assumptions/open points
|
|
273
|
+
2. request user feedback and obtain explicit alignment confirmation (Gate 1)
|
|
274
|
+
3. if alignment is rejected, revise summary and repeat steps 1-2
|
|
275
|
+
4. create `reqs/REQ-XXXX-<slug>/`
|
|
276
|
+
5. create `REQUEST.md` with aligned scope baseline from Gate 1
|
|
277
|
+
6. create `STATUS.md` with status `DRAFT`
|
|
278
|
+
7. create `reqs/ACTIVE.md` pointing to this requirement with status `DRAFT`
|
|
279
|
+
8. if sourced from `reqs/INBOX.md`, update that item status to `promoted`
|
|
274
280
|
|
|
275
281
|
### B) Confirm Requirement (`DRAFT` -> `ACTIVE`)
|
|
276
282
|
Trigger:
|
|
277
|
-
-
|
|
278
|
-
- Full mode: `ROADMAP.md` created in active requirement
|
|
279
|
-
- Mini mode: `REQUEST.md` includes `Mini Roadmap` and meets all Mini criteria
|
|
283
|
+
- active requirement is in `DRAFT` after Gate 1 alignment
|
|
280
284
|
|
|
281
285
|
Steps:
|
|
282
|
-
1.
|
|
283
|
-
2.
|
|
284
|
-
3.
|
|
285
|
-
4.
|
|
286
|
-
5.
|
|
286
|
+
1. perform deep codebase exploration for the requirement scope
|
|
287
|
+
2. map impacted components/files, constraints, risks, and validation approach in `REQUEST.md`
|
|
288
|
+
3. present the codebase-informed requirement specification to user and obtain explicit confirmation (Gate 2)
|
|
289
|
+
4. if Gate 2 feedback requests changes, iterate steps 1-3 until confirmed
|
|
290
|
+
5. choose confirmation mode (`full` or `mini`)
|
|
291
|
+
6. if `full`: create `ROADMAP.md` (phases, goals, acceptance)
|
|
292
|
+
7. if `mini`: add `Mini Roadmap` in `REQUEST.md` (tasks + acceptance + criteria flags)
|
|
293
|
+
8. update `STATUS.md` to `ACTIVE` and record `roadmap_mode: full|mini`
|
|
294
|
+
9. update `reqs/ACTIVE.md` to `ACTIVE`
|
|
287
295
|
|
|
288
296
|
### C) Execute Phase (loop)
|
|
289
297
|
For each `PHASE-XX`:
|
|
@@ -526,6 +534,8 @@ ADR metadata for selective lookup (required for new ADRs):
|
|
|
526
534
|
|
|
527
535
|
## Prohibitions (MUST NOT)
|
|
528
536
|
- do not create a new requirement while `reqs/ACTIVE.md` exists (except the explicit interrupt exception path)
|
|
537
|
+
- do not create `REQ-*`/`REQUEST.md` before Gate 1 alignment feedback is explicitly confirmed by user
|
|
538
|
+
- do not create `ROADMAP.md` or `REQUEST.md` Mini Roadmap before Gate 2 codebase-informed feedback is explicitly confirmed by user
|
|
529
539
|
- do not treat requirement as confirmed without either:
|
|
530
540
|
- `ROADMAP.md` (full mode), or
|
|
531
541
|
- valid `REQUEST.md` Mini Roadmap that satisfies all Mini criteria (mini mode)
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# This-Is-Enough
|
|
2
2
|
|
|
3
3
|
가볍지만 실행 가능한 에이전트 작업 규칙을 프로젝트에 설치하는 CLI입니다.
|
|
4
4
|
|
|
@@ -53,7 +53,7 @@ node /path/to/this-is-enough/bin/cli.js init --mode existing --cwd /path/to/repo
|
|
|
53
53
|
- `--mode new|existing`
|
|
54
54
|
- `--cwd <path>` (기본값: 현재 디렉토리)
|
|
55
55
|
- `--dry-run` (변경 예정만 출력)
|
|
56
|
-
- `--force` (기존 파일
|
|
56
|
+
- `--force` (기존 파일 덮어쓰기, `AGENTS.md`는 차이가 있으면 `--force` 없이도 백업 후 갱신)
|
|
57
57
|
- `--yes` (호환용, 기본이 이미 non-interactive)
|
|
58
58
|
|
|
59
59
|
### `doctor`
|
package/bin/cli.js
CHANGED
|
@@ -157,6 +157,31 @@ function createFileIfMissing(filePath, content, options, actions) {
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
function syncCoreAgents(filePath, content, options, actions) {
|
|
161
|
+
if (!fs.existsSync(filePath)) {
|
|
162
|
+
actions.push(`create ${filePath}`);
|
|
163
|
+
if (!options.dryRun) {
|
|
164
|
+
fs.writeFileSync(filePath, content, "utf8");
|
|
165
|
+
}
|
|
166
|
+
return { status: "created", backupPath: null };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const current = fs.readFileSync(filePath, "utf8");
|
|
170
|
+
if (current === content) {
|
|
171
|
+
actions.push(`skip up-to-date ${filePath}`);
|
|
172
|
+
return { status: "up-to-date", backupPath: null };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const backupPath = `${filePath}.bak.${timestampForBackup()}`;
|
|
176
|
+
actions.push(`backup ${filePath} -> ${backupPath}`);
|
|
177
|
+
actions.push(`overwrite ${filePath}`);
|
|
178
|
+
if (!options.dryRun) {
|
|
179
|
+
fs.copyFileSync(filePath, backupPath);
|
|
180
|
+
fs.writeFileSync(filePath, content, "utf8");
|
|
181
|
+
}
|
|
182
|
+
return { status: "replaced", backupPath };
|
|
183
|
+
}
|
|
184
|
+
|
|
160
185
|
function timestampForBackup() {
|
|
161
186
|
const now = new Date();
|
|
162
187
|
const p = (n) => String(n).padStart(2, "0");
|
|
@@ -195,7 +220,7 @@ function initProject(options) {
|
|
|
195
220
|
ensureDir(dirPath, options, actions);
|
|
196
221
|
}
|
|
197
222
|
|
|
198
|
-
|
|
223
|
+
const agentsSyncResult = syncCoreAgents(paths.agentsPath, readTemplateAgents(), options, actions);
|
|
199
224
|
writeFileIfNeeded(paths.architecturePath, ARCHITECTURE_TEMPLATE, options, actions);
|
|
200
225
|
writeFileIfNeeded(paths.inboxPath, INBOX_TEMPLATE, options, actions);
|
|
201
226
|
|
|
@@ -243,6 +268,14 @@ function initProject(options) {
|
|
|
243
268
|
}
|
|
244
269
|
}
|
|
245
270
|
|
|
271
|
+
if (agentsSyncResult.status === "replaced") {
|
|
272
|
+
if (options.dryRun) {
|
|
273
|
+
info(`Note: existing AGENTS.md would be backed up to ${agentsSyncResult.backupPath} before replacement.`);
|
|
274
|
+
} else {
|
|
275
|
+
info(`Note: existing AGENTS.md was backed up to ${agentsSyncResult.backupPath} before replacement.`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
246
279
|
info(options.dryRun ? "Init check complete." : "Init complete.");
|
|
247
280
|
}
|
|
248
281
|
|
|
@@ -369,6 +402,7 @@ function upgradeProject(options) {
|
|
|
369
402
|
const paths = resolveProjectPaths(options.cwd);
|
|
370
403
|
const actions = [];
|
|
371
404
|
const warnings = [];
|
|
405
|
+
let agentsBackupPath = null;
|
|
372
406
|
|
|
373
407
|
ensureDir(paths.adrDir, options, actions);
|
|
374
408
|
ensureDir(paths.reqsDir, options, actions);
|
|
@@ -392,6 +426,7 @@ function upgradeProject(options) {
|
|
|
392
426
|
const backupPath = `${paths.agentsPath}.bak.${timestampForBackup()}`;
|
|
393
427
|
actions.push(`backup ${paths.agentsPath} -> ${backupPath}`);
|
|
394
428
|
actions.push(`overwrite ${paths.agentsPath}`);
|
|
429
|
+
agentsBackupPath = backupPath;
|
|
395
430
|
if (!options.dryRun) {
|
|
396
431
|
fs.copyFileSync(paths.agentsPath, backupPath);
|
|
397
432
|
fs.writeFileSync(paths.agentsPath, templateAgents, "utf8");
|
|
@@ -430,6 +465,14 @@ function upgradeProject(options) {
|
|
|
430
465
|
}
|
|
431
466
|
}
|
|
432
467
|
|
|
468
|
+
if (agentsBackupPath) {
|
|
469
|
+
if (options.dryRun) {
|
|
470
|
+
info(`Note: existing AGENTS.md would be backed up to ${agentsBackupPath} before replacement.`);
|
|
471
|
+
} else {
|
|
472
|
+
info(`Note: existing AGENTS.md was backed up to ${agentsBackupPath} before replacement.`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
433
476
|
info(options.dryRun ? "Upgrade check complete." : "Upgrade complete.");
|
|
434
477
|
return 0;
|
|
435
478
|
}
|