devlyn-cli 4.0.1 → 4.2.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 (72) hide show
  1. package/AGENTS.md +11 -95
  2. package/CLAUDE.md +7 -160
  3. package/LICENSE +21 -0
  4. package/README.md +83 -114
  5. package/bin/devlyn.js +330 -472
  6. package/bin/instruction-templates.json +120 -2
  7. package/bin/instructions.js +35 -8
  8. package/config/skills/_shared/adapters/claude.md +8 -85
  9. package/config/skills/_shared/adapters/codex.md +14 -34
  10. package/config/skills/_shared/adapters/omp.md +1 -11
  11. package/config/skills/_shared/codex-monitored.sh +4 -54
  12. package/config/skills/_shared/engine-doctor.sh +18 -58
  13. package/config/skills/_shared/engine-preflight.md +15 -47
  14. package/config/skills/_shared/expected-contract.py +242 -0
  15. package/config/skills/_shared/expected.schema.json +10 -95
  16. package/config/skills/_shared/invocation-receipt.py +26 -757
  17. package/config/skills/_shared/platform-support.py +37 -28
  18. package/config/skills/_shared/role-config.py +100 -421
  19. package/config/skills/_shared/runtime-principles.md +17 -93
  20. package/config/skills/_shared/task-complete.py +490 -285
  21. package/config/skills/_shared/task-completion.md +235 -0
  22. package/config/skills/devlyn-engines/SKILL.md +9 -11
  23. package/config/skills/devlyn-ideate/SKILL.md +57 -107
  24. package/config/skills/devlyn-ideate/references/elicitation.md +18 -99
  25. package/config/skills/devlyn-ideate/references/loop.md +110 -0
  26. package/config/skills/devlyn-ideate/references/package-format.md +128 -0
  27. package/config/skills/devlyn-ideate/scripts/acceptance.py +795 -0
  28. package/config/skills/devlyn-ideate/scripts/queue.py +1780 -0
  29. package/package.json +2 -3
  30. package/config/commit-conventions.md +0 -28
  31. package/config/skills/_shared/adapters/README.md +0 -74
  32. package/config/skills/_shared/adapters/grok.md +0 -100
  33. package/config/skills/_shared/archive_run.py +0 -969
  34. package/config/skills/_shared/codex-config.md +0 -81
  35. package/config/skills/_shared/collect-codex-findings.py +0 -505
  36. package/config/skills/_shared/finish-gate.py +0 -521
  37. package/config/skills/_shared/grok-anchor-guard.py +0 -78
  38. package/config/skills/_shared/judge-output-parser.py +0 -200
  39. package/config/skills/_shared/judge-role-evidence.py +0 -320
  40. package/config/skills/_shared/phase-prompt-render.py +0 -183
  41. package/config/skills/_shared/process-evidence.py +0 -926
  42. package/config/skills/_shared/resolve-bootstrap.py +0 -1410
  43. package/config/skills/_shared/resolve-stop-hook.py +0 -359
  44. package/config/skills/_shared/run-bounded.py +0 -58
  45. package/config/skills/_shared/spec-verify-check.py +0 -5083
  46. package/config/skills/_shared/state-phase-write.py +0 -5989
  47. package/config/skills/_shared/terminal-claim-check.py +0 -777
  48. package/config/skills/_shared/verify-merge-findings.py +0 -3528
  49. package/config/skills/devlyn-design-ui/SKILL.md +0 -650
  50. package/config/skills/devlyn-ideate/references/from-spec-mode.md +0 -61
  51. package/config/skills/devlyn-ideate/references/project-mode.md +0 -80
  52. package/config/skills/devlyn-ideate/references/spec-template.md +0 -121
  53. package/config/skills/devlyn-ideate/references/templates/decision.md +0 -48
  54. package/config/skills/devlyn-ideate/references/templates/roadmap.md +0 -50
  55. package/config/skills/devlyn-ideate/references/templates/vision.md +0 -44
  56. package/config/skills/devlyn-queue/SKILL.md +0 -66
  57. package/config/skills/devlyn-queue/scripts/append.py +0 -94
  58. package/config/skills/devlyn-resolve/SKILL.md +0 -379
  59. package/config/skills/devlyn-resolve/references/free-form-mode.md +0 -71
  60. package/config/skills/devlyn-resolve/references/outer-loop.md +0 -23
  61. package/config/skills/devlyn-resolve/references/phases/build-gate.md +0 -75
  62. package/config/skills/devlyn-resolve/references/phases/cleanup.md +0 -33
  63. package/config/skills/devlyn-resolve/references/phases/implement.md +0 -44
  64. package/config/skills/devlyn-resolve/references/phases/plan.md +0 -39
  65. package/config/skills/devlyn-resolve/references/phases/probe-derive.md +0 -261
  66. package/config/skills/devlyn-resolve/references/phases/surface-close.md +0 -34
  67. package/config/skills/devlyn-resolve/references/phases/verify.md +0 -310
  68. package/config/skills/devlyn-resolve/references/state-schema.md +0 -152
  69. package/config/skills/devlyn-resolve/references/task-completion.md +0 -160
  70. package/config/templates/prompt-templates.md +0 -71
  71. package/config/templates/template-feature.spec.md +0 -255
  72. package/config/templates/template-product-spec.md +0 -680
