@bluenyang/reins 0.0.0-stage → 0.1.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -2
  3. package/cli/dist/commands/check.js +244 -0
  4. package/cli/dist/commands/install.js +230 -0
  5. package/cli/dist/commands/migrate.js +122 -0
  6. package/cli/dist/lib/ask.js +27 -0
  7. package/cli/dist/lib/blocks.js +93 -0
  8. package/cli/dist/lib/detect.js +105 -0
  9. package/cli/dist/lib/fsx.js +36 -0
  10. package/cli/dist/lib/git.js +30 -0
  11. package/cli/dist/lib/glob.js +30 -0
  12. package/cli/dist/lib/harness.js +33 -0
  13. package/cli/dist/lib/migrate-plan.js +233 -0
  14. package/cli/dist/lib/schema.js +70 -0
  15. package/cli/dist/lib/secrets.js +28 -0
  16. package/cli/dist/lib/skills.js +63 -0
  17. package/cli/dist/lib/upstream.js +16 -0
  18. package/cli/dist/lib/verdict.js +15 -0
  19. package/cli/dist/reins.js +122 -0
  20. package/docs/README.ko.md +151 -0
  21. package/harness/CHANGELOG.md +10 -0
  22. package/harness/VERSION +1 -0
  23. package/harness/knowledge-seeds/node/2026-10-25_frozen-lockfile.md +24 -0
  24. package/harness/knowledge-seeds/node/2026-10-25_mutating-lint-is-not-a-gate.md +19 -0
  25. package/harness/policy/budget.yaml +13 -0
  26. package/harness/policy/common-red-lines.yaml +25 -0
  27. package/harness/policy/stops.yaml +29 -0
  28. package/harness/policy/transitions.yaml +13 -0
  29. package/harness/roles/advisor.md +15 -0
  30. package/harness/roles/code-review.md +21 -0
  31. package/harness/roles/deploy.md +17 -0
  32. package/harness/roles/docs.md +16 -0
  33. package/harness/roles/implementer.md +22 -0
  34. package/harness/roles/lookup.md +19 -0
  35. package/harness/roles/pl.md +21 -0
  36. package/harness/roles/planner.md +20 -0
  37. package/harness/roles/pm.md +23 -0
  38. package/harness/roles/qa-design.md +19 -0
  39. package/harness/roles/qa-run.md +16 -0
  40. package/harness/roles/verify-tool.md +19 -0
  41. package/harness/schemas/bus-request.schema.json +17 -0
  42. package/harness/schemas/bus-response.schema.json +14 -0
  43. package/harness/schemas/intent.schema.json +13 -0
  44. package/harness/schemas/knowledge.schema.json +16 -0
  45. package/harness/schemas/plan.schema.json +10 -0
  46. package/harness/schemas/spec.schema.json +8 -0
  47. package/harness/schemas/ticket.schema.json +15 -0
  48. package/harness/templates/agents-md-blocks.md +26 -0
  49. package/harness/templates/bus/request.yaml +14 -0
  50. package/harness/templates/bus/response.yaml +9 -0
  51. package/harness/templates/intent.md +23 -0
  52. package/harness/templates/knowledge.md +20 -0
  53. package/harness/templates/plan.md +23 -0
  54. package/harness/templates/spec.md +17 -0
  55. package/harness/templates/ticket.md +29 -0
  56. package/package.json +43 -4
  57. package/skills/reins-intent/SKILL.md +35 -0
  58. package/skills/reins-loop/SKILL.md +46 -0
  59. package/skills/reins-setup/SKILL.md +27 -0