@@ -1,61 +0,0 @@
1
- # `--from-spec` mode
2
-
3
- Per-engine adapter prepended at runtime.
4
-
5
- <role>
6
- The user already wrote a spec (or has one from elsewhere — a teammate, a previous project, a copy-paste from a doc). Your job is to lint and normalize it to the canonical shape — without reshaping the user's substantive intent.
7
- </role>
8
-
9
- <input>
10
- - `<path>` — the external spec markdown file.
11
- - `_shared/expected.schema.json` — the schema for the sibling `spec.expected.json`.
12
- - `references/spec-template.md` — the canonical shape.
13
- </input>
14
-
15
- <allowed_changes>
16
- You may:
17
- 1. Add missing frontmatter fields (id from filename, kind=feature default, status=planned, complexity=medium default; set complexity=high only when preserved Requirements clearly combine state/order/failure/output-shape risks).
18
- 2. Rename non-canonical section headings to canonical (`## Goals` → `## Requirements`, `## Notes` ignored unless they clearly belong in Constraints).
19
- 3. Add a missing `## Out of Scope` section with `- (no explicit non-goals provided by author)`.
20
- 4. Add a missing `## Verification` section if Requirements imply observable runtime checks — best-effort one-command-per-Requirement, then surface to user for review.
21
- 5. Generate `spec.expected.json` from the `## Verification` block if the file is absent.
22
- 6. Fix structurally invalid `spec.expected.json` (malformed JSON, missing required keys per `_shared/expected.schema.json`).
23
- </allowed_changes>
24
-
25
- <forbidden_changes>
26
- You must NOT:
27
- - Reshape Requirements content. The user's substantive intent is preserved verbatim.
28
- - Add new Constraints the user did not write.
29
- - Move items between Requirements and Out of Scope.
30
- - "Improve" the prose in Context. Author voice stays.
31
- - Add `## Assumptions` or `## Open questions` sections — that is default-mode work, not normalization.
32
- </forbidden_changes>
33
-
34
- <flow>
35
- 1. Read `<path>`. Parse frontmatter. Identify present sections.
36
- 2. Lint structurally (same checks as default mode).
37
- 3. For each missing/malformed piece: apply the smallest allowed fix.
38
- 4. Write the normalized spec. Default location: `<spec-dir>/<id>-<slug>/spec.md`. With `--in-place` flag: write to `<path>` directly (overwrites the original).
39
- 5. Generate or fix `spec.expected.json` per the rules above. Same dir as the spec.
40
- 6. Run `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check <spec-path>` to validate the actual spec's carrier shape and supported `complexity` frontmatter. Sibling `spec.expected.json` takes precedence over the legacy inline `## Verification` JSON carrier. If exit 2, fix the file named in the error and re-run.
41
- 7. Run `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check-expected <expected-path>` to validate sibling `spec.expected.json` plus sibling spec `complexity` frontmatter.
42
- 8. If lint still fails after allowed fixes (e.g. Requirements section is empty in the source), surface the issue and exit non-zero — do NOT invent Requirements.
43
- 9. If the preserved Requirements combine state mutation with ordering/priority,
44
- idempotency, auth/error priority, or exact output shape but the Verification
45
- section lacks a compound end-to-end scenario, do not rewrite the author's
46
- content. Add a final warning that `/devlyn-resolve` may need default-mode
47
- ideation or a stronger Verification section before pair-relevant risks are
48
- measurable.
49
- </flow>
50
-
51
- <output>
52
- Same as default mode: `<spec-dir>/<id>-<slug>/spec.md` + `<spec-dir>/<id>-<slug>/spec.expected.json`.
53
-
54
- Final announcement: `spec normalized — /devlyn-resolve --spec <spec-path>`. If the spec was lint-passing with no changes needed, announce: `spec already canonical — /devlyn-resolve --spec <spec-path>`. If step 9 applies, append: `warning: Verification may need one compound end-to-end scenario before pair-relevant risks are measurable`.
55
-
56
- If lint failed unfixably: print the specific failure, exit non-zero. Do not write a partial output.
57
- </output>
58
-
59
- <rationale>
60
- `--from-spec` exists for power users with external context. Adding friction by forcing them through default-mode elicitation defeats the purpose. The mode trades elicitation depth for normalization speed; the user accepts that any author-side under-specification stays under-specified.
61
- </rationale>
@@ -1,80 +0,0 @@
1
- # `--project` mode
2
-
3
- Per-engine adapter prepended at runtime.
4
-
5
- <role>
6
- The user wants to build a project, not a single feature. Your job is to elicit the project description, decompose it into 3-7 independently-shippable features, and write `plan.md` (the index) plus one spec.md + spec.expected.json per feature.
7
- </role>
8
-
9
- <conversation_rules>
10
- 1. Project elicitation warrants more turns than single-spec mode. Hard ceiling: 12 turns instead of 8.
11
- 2. Ask the same question categories as default mode (input/output/failure/scope/constraints/verification) but at the project level first, then drill into each feature.
12
- 3. Decompose into 3-7 features. Fewer = the project is actually one big feature; recommend default mode. More = the project is too large; recommend splitting into separate ideate runs.
13
- 4. Each feature must be independently shippable: a feature whose verification depends on another feature's runtime behavior is a dependency, not a feature.
14
- 5. When a feature combines state mutation with ordering/priority, idempotency,
15
- auth/error priority, or exact output shape, its per-feature Verification must
16
- include one compound end-to-end scenario; do not hide the interaction in
17
- project-level prose.
18
- </conversation_rules>
19
-
20
- <decomposition_rules>
21
- - Features should be vertically sliced (full stack of one user-facing capability), not horizontally sliced (a layer that other features will need to consume).
22
- - A feature whose ONLY value is enabling other features (pure infrastructure) belongs in the first feature that needs it OR as an explicit "enabling spec" with the dependent feature waiting on it.
23
- - Feature dependencies are explicit in `frontmatter.depends_on`. The plan's suggested implementation order respects topological dependency.
24
- - Aim for features that take 1-3 hours of `/devlyn-resolve --spec` work each. Larger → split. Trivial → merge with neighbor.
25
- </decomposition_rules>
26
-
27
- <plan_md_shape>
28
- Output `<spec-dir>/plan.md`:
29
-
30
- ```markdown
31
- # <Project name>
32
-
33
- ## Goal
34
-
35
- 2-4 sentences from the elicitation — what the project delivers and why.
36
-
37
- ## Decomposition rationale
38
-
39
- 1-2 paragraphs explaining how the project was sliced into features. Includes the order rationale.
40
-
41
- ## Feature specs
42
-
43
- | ID | Title | Depends on | Status |
44
- |----|-------|-----------|--------|
45
- | <id-1> | ... | (none) | planned |
46
- | <id-2> | ... | <id-1> | planned |
47
- | ... | ... | ... | ... |
48
-
49
- ## Suggested implementation order
50
-
51
- 1. `/devlyn-resolve --spec <spec-dir>/<id-1>/spec.md`
52
- 2. `/devlyn-resolve --spec <spec-dir>/<id-2>/spec.md`
53
- 3. ...
54
-
55
- The order respects `depends_on`. Topologically equivalent specs can be parallelized later (Mission 2 work); single-task L1 ships them sequentially.
56
-
57
- ## Project-level constraints
58
-
59
- Anything binding all features (e.g. "no new top-level dependencies", "all CLI output must support `NO_COLOR`"). Each feature spec inherits these in its Constraints section.
60
- ```
61
-
62
- `plan.md` is the **index**, not a hidden dependency. `/devlyn-resolve` reads only the spec it is invoked with; it does not parse `plan.md`.
63
- </plan_md_shape>
64
-
65
- <output>
66
- - `<spec-dir>/plan.md` (the index above).
67
- - `<spec-dir>/<id-N>/spec.md` for each feature (per `references/spec-template.md`).
68
- - `<spec-dir>/<id-N>/spec.expected.json` for each feature (per `_shared/expected.schema.json`).
69
-
70
- Each per-feature spec is structurally lint-validated using `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check <spec-path>`, including supported `complexity` frontmatter, and each sibling expected contract plus sibling spec `complexity` frontmatter is validated using `python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check-expected <expected-path>`.
71
-
72
- Final announcement: `project ready — N specs at <spec-dir>/. Start with /devlyn-resolve --spec <first-spec-path>`.
73
- </output>
74
-
75
- <anti_patterns>
76
- - Decomposing into more features than the project needs (10+ features for a CLI). Project mode is for genuine multi-feature work.
77
- - Hidden coupling between features (feature B's spec assumes feature A's internal data structure). Surface as `depends_on` or fold into one spec.
78
- - Vision documents, roadmaps as separate tiers, market-positioning paragraphs. The locked design is index + specs. Anything else is context pollution.
79
- - Continuing past 12 turns of elicitation. If the project is still not clear at turn 12, recommend the user split it into 2-3 separate ideate runs.
80
- </anti_patterns>
@@ -1,121 +0,0 @@
1
- # Canonical spec template
2
-
3
- The shape `/devlyn-ideate` writes and `/devlyn-resolve --spec` consumes. Single source of truth for spec structure.
4
-
5
- ## Frontmatter
6
-
7
- ```yaml
8
- ---
9
- id: "<spec-id>" # kebab-case, unique per spec-dir; auto-generated if user omits
10
- title: "<short title>" # one line, descriptive
11
- kind: feature # feature | spike | prototype
12
- status: planned # planned → in_progress → done. ideate writes "planned"; resolve's CLEANUP flips to "done".
13
- complexity: medium # trivial | medium | high. Use high when Verification needs compound state/order/failure checks.
14
- depends_on: [] # list of spec ids this depends on (empty for standalone). project mode populates this.
15
- ---
16
- ```
17
-
18
- ## `# <title>`
19
-
20
- Top-level heading repeats the title.
21
-
22
- ## `## Context`
23
-
24
- 2-4 sentences answering "why does this exist." User-facing motivation, not implementation detail. Traceable to whatever the user said during elicitation.
25
-
26
- ## `## Requirements`
27
-
28
- Checklist of testable, scoped statements. Each bullet is one observable behavior:
29
-
30
- ```markdown
31
- - [ ] `node bin/cli.js doctor` exits 0 on a clean machine.
32
- - [ ] `--verbose` lists installed plugins by name.
33
- - [ ] Exit code is `1` when any FAIL line appears.
34
- ```
35
-
36
- Rules:
37
- - Each Requirement is independently verifiable (a command, a test, a file existence check).
38
- - Avoid implementation language ("use a try/catch") in Requirements; that goes in Constraints.
39
- - Pure-design Requirements are allowed (e.g. "follow the existing pattern in `lib/X.js`") but mark them "design-only" so Verification can be omitted for that bullet.
40
-
41
- ## `## Constraints`
42
-
43
- Concrete rules with reasoning. Examples:
44
-
45
- ```markdown
46
- - **Zero new npm dependencies.** Use only Node.js built-ins.
47
- - **No silent error catches.** Errors must be visible to the user with actionable messages.
48
- - **Touch only `bin/cli.js` and `tests/cli.test.js`.** Other files are out of scope.
49
- ```
50
-
51
- Each constraint has a one-line "why" — bare constraints invite negotiation; reasoned constraints lock the contract.
52
-
53
- ## `## Out of Scope`
54
-
55
- Explicit "must NOT build" list. Examples:
56
-
57
- ```markdown
58
- - Auto-repair (report only).
59
- - Checking remote/registry state.
60
- - Refactoring the argument parser.
61
- ```
62
-
63
- If the spec is small enough that nothing meaningful is out of scope, write `- (nothing notable; see Constraints for boundary)`.
64
-
65
- ## `## Verification`
66
-
67
- Immediately precede the heading with a `<!-- devlyn:verification -->` sentinel
68
- comment on its own line, directly above `## Verification` (no blank line
69
- between them). This is the machine locator `spec-verify-check.py` uses to
70
- find the section — it is language-neutral: the heading text after the
71
- sentinel may be any human language (`## Verification`, `## 검증`, etc.); only
72
- the sentinel itself is fixed ASCII and must never be translated.
73
-
74
- Concrete commands or tests whose expected behavior names the success condition:
75
-
76
- ```markdown
77
- <!-- devlyn:verification -->
78
- ## Verification
79
-
80
- - `node bin/cli.js doctor` exits 0; output contains `doctor:`.
81
- - `HOME=/nonexistent node bin/cli.js doctor` exits 1; output mentions `/nonexistent`.
82
- - `node --test tests/cli.test.js` passes.
83
- - `git diff -- package.json` is empty.
84
- ```
85
-
86
- The body of the section reads humanely; the machine-readable contract lives in `spec.expected.json` (sibling file). Each command in this section maps to one entry in `spec.expected.json.verification_commands`.
87
-
88
- If all Requirements are pure-design (no observable runtime check), the body of this section is a single descriptive line (e.g. `- No runtime verification commands.`) and sibling `spec.expected.json` declares `"pure_design": true` instead of listing `verification_commands`.
89
-
90
- ## Sibling file: `spec.expected.json`
91
-
92
- Schema: `_shared/expected.schema.json`. Required when Requirements have observable checks; optional when all Requirements are pure-design (declare `"pure_design": true` in that case — contradictory, and rejected, alongside a non-empty `verification_commands`). Validate before announcing ready:
93
-
94
- ```bash
95
- python3 "$DEVLYN_SHARED_DIR/spec-verify-check.py" --check-expected <expected-path>
96
- ```
97
-
98
- Map mechanically decidable rules from both Requirements and Constraints into the existing carriers. Preserve specific file constraints even when narrower than PLAN's scope. During BUILD_GATE, with `state.base_ref.sha` recorded, the existing `authorized_surface` check enforces PLAN's scope over the run diff and newly created untracked paths (`.devlyn/` exempt). Do not duplicate this general scope check with a whole-checkout scan in `verification_commands`. Validate each new guard with a violating control that fails and an allowed control that passes, preserving permitted pre-existing occurrences:
99
- - `verification_commands` ← `## Verification` + commands the conversation surfaced. While drafting both Verification and its carrier, omit a standalone check only when another command in that contract runs the same assertions under the required execution conditions and propagates failure; describe that shared coverage in Verification and keep both carriers aligned. Preserve distinct scenarios and required independent verification; execute approved commands unchanged without reusing results across phases. For semantic annotation or exception-handling rules, use a suitable syntax-aware/executable check, preferring existing checks; explicitly retain uncovered semantics as source-review obligations.
100
- - `forbidden_patterns` ← literal syntax constraints only; regex does not prove semantics. It scans the whole file-filtered diff, including context, deletions and headers; additions-only guards must exclude those lines.
101
- - `required_files` / `forbidden_files` ← literal file paths from Requirements, Constraints and Out of Scope; `forbidden_files` matches exact Git-relative paths (forward slashes, no leading `./`), including both names of a rename. Globs and directory-wide exclusions need a suitable `verification_commands` guard, not wildcard-looking entries in these lists.
102
- - `max_deps_added` ← dependency limits in Requirements or Constraints (default 0 unless the spec licenses a new dep).
103
- - `required_risk_probe_requirements` ← for specs where a Requirement combines ordering/priority, rollback, idempotency, auth/signature, concurrency, atomic-batch, or exact output shape, declare the risk categories PHASE 1.5 risk-probe derivation must cover directly, e.g. `[{"tag": "rollback_state", "derived_from": "<exact ## Verification bullet>"}]`. This replaces guessing the required categories from prose — declare them explicitly so the check works in any language. `tag` must be one of the risk-probe tags in `_shared/spec-verify-check.py:RISK_PROBE_TAGS`; `derived_from` must be an exact substring of `## Verification`. Omit entirely when the spec has no ordering/rollback/idempotency/auth/concurrency/atomic-batch/exact-shape risk.
104
-
105
- ## Quality bar (lint enforces structurally; ideate enforces substantively)
106
-
107
- Structural (lint):
108
- - Frontmatter valid + required fields present.
109
- - All five H2 sections present.
110
- - Requirements has ≥ 1 bullet.
111
- - Verification has either commands or `spec.expected.json` declares `"pure_design": true`.
112
-
113
- Substantive (ideate's job during elicitation):
114
- - Each Requirement is independently verifiable.
115
- - Each Constraint has a reasoning clause.
116
- - Out of Scope explicitly enumerates non-goals.
117
- - Verification commands actually verify the Requirement they map to (no "looks plausible" verification).
118
- - Avoid formatter-sensitive single-line adjacency checks — prefer a semantic test (runtime, DB, or CLI check), or grep one stable line-local anchor and assert required context separately.
119
- - Frontmatter `complexity` reflects verification shape: `high` when the spec combines state mutation with ordering/priority, idempotency, auth/error priority, rollback/failure handling, or exact output shape; `medium` for ordinary multi-step work; `trivial` only for a single localized behavior.
120
- - When Requirements combine state mutation, ordering/priority, idempotency, auth/error priority, or exact output shape, Verification includes at least one compound scenario that exercises the interaction end-to-end; isolated happy paths are insufficient.
121
- - Spec text is plain language — no jargon walls, no "for future flexibility" hedging.
@@ -1,48 +0,0 @@
1
- # Decision Record Template
2
-
3
- Generate decision records at `docs/roadmap/decisions/{NNN}-{title}.md`. These capture WHY a decision was made, preventing future agents and collaborators from re-debating settled questions.
4
-
5
- ---
6
-
7
- ```markdown
8
- ---
9
- id: [NNN]
10
- title: "[Decision Title]"
11
- date: [YYYY-MM-DD]
12
- status: accepted
13
- ---
14
-
15
- # [NNN] [Decision Title]
16
-
17
- ## Context
18
- <!-- What situation or question prompted this decision? -->
19
-
20
- ## Decision
21
- <!-- What was decided. Be specific and concrete. -->
22
-
23
- ## Alternatives Considered
24
-
25
- ### [Alternative 1]
26
- - Pros: [advantages]
27
- - Cons: [disadvantages]
28
- - Why rejected: [the deciding factor]
29
-
30
- ### [Alternative 2]
31
- - Pros: [advantages]
32
- - Cons: [disadvantages]
33
- - Why rejected: [the deciding factor]
34
-
35
- ## Consequences
36
- <!-- What changes as a result. Include both positive tradeoffs and costs accepted. -->
37
- - [Positive consequence]
38
- - [Cost or constraint accepted]
39
- ```
40
-
41
- ## Guidelines
42
-
43
- - Status values: `proposed` | `accepted` | `superseded`
44
- - Number decisions sequentially: 001, 002, 003...
45
- - Focus on the "why rejected" for alternatives — this is what prevents re-debating
46
- - Keep decisions atomic: one decision per record
47
- - If a decision is later reversed, mark the original as `superseded` and create a new record referencing it
48
- - Only create decision records for choices that affect multiple roadmap items or have non-obvious reasoning. Don't document every small implementation choice.
@@ -1,50 +0,0 @@
1
- # ROADMAP.md Template
2
-
3
- Generate `docs/ROADMAP.md` using this structure. This is an **index** — brief descriptions and links to detail specs. No inline specifications.
4
-
5
- ---
6
-
7
- ```markdown
8
- # [Project Name] Roadmap
9
-
10
- > **North Star**: [One sentence from VISION.md]
11
-
12
- ## Phase 1: [Theme Name] (Target: [date or timeframe])
13
- <!-- 1-2 sentences: what this phase delivers and why it comes first -->
14
-
15
- | # | Feature | Status | Priority | Complexity | Spec |
16
- |---|---------|--------|----------|-----------|------|
17
- | 1.1 | [Feature Name] | Planned | High | Medium | [spec](roadmap/phase-1/1.1-feature-name.md) |
18
- | 1.2 | [Feature Name] | Planned | High | High | [spec](roadmap/phase-1/1.2-feature-name.md) |
19
- | 1.3 | [Feature Name] | Planned | Medium | Low | [spec](roadmap/phase-1/1.3-feature-name.md) |
20
-
21
- ## Phase 2: [Theme Name] (Target: [date or timeframe])
22
- <!-- 1-2 sentences -->
23
-
24
- | # | Feature | Status | Priority | Complexity | Spec |
25
- |---|---------|--------|----------|-----------|------|
26
- | 2.1 | [Feature Name] | Planned | High | Medium | [spec](roadmap/phase-2/2.1-feature-name.md) |
27
-
28
- ## Backlog
29
- <!-- Ideas acknowledged but not yet phased -->
30
- | Feature | Reason Deferred | Revisit |
31
- |---------|----------------|---------|
32
- | [Name] | [Why not now] | [When to reconsider] |
33
-
34
- ## Decisions
35
- | # | Decision | Date | Record |
36
- |---|----------|------|--------|
37
- | 1 | [Decision Title] | [YYYY-MM-DD] | [record](roadmap/decisions/001-decision-title.md) |
38
- ```
39
-
40
- ## Guidelines
41
-
42
- - Status values: `Planned` | `In Progress` | `Done` | `Blocked`
43
- - Priority: `High` | `Medium` | `Low`
44
- - Complexity: `Low` | `Medium` | `High`
45
- - Feature names should be user-facing descriptions, not technical jargon
46
- - Each phase should deliver usable value — no "infrastructure only" phases
47
- - The spec column links to the detail spec in `roadmap/phase-N/`
48
- - Numbering: `{phase}.{item}` (e.g., 1.1, 1.2, 2.1)
49
- - Slug format for filenames: `{id}-{kebab-case-name}.md` (e.g., `1.1-user-auth.md`)
50
- - Keep this file under 150 lines — it's an index, not a specification
@@ -1,44 +0,0 @@
1
- # VISION.md Template
2
-
3
- Generate `docs/VISION.md` using this structure. Keep it under 100 lines — this is a strategic orientation document, not a detailed specification.
4
-
5
- ---
6
-
7
- ```markdown
8
- # [Project Name] Vision
9
-
10
- ## North Star
11
- <!-- One sentence. Every decision should move toward this. -->
12
-
13
- ## Principles
14
- <!-- 3-5 guiding principles. Each includes what it means AND the tradeoff it implies. -->
15
- 1. **[Principle Name]** — [What this means in practice]. Tradeoff: [what we accept giving up].
16
- 2. ...
17
-
18
- ## Target Users
19
- ### Primary
20
- <!-- Be specific: role, context, pain, what they need -->
21
- **[Who]** — [Their situation]. Pain: [what frustrates them]. Need: [what they want].
22
-
23
- ### Not For
24
- <!-- Explicitly state who this isn't for, so the team doesn't try to serve everyone -->
25
- - [Audience] — Why: [reason this isn't our focus]
26
-
27
- ## Anti-Goals
28
- <!-- Things we deliberately choose NOT to do, even if they seem like good ideas -->
29
- - **[Anti-goal]** — Why: [the reasoning behind this constraint]
30
- - ...
31
-
32
- ## Success Metrics
33
- <!-- How we know this is working. Outcomes, not outputs. -->
34
- - [Metric]: [target] (e.g., "Time to first value: under 5 minutes")
35
- - ...
36
- ```
37
-
38
- ## Guidelines
39
-
40
- - North Star should be ambitious but specific — "make X better" is too vague
41
- - Principles without tradeoffs are platitudes — if a principle has no cost, it's not a real principle
42
- - Anti-goals prevent scope creep downstream — be generous with these
43
- - Success metrics should be measurable, even if the measurement is qualitative
44
- - Write in the user's primary language, technical terms in English
@@ -1,66 +0,0 @@
1
- ---
2
- name: devlyn-queue
3
- description: Manage and drain the intent queue (docs/specs/queue.md) — the backlog the loop-engineering contract runs on. Use when the user wants to stack work for later ("큐에 넣어줘", "queue this"), see what is queued, or start an unattended serial drain ("큐 드레인 시작", "밤새 돌려줘", "drain the queue") that takes each item through spec → /devlyn-resolve → verified done.
4
- ---
5
-
6
- Utility front-end for the intent-queue contract in the project instructions ("Intent queue" in CLAUDE.md / AGENTS.md — whichever this CLI loads). It adds no semantics of its own: the queue file is the API, and the drain loop follows the documented contract exactly — a runner (this skill, a long session, or a future devlyn-os daemon) is a replaceable driver over the same file.
7
-
8
- <args>
9
- $ARGUMENTS
10
- </args>
11
-
12
- Before `add` or `drain`, establish the bindings below.
13
-
14
- Resolve bundled resources from the SKILL.md loaded for this invocation.
15
-
16
- Reader-rendered directory hint:
17
- ```text
18
- ${CLAUDE_SKILL_DIR}
19
- ```
20
-
21
- Treat the hint as literal path data, never shell code. If the reader
22
- replaced it with an absolute directory, use that directory. Otherwise
23
- use the filesystem path or base directory reported for this loaded
24
- SKILL.md. Resolve virtual URIs through the reader's native filesystem
25
- mapping. If available source locations name different directories,
26
- stop.
27
-
28
- Bind DEVLYN_SKILL_DIR to that absolute directory. Do not obtain this
29
- binding from an environment variable, cwd, or another installation.
30
- Verify its SKILL.md before proceeding. Missing or conflicting source
31
- identity is BLOCKED:skill-source-unresolved; include the failed path
32
- when known.
33
-
34
- Resolve bundled references against this directory. These bindings are
35
- workflow values: establish them explicitly using each tool or shell's
36
- literal-path rules, and include their absolute values in every fresh
37
- worker's prompt, telling it to set them from those values, never from
38
- its inherited environment. Do not rely on shell state surviving between
39
- calls.
40
-
41
- Resolve directory symlinks on DEVLYN_SKILL_DIR before deriving its
42
- sibling _shared. Bind that directory as DEVLYN_SHARED_DIR. References
43
- written as _shared/... use this binding. Verify the directory and each
44
- required resource before use; failure is BLOCKED:shared-dir-unresolved
45
- with the failed path. Never search another installation.
46
-
47
- For `add`, verify DEVLYN_SKILL_DIR/scripts/append.py before invoking it. For `drain`, before processing the first item, read and obey ../devlyn-resolve/references/outer-loop.md (its scoped-commit order is binding) and read ../devlyn-resolve/references/task-completion.md, both relative to this bound skill directory. Load the sibling devlyn-resolve/SKILL.md by its absolute path and preserve this bundle's DEVLYN_SHARED_DIR when handing off; do not rediscover resolve by its bare command name. In omp, use `printf '%s\n' skill://devlyn-queue`.
48
-
49
- Queue state is base's `docs/specs/queue.md` plus owned receipts: for each `$(git rev-parse --git-common-dir)/devlyn-completion/*/receipt.json`, read `git show <ref>:docs/specs/queue.md` from its `recovery_ref` if that ref exists (it is never deleted), else its `branch` if it still exists; an item unmarked on base but `[x]`/`[F]` there counts as that mark. Two different terminal marks for one item stop for inspection. Status and drain selection both use this view.
50
-
51
- ## No args — status
52
-
53
- Read the queue state above (absent `docs/specs/queue.md` → report "queue empty — nothing staged" and how to add). Print pending `[ ]`, done `[x]`, and blocked `[F]` counts, the next item up, and one usage line per subcommand.
54
-
55
- ## Subcommands
56
-
57
- - `add <intent text>` — use the Write tool to place the exact full intent in a new file `.devlyn/queue-intent-<unique>.txt` (a name no other add uses, made of letters, digits, `.`, `_` and `-`, e.g. `queue-intent-20261001-1230-k3x9.txt`); do not create it with shell syntax. If the conversation already produced a spec, the file must start with `(spec: docs/specs/<id>/spec.md)`. Then, from the project root, run exactly once `python3 "$DEVLYN_SKILL_DIR/scripts/append.py" .devlyn/queue-intent-<unique>.txt`. The helper consumes that file, appends one `- [ ] <intent>` line at the physical end of `docs/specs/queue.md` under a lock (creating it with its header if missing), and is the sole queue writer. Never edit `docs/specs/queue.md` directly for `add` and never use a direct-edit fallback; a nonzero helper exit is shown to the user and stops the `add`.
58
- - `drain` — serial drain per the project-instructions contract. For each pending item, in order:
59
- 1. Allocate the owner's absent task branch with `--worktree <absent path>` per `../devlyn-resolve/references/task-completion.md`, and work in that worktree; then spec it if unspecced (the queue entry is the user's go-ahead). Unattended assumptions may only take scope-narrowing, reversible, non-user-visible defaults; material ambiguity (user-visible behavior, data/state semantics, new files/scripts/flags, implementation surface) → mark `[F] needs-review: <question>`, commit that queue transition, and continue.
60
- 2. Bring only the current queue-item delta and linked spec bundle from the queue view into the task worktree, which starts from the fetched remote base with no other local commits, commit that scoped owner baseline, then run the sibling devlyn-resolve loaded above with `--spec <path>` hands-free.
61
- After every resolve invocation, run `python3 "$DEVLYN_SHARED_DIR/terminal-claim-check.py" .`; exit 79 marks `[F] FAILED-INCOMPLETE` from the predicate, never from the session self-report.
62
- 3. Outer loop on the terminal verdict: PASS → mark `[x]`. Findings-backed verdicts (NEEDS_WORK, BLOCKED:repair-budget-exhausted) → amend the spec, commit that scoped amendment, then re-run — at most 3 outer iterations. Infrastructure / invalid-input / engine-availability / implement-empty BLOCKED verdicts are not spec-amendable → mark `[F] <verdict>` immediately.
63
- 4. Commit each terminal `[x]` / `[F]` queue transition before advancing. For successfully archived normal runs, invoke owner completion once after that declared queue-file-only commit; bind it separately from the verified source. Honor local-only/no-push. Failed products never publish. Retain PR/pending workspaces and use a separate owned branch from base for the next item; unavailable safe placement stops the drain with remaining items pending. A product-blocked item otherwise never halts the queue.
64
- 5. When the queue is drained (or the session must stop), emit the drain report: per-item product verdict and separate delivery status/URL/resume, every logged assumption, and the commit range produced.
65
-
66
- Strictly SERIAL — one `/devlyn-resolve` run at a time, never parallel. Never invent queue items, never reorder them, and never delete an item — only mark `[x]` / `[F]`.
@@ -1,94 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Append one normalized pending intent to the project queue."""
3
-
4
- import argparse
5
- import os
6
- import re
7
- import sys
8
- from contextlib import contextmanager
9
- from pathlib import Path
10
-
11
-
12
- QUEUE_PATH = Path("docs/specs/queue.md")
13
- LOCK_PATH = Path(".devlyn/queue.lock")
14
- # Each `add` writes its own handoff file, so two adds never consume each other's intent.
15
- HANDOFF = re.compile(r"\.devlyn/queue-intent-[A-Za-z0-9._-]+\.txt")
16
- MINIMAL_HEADER = b"# Intent Queue\n\n"
17
-
18
-
19
- @contextmanager
20
- def queue_lock():
21
- """One writer at a time across processes, from creating the queue to the append."""
22
- LOCK_PATH.parent.mkdir(parents=True, exist_ok=True)
23
- fd = os.open(LOCK_PATH, os.O_RDWR | os.O_CREAT, 0o644)
24
- try:
25
- if os.name == "nt":
26
- import msvcrt
27
-
28
- # The CRT locks bytes that exist; give a new lock file its one byte.
29
- if os.fstat(fd).st_size == 0:
30
- os.write(fd, b"\0")
31
- os.lseek(fd, 0, os.SEEK_SET)
32
- msvcrt.locking(fd, msvcrt.LK_LOCK, 1)
33
- try:
34
- yield
35
- finally:
36
- os.lseek(fd, 0, os.SEEK_SET)
37
- msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
38
- else:
39
- import fcntl
40
-
41
- fcntl.flock(fd, fcntl.LOCK_EX)
42
- yield
43
- finally:
44
- os.close(fd)
45
-
46
-
47
- def append_intent(queue_path, intent):
48
- normalized = " ".join(intent.split())
49
- if not normalized:
50
- raise ValueError("intent must contain non-whitespace text")
51
- item = f"- [ ] {normalized}\n".encode("utf-8")
52
-
53
- with queue_lock():
54
- if not queue_path.exists():
55
- queue_path.parent.mkdir(parents=True, exist_ok=True)
56
- queue_path.write_bytes(MINIMAL_HEADER + item)
57
- return
58
-
59
- with queue_path.open("rb") as queue:
60
- queue.seek(0, 2)
61
- size = queue.tell()
62
- if size:
63
- queue.seek(-1, 2)
64
- ends_with_newline = queue.read(1) == b"\n"
65
- else:
66
- ends_with_newline = True
67
-
68
- prefix = b"" if ends_with_newline else b"\n"
69
- with queue_path.open("ab") as queue:
70
- queue.write(prefix + item)
71
-
72
-
73
- def main(argv=None):
74
- parser = argparse.ArgumentParser(
75
- description="Append one pending intent at the physical end of docs/specs/queue.md."
76
- )
77
- parser.add_argument("handoff", type=Path, help=".devlyn/queue-intent-<unique>.txt, relative to the project root")
78
- args = parser.parse_args(argv)
79
- if not HANDOFF.fullmatch(args.handoff.as_posix()):
80
- parser.error(f"handoff must be .devlyn/queue-intent-<unique>.txt: {args.handoff}")
81
- try:
82
- try:
83
- intent = args.handoff.read_text(encoding="utf-8")
84
- finally:
85
- args.handoff.unlink(missing_ok=True)
86
- append_intent(QUEUE_PATH, intent)
87
- except (OSError, UnicodeError, ValueError) as error:
88
- print(f"queue add failed: {error}", file=sys.stderr)
89
- return 1
90
- return 0
91
-
92
-
93
- if __name__ == "__main__":
94
- raise SystemExit(main())