@@ -0,0 +1,8 @@
1
+ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "reins/spec@1", "type": "object",
2
+ "required": ["intent", "status", "approvals"],
3
+ "properties": {
4
+ "intent": { "type": "string", "pattern": "^[0-9]{3}$" },
5
+ "status": { "enum": ["draft", "reviewed", "accepted", "rejected"] },
6
+ "approvals": { "$ref": "intent@1#/$defs/approvals" },
7
+ "summary_for_user": { "type": "string", "maxLength": 600 }
8
+ } }
@@ -0,0 +1,15 @@
1
+ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "reins/ticket@1", "type": "object",
2
+ "required": ["id", "intent", "plan_step", "title", "status", "release", "role"],
3
+ "properties": {
4
+ "id": { "type": "string", "pattern": "^[0-9]{3}-[0-9]+$" },
5
+ "intent": { "type": "string", "pattern": "^[0-9]{3}$" },
6
+ "plan_step": { "type": "integer", "minimum": 1 },
7
+ "title": { "type": "string", "minLength": 1 },
8
+ "status": { "enum": ["todo", "doing", "blocked", "done"] },
9
+ "depends": { "type": "array", "items": { "type": "string" } },
10
+ "release": { "enum": ["planned", "stabilization"] },
11
+ "role": { "type": "string" },
12
+ "budget": { "type": "object", "properties": { "tokens": { "type": "integer", "minimum": 0 } } },
13
+ "asks": { "type": "array", "items": { "type": "string" } },
14
+ "branch": { "type": "string" }
15
+ } }
@@ -0,0 +1,26 @@
1
+ <!-- reins:begin notice v=0.1.0 -->
2
+ > The blocks marked `reins:begin … reins:end` in this file are generated by reins from `.agents/harness/`. Do not edit them by hand; run `reins update`. Everything outside the blocks belongs to the project.
3
+ <!-- reins:end notice -->
4
+
5
+ <!-- reins:begin workflow v=0.1.0 -->
6
+ ## Workflow
7
+
8
+ - Session start: `AGENTS.md` → `docs/ROADMAP.md` → open intents in `.agents/intent/` → `reins status`.
9
+ - Work comes from `.loctx/ticket/`; one file is one item; delete it when done after writing a line in `.loctx/history/`.
10
+ - **Committing is part of doing the work.** Land each finished unit — one coherent change that builds on its own — as its own local commit as you go, on the feature branch. Do not batch a whole ticket into one commit, and do not wait for permission to commit locally. Never commit on the default branch; never bypass hooks.
11
+ - Before a non-trivial decision: `reins recall <keyword>` (knowledge, history, symptoms).
12
+ - The verifier runs at every transition (`reins check`). Verdicts: CONTINUE · HOLD (ask the user) · STOP (recorded, resumable) · ESCALATE. A stop names its reason id (A1–G2).
13
+ - Anything that leaves the machine happens only in the deploy role inside the pre-release loop, or on the user's explicit instruction.
14
+ <!-- reins:end workflow -->
15
+
16
+ <!-- reins:begin skills v=0.1.0 -->
17
+ ## Skills
18
+
19
+ See `.agents/SKILLS.md`. Skills that push, merge or release are user-invoked only.
20
+ <!-- reins:end skills -->
21
+
22
+ <!-- reins:begin language v=0.1.0 -->
23
+ ## Language
24
+
25
+ `AGENTS.md`, code, commits, `.agents/` sources: English. Documents the user reads (`intent/`, `.loctx/`, `docs/*.ko.md`): the project's user language.
26
+ <!-- reins:end language -->
@@ -0,0 +1,14 @@
1
+ schema: reins/bus/request@1
2
+ id: 000-1_01
3
+ from: pl
4
+ to: implementer
5
+ ticket: 000-1
6
+ intent: "000"
7
+ kind: implement
8
+ changes: []
9
+ why: ""
10
+ tried: []
11
+ not_tried: []
12
+ deadline: null
13
+ revert: ""
14
+ errors: ""
@@ -0,0 +1,9 @@
1
+ schema: reins/bus/response@1
2
+ request: 000-1_01
3
+ from: implementer
4
+ verdict: pass
5
+ grounds: ""
6
+ fixes: []
7
+ may_proceed: true
8
+ major_issues: []
9
+ evidence: ""
@@ -0,0 +1,23 @@
1
+ ---
2
+ id: "000"
3
+ slug: example
4
+ version: 0.0.0
5
+ status: draft
6
+ origin: user
7
+ approvals: []
8
+ supersedes: null
9
+ ---
10
+ ## 문제
11
+ —
12
+ ## 바라는 결과
13
+ —
14
+ ## 영향 범위
15
+ —
16
+ ## 제약
17
+ —
18
+ ## 열린 질문
19
+ —
20
+ ## 질의서 기록
21
+ —
22
+ ## 하지 않을 것
23
+ —
@@ -0,0 +1,20 @@
1
+ ---
2
+ id: YYYY-MM-DD_slug
3
+ kind: decision
4
+ status: active
5
+ supersedes: null
6
+ topics: []
7
+ decisions: []
8
+ symptoms: []
9
+ applies_to: all
10
+ source: —
11
+ approved: { by: user, at: YYYY-MM-DD }
12
+ ---
13
+ ## 결정
14
+ —
15
+ ## 이유
16
+ —
17
+ ## 적용
18
+ —
19
+ ## 바뀌면
20
+ —
@@ -0,0 +1,23 @@
1
+ ---
2
+ intent: "000"
3
+ status: draft
4
+ approvals: []
5
+ agents:
6
+ implement: [implementer]
7
+ verify: [verify-tool]
8
+ review: [code-review]
9
+ budget: {}
10
+ tickets: []
11
+ ---
12
+ ## 바뀌는 파일
13
+ —
14
+ ## 작업 순서
15
+ 1. — (S-1)
16
+ ## 위험
17
+ —
18
+ ## 증명
19
+ —
20
+ ## 테스트 체크리스트
21
+ —
22
+ ## 이탈 기록
23
+ —
@@ -0,0 +1,17 @@
1
+ ---
2
+ intent: "000"
3
+ status: draft
4
+ approvals: []
5
+ summary_for_user: |
6
+ —
7
+ ---
8
+ ## 요구 해석
9
+ - S-1 —
10
+ ## 설계
11
+ —
12
+ ## 우려 표시
13
+ —
14
+ ## 검증 기준
15
+ —
16
+ ## 범위 밖
17
+ —
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: 000-1
3
+ intent: "000"
4
+ plan_step: 1
5
+ title: —
6
+ status: todo
7
+ depends: []
8
+ release: planned
9
+ role: implementer
10
+ budget: {}
11
+ asks: []
12
+ branch: feat/000-example
13
+ ---
14
+ ## 목적
15
+ —
16
+ ## 현재 코드
17
+ —
18
+ ## 작업
19
+ - [ ] —
20
+ ## 결정
21
+ —
22
+ ## 기대 결과
23
+ —
24
+ ## 예상 오류 / 주의
25
+ —
26
+ ## 검증
27
+ - [ ] 게이트
28
+ - [ ] 시나리오
29
+ - [ ] 사용자 확인 필요
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@bluenyang/reins",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Installs, migrates and updates an agent harness (harness → loop → graph) that keeps coding agents inside their permitted roles.",
5
+ "license": "MIT",
6
+ "repository": "github:bluenyang/reins",
7
+ "type": "module",
8
+ "bin": {
9
+ "reins": "cli/dist/reins.js"
10
+ },
11
+ "files": [
12
+ "cli/dist",
13
+ "harness",
14
+ "skills",
15
+ "README.md",
16
+ "docs/README.ko.md"
17
+ ],
18
+ "engines": {
19
+ "node": ">=20"
20
+ },
21
+ "packageManager": "pnpm@12.15.0",
22
+ "scripts": {
23
+ "build": "tsc -p cli/tsconfig.json",
24
+ "typecheck": "tsc -p cli/tsconfig.json --noEmit",
25
+ "lint": "oxlint cli/src cli/test test",
26
+ "fmt": "oxfmt --write cli/src cli/test test",
27
+ "fmt:check": "oxfmt --check cli/src cli/test test",
28
+ "test": "vitest run",
29
+ "check": "pnpm lint && pnpm fmt:check && pnpm typecheck && pnpm test",
30
+ "prepare": "husky"
31
+ },
32
+ "dependencies": {
33
+ "ajv": "^8.20.0",
34
+ "commander": "^15.0.0",
35
+ "yaml": "^2.9.1"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^26.6.5",
39
+ "husky": "^9.1.7",
40
+ "oxfmt": "^0.74.0",
41
+ "oxlint": "^1.89.0",
42
+ "typescript": "^7.0.2",
43
+ "vitest": "^5.0.5"
44
+ }
45
+ }
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: reins-intent
3
+ description: Turn a request into an approved intent and an accepted spec — runs the questionnaire with the user, writes .agents/intent/NNN_slug/intent.md, holds for the user's approval, then has the planner write spec.md and shows its summary for the user's veto. Use when the user brings a new feature, change or problem, says new intent or plan this, or before any spec, plan or code exists for the work.
4
+ ---
5
+
6
+ # reins-intent
7
+
8
+ The two points where a person decides (design §4): **the intent is approved by the user**, and **the spec
9
+ summary may be vetoed by the user** (R64). Everything here leads to one of them; never cross either alone.
10
+
11
+ ## Intent — pm role
12
+ 1. Search what was already decided or rejected: `reins recall <keywords>` (until it ships:
13
+ `grep -l 'decisions:.*<keyword>' .loctx/history/*` and `.agents/knowledge/`). A rejected proposal is not
14
+ raised again (C8).
15
+ 2. Next id = highest `.agents/intent/NNN_*` + 1, three digits; slug in kebab-case.
16
+ 3. **Questionnaire — ask only what only the user knows**, in one batch: the problem, the desired outcome,
17
+ constraints, what not to do. State your defaults for everything else instead of asking.
18
+ 4. Copy `.agents/harness/templates/intent.md` to `.agents/intent/<NNN>_<slug>/intent.md`; write it in the
19
+ user's words and language; record the questions and answers under the questionnaire section;
20
+ `status: draft`, `origin: user`, `version:` the release it targets.
21
+ 5. Show it and **ask for approval. Never set `approved` yourself.** On the user's explicit yes:
22
+ `status: approved`, `approvals: [{role: user, at: <date>}]`, and commit only that change with the trailer
23
+ `Approved-by: <the user's name>` (`git commit -m "docs(intent): approve <NNN> <slug>" -m "Approved-by: …"`).
24
+
25
+ ## Spec — planner, then pm and qa-design
26
+ 6. planner: copy `templates/spec.md`; every requirement is `S-n` with the intent sentence it comes from;
27
+ invariants in AGENTS.md checked (conflict or none); `summary_for_user:` 3–5 lines in the user's language.
28
+ 7. pm reviews against the intent; qa-design gives the first review (bus `kind: review`). Fix, then
29
+ `status: reviewed`.
30
+ 8. **Show `summary_for_user` and the acceptance criteria; the user may veto** (G2 → revise the spec). No veto →
31
+ `status: accepted`, `approvals:` pm, qa-design and `{role: user, kind: summary}`; commit with
32
+ `Approved-by:`. Then hand over to `reins-loop`.
33
+
34
+ A role bound to a vendor with no generated files yet (round one generates Claude only) runs on Claude with
35
+ its role file as instructions; say so in the history line.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: reins-loop
3
+ description: Run an accepted spec through the reins loop — plan, tickets, implement, verify, review, history — calling reins check at every transition (T1 ticket-start, T2 pre-commit, T3 verdict, T5 rc-close) and stopping where it says. Use when an intent's spec is accepted, when the user says continue, next ticket or run the loop, or to resume a stopped ticket.
4
+ ---
5
+
6
+ # reins-loop
7
+
8
+ Roles judge, scripts enforce. After every step run the named check; **its verdict decides what happens next**:
9
+ CONTINUE → go on · HOLD → ask the user (one line: reason id + what you need) · STOP → do what `resume` says,
10
+ then re-run the same check · ESCALATE → the next role in the chain (pl → pm → advisor → user).
11
+ Exit codes 0/10/20/30. Use `npx @bluenyang/reins` (inside the reins repository: `node cli/dist/reins.js`).
12
+
13
+ ## Plan — pl
14
+ 1. From the accepted spec: copy `templates/plan.md` to the intent folder — files that change, **order of work
15
+ (one item = one ticket)**, risks, proof, test checklist; `tickets: [<NNN>-1, …]`, `agents:` roles.
16
+ 2. qa-design reviews it lightly (bus `kind: review`) → `status: reviewed`. Commit.
17
+ 3. For each order-of-work item: `.loctx/ticket/<NNN>-<n>_<slug>.md` from `templates/ticket.md`. Anything
18
+ the ticket cannot decide alone goes in `asks:`.
19
+
20
+ ## Each ticket
21
+ 4. **T1** `reins check --stage ticket-start --ticket <id>`. Open `asks:` hold for the user; the check also
22
+ names recorded decisions that may already answer them.
23
+ 5. Branch `type/<NNN>-<slug>` from the default branch. implementer (`reins-implementer` subagent):
24
+ ticket → plan section → `reins recall` → implement, **one commit per finished unit** (the hook runs **T2**).
25
+ A diff outside the plan updates plan.md's departure log in the same commit (C2), or opens a new ticket (C10).
26
+ 6. **Verify.** Write `.loctx/bus/<id>_<nn>.request.yaml` (`kind: verify`); verify-tool runs
27
+ `reins gate --ticket <id>` and answers in `<id>_<nn>.response.yaml` with the report paths as `evidence:`.
28
+ **T3** `reins check --stage verdict --ticket <id>`. Fail → back to 5 (a second failure escalates, D1).
29
+ 7. **Review.** code-review gets the diff against plan and spec (`kind: review`) and proposes fixes only;
30
+ pl decides fix or proceed. Nobody judges their own work.
31
+ 8. **Close.** `status: done`; one history page or line in `.loctx/history/` naming the ticket id, its commits,
32
+ and a `decisions:` line; then delete the ticket file and its bus files.
33
+
34
+ **Metrics.** After each role run, report what it cost: `reins metrics record --role <r> --tokens <n> --ticket <id>`.
35
+ Tokens come from the vendor — Claude subagent: the Agent result's token count · `codex exec`: the "tokens used"
36
+ line · `agy`, `cursor-agent` with `--output-format json`: the usage field when present. No count from the
37
+ vendor → record nothing, never guess. `reins check` and `reins gate` log themselves to
38
+ `.loctx/reports/metrics.jsonl`; `reins metrics` summarises it.
39
+
40
+ ## Release
41
+ 9. When every planned ticket is done: **T5** `reins check --stage rc-close --release <version>`. Report to
42
+ the user. Push, PR and release happen only on the user's instruction, in the deploy role (T4 runs in the
43
+ pre-push hook); a stable release is always the user's explicit call (A2).
44
+
45
+ On an interruption (G1) write where you are — ticket, step, last commit, open bus files, next command — to
46
+ the ticket, so the same command resumes.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: reins-setup
3
+ description: Install reins in this repository, or move an existing harness onto it — detects the harness generation, runs reins install or reins migrate, confirms gates, bindings and hooks with the user, and checks for drift. Use when the user asks to set up, install, adopt or migrate to reins, or when AGENTS.md has no reins blocks yet.
4
+ ---
5
+
6
+ # reins-setup
7
+
8
+ You act as the **pm** role (`.agents/harness/roles/pm.md` once installed). The CLI does the work; you collect
9
+ the answers only the user can give and report what happened. Run the CLI as `npx @bluenyang/reins …`
10
+ (inside the reins repository itself: `node cli/dist/reins.js …`).
11
+
12
+ 1. **Look first.** `reins install graph --dry-run --json` → read `generation` and `refused`.
13
+ - `refused` (3rd/4th-generation harness) → `reins migrate <tier> --dry-run` and show the moves.
14
+ - `.ai/` present (1st/2nd generation) → install, then offer `reins migrate`.
15
+ 2. **One batch of questions, defaults stated** — never more than one round:
16
+ tier (`graph` when two or more vendors are detected, else `loop`; `harness` for permissions only) ·
17
+ vendors to use (show the detected ones) · language of the documents the user reads · public repository?
18
+ 3. **Apply** non-interactively: `reins install <tier> --mode auto` (or `reins migrate <tier> --mode auto`).
19
+ Then adjust what the user changed: `reins configure bindings --set <role>=<model> …`.
20
+ 4. **Gates.** Show `.agents/harness/gates.yaml`; run `reins gate` once. A gate that fails or mutates files is
21
+ the user's call — never edit the project's scripts to make it pass.
22
+ 5. **Hooks are proposed, not added.** Show the proposal from the install notes; only on the user's yes run
23
+ `reins install <tier> --mode auto --hooks`.
24
+ 6. **Verify.** `reins check --drift` must print `drift: ok`. Commit on a branch (`chore/reins-setup`), one commit
25
+ per step that changed files. Never push.
26
+ 7. **Report** in the user's language: generation before → after, the bindings table, gates, notes, and the
27
+ next step — bring the first request to `reins-intent`.