devlyn-cli 4.3.30 → 4.3.32

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 (43) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +3 -1
  4. package/bin/devlyn.js +33 -8
  5. package/bin/harness-activation.js +4 -1
  6. package/bin/harness-status.js +15 -8
  7. package/bin/instruction-templates.json +2 -0
  8. package/bin/skill-history.json +12 -1
  9. package/config/skills/_shared/bring-in.py +10 -0
  10. package/config/skills/_shared/runtime-principles.md +1 -1
  11. package/config/skills/_shared/task-complete.py +319 -54
  12. package/config/skills/_shared/task-completion.md +5 -5
  13. package/config/skills/_shared/warm-build-dirs.py +13 -0
  14. package/config/skills/devlyn-ideate/references/executor.md +1 -1
  15. package/config/skills/devlyn-ideate/references/loop.md +1 -1
  16. package/config/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  17. package/config/skills/devlyn-ideate/scripts/queue.py +17 -1
  18. package/harness/AGENTS.md +2 -2
  19. package/harness/CLAUDE.md +2 -2
  20. package/native/claude/.claude-plugin/plugin.json +1 -1
  21. package/native/claude/skills/_shared/bring-in.py +10 -0
  22. package/native/claude/skills/_shared/runtime-principles.md +1 -1
  23. package/native/claude/skills/_shared/task-complete.py +319 -54
  24. package/native/claude/skills/_shared/task-completion.md +5 -5
  25. package/native/claude/skills/_shared/warm-build-dirs.py +13 -0
  26. package/native/claude/skills/devlyn-ideate/references/executor.md +1 -1
  27. package/native/claude/skills/devlyn-ideate/references/loop.md +1 -1
  28. package/native/claude/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  29. package/native/claude/skills/devlyn-ideate/scripts/queue.py +17 -1
  30. package/native/codex/.agents/plugins/marketplace.json +1 -1
  31. package/native/codex/plugins/devlyn/.codex-plugin/plugin.json +1 -1
  32. package/native/codex/plugins/devlyn/skills/_shared/bring-in.py +10 -0
  33. package/native/codex/plugins/devlyn/skills/_shared/runtime-principles.md +1 -1
  34. package/native/codex/plugins/devlyn/skills/_shared/task-complete.py +319 -54
  35. package/native/codex/plugins/devlyn/skills/_shared/task-completion.md +5 -5
  36. package/native/codex/plugins/devlyn/skills/_shared/warm-build-dirs.py +13 -0
  37. package/native/codex/plugins/devlyn/skills/devlyn-ideate/references/executor.md +1 -1
  38. package/native/codex/plugins/devlyn/skills/devlyn-ideate/references/loop.md +1 -1
  39. package/native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/acceptance.py +11 -0
  40. package/native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/queue.py +17 -1
  41. package/optional-skills/code-review-standards/SKILL.md +10 -6
  42. package/package.json +1 -1
  43. package/release.json +45 -45
@@ -201,14 +201,14 @@ publication mode pushes no task commit and opens no PR. Delivery is `COMPLETE` w
201
201
  `pr` pushes the exact accepted task ref and creates/reuses its exact repository,
202
202
  head and base PR. While OPEN, it cancels owned auto-merge, reports `PR` with its URL
203
203
  and retains the checkout. Once MERGED by any method, either mode cleans released
204
- resources in that call, on resume or at the next allocation. Default `auto` also requests
205
- a `--merge --match-head-commit <accepted SHA>` merge. Repository
206
- checks/reviews and merge policy remain authoritative: no admin bypass, strategy
204
+ resources in that call, on resume or at the next allocation. Default `auto` also
205
+ merges the accepted commit. Merge policy remains authoritative: no admin bypass, strategy
207
206
  fallback or repository setting changes. When the repository disallows merge
208
- commits or refuses the request, delivery reports `PR` with `merge_refused` and
207
+ commits or refuses the merge, delivery reports `PR` with `merge_refused` and
209
208
  the PR waits for a person. Command success alone never proves merge.
210
209
 
211
- `PENDING` retains the workspace and reports a receipt-based resume command.
210
+ `PENDING` retains the workspace; its receipt-based resume command merges once
211
+ required checks or reviews pass, or a person merges it.
212
212
  `BLOCKED` names the cause and retry action; repair that condition before retrying.
213
213
  Resume reobserves Git/PR state under a per-receipt lock, reuses the original
214
214
  acceptance and performs only missing eligible effects.
@@ -706,9 +706,14 @@ class WarmTests(unittest.TestCase):
706
706
  (bin_dir / "cargo").write_text(FAKE_CARGO)
707
707
  (bin_dir / "cargo").chmod(0o755)
708
708
  self.fixture, self.log = self.root / "fixture.json", self.root / "cargo.log"
709
+ # A commit's detached automatic maintenance would still write into .git while a test reads the tree. Appended to
710
+ # the inherited GIT_CONFIG_COUNT entries, which this environment keeps.
711
+ count = int(os.environ.get("GIT_CONFIG_COUNT") or 0)
709
712
  self.environment = mock.patch.dict(os.environ, {
710
713
  "PATH": f"{bin_dir}{os.pathsep}{os.environ['PATH']}", "FAKE_CARGO": str(self.fixture),
711
714
  "FAKE_CARGO_LOG": str(self.log), "GIT_CONFIG_GLOBAL": os.devnull, "GIT_CONFIG_NOSYSTEM": "1",
715
+ "GIT_CONFIG_COUNT": str(count + 1), f"GIT_CONFIG_KEY_{count}": "maintenance.auto",
716
+ f"GIT_CONFIG_VALUE_{count}": "false",
712
717
  "PYTHONPATH": str(self.root) + os.pathsep + os.environ.get("PYTHONPATH", ""),
713
718
  "PYTHONDONTWRITEBYTECODE": "1",
714
719
  "GIT_AUTHOR_NAME": "t", "GIT_AUTHOR_EMAIL": "t@t", "GIT_COMMITTER_NAME": "t", "GIT_COMMITTER_EMAIL": "t@t"})
@@ -749,6 +754,14 @@ class WarmTests(unittest.TestCase):
749
754
  def git(self, work, *args):
750
755
  return subprocess.run(["git", "-C", str(work), *args], check=True, capture_output=True, text=True).stdout
751
756
 
757
+ def test_fixture_commit_starts_no_automatic_maintenance(self):
758
+ # Its detached child would still write into .git while a test reads the tree or cleanup removes it.
759
+ trace = self.root / "trace.json"
760
+ os.environ["GIT_TRACE2_EVENT"] = str(trace) # setUp's patch restores the environment
761
+ self.git(self.anchor, "commit", "-q", "--allow-empty", "-m", "traced")
762
+ children = [line for line in trace.read_text(encoding="utf-8").splitlines() if '"event":"child_start"' in line]
763
+ self.assertEqual(children, [])
764
+
752
765
  def write_fixture(self, **extra):
753
766
  packages = [
754
767
  {"name": "app", "source": None, "manifest_path": str(self.work / "Cargo.toml"), "targets": [{"kind": ["lib"], "name": "LIB"}]},
@@ -59,4 +59,4 @@ Each `review_requirements` ID needs review evidence: a JSON record under `<workt
59
59
  }
60
60
  ```
61
61
 
62
- A record counts only when it binds this task, the candidate source and both contract digests; any other well-formed record is reported under `ignored_reviews` (a source change invalidates earlier reviews). A listed review or runner record that is unreadable or not this shape fails acceptance with its path named; keys a review record or finding adds beyond this shape are ignored. The counted records' `requirements` must cover `review_requirements`. Each finding's `disposition` is `open`, `resolved` or `rejected` (`rejected` needs a `reason`); an open binding finding blocks acceptance. The loop requires no particular engine or number of reviewers.
62
+ A record counts only when it binds this task, the candidate source and both contract digests; any other well-formed record is reported under `ignored_reviews` (a source change invalidates earlier reviews; the record for the changed source may come from a pass that reads only the change and the invariants it touches). A listed review or runner record that is unreadable or not this shape fails acceptance with its path named; keys a review record or finding adds beyond this shape are ignored. The counted records' `requirements` must cover `review_requirements`. Each finding's `disposition` is `open`, `resolved` or `rejected` (`rejected` needs a `reason`); an open binding finding blocks acceptance. The loop requires no particular engine or number of reviewers.
@@ -32,7 +32,7 @@ The host supplies the executor and maps its configured engine to the argv; the l
32
32
  6. **Derive acceptance** with `acceptance.py accept`. It binds the committed contract to the packet digests; requires the candidate to be the owned branch head with HEAD checked out on that branch, to descend from the inputs, to leave the package (its queue file included) and `docs/specs/queue.md` untouched and to have a clean worktree; executes each declared command on that source, recording raw stdout/stderr and exit, timeout or spawn outcomes (a runner result is reused only when it is wholly clean — no reasons, so no failed check and no source change during its checks — for the same source and contract digests, with unchanged streams); evaluates the file and diff guards against the inputs; confirms the source is unchanged; checks review records; and writes `.devlyn/loop/acceptance.json`. Missing checks, missing review coverage and open binding findings cannot produce `[x]`, and acceptance weakening is not repair. This establishes command outcomes and evidence completeness, not a reviewer's semantic judgment; deliberate evidence forgery is outside the trust model.
33
33
  7. **Bind before terminal metadata.** `task-complete.py accept --receipt <receipt> --acceptance <worktree>/.devlyn/loop/acceptance.json` takes evidence custody and points the recovery ref at the source. Failed results are bound the same way; they never become a frontier or a publishable product.
34
34
  8. **Commit the terminal transition** under the queue lock: one commit whose sole parent is the bound source and whose only change is this task's row in `docs/specs/<loop-id>/queue.md` (`[x]`, or `[F] — <first reason> (receipt <id>)`), validated as the only legal transition. Then `task-complete.py attach --receipt <receipt> --commit <terminal> --file docs/specs/<loop-id>/queue.md` records it separately from the source and moves the recovery ref to it.
35
- 9. **Deliver** after waiting for the executor, with `task-complete.py complete --receipt <receipt> --writers-stopped`, plus `--local-only` or, until the receipt records a mode, the packet's `--mode auto|pr`, so a per-task `--mode` persists. Local-only keeps source, custody and the recovery ref with no remote effect. `auto`/`pr` publish the terminal commit under the completion contract; a pending or refused delivery keeps product acceptance, resources and a resume command. Where writer cessation cannot be observed, or a process still uses the tree, a merged delivery settles (`COMPLETE`) with its workspace, task ref and custody retained and reported under workspace cleanup; retained cleanup never blocks the queue. Failed products are never published. The receipt's `delivery` field checkpoints the latest outcome. A local chain is never turned into stacked PRs; publishing it requires integrated acceptance of the actual publication candidate.
35
+ 9. **Deliver** after waiting for the executor, with `task-complete.py complete --receipt <receipt> --writers-stopped`, plus `--local-only` or, until the receipt records a mode, the packet's `--mode auto|pr`, so a per-task `--mode` persists. Local-only keeps source, custody and the recovery ref with no remote effect. `auto`/`pr` publish the terminal commit under the completion contract; a pending or refused delivery keeps product acceptance, resources and a resume command. A merged delivery whose cleanup is refused settles (`COMPLETE`) with what the refusal guards retained and reported under workspace cleanup; retained cleanup never blocks the queue. Failed products are never published. The receipt's `delivery` field checkpoints the latest outcome. A local chain is never turned into stacked PRs; publishing it requires integrated acceptance of the actual publication candidate.
36
36
  10. **Recover** from durable state only:
37
37
 
38
38
  | Interrupted | Resume |
@@ -515,6 +515,8 @@ class AcceptanceTests(unittest.TestCase):
515
515
  self.addCleanup(self.temp.cleanup)
516
516
  self.root = Path(self.temp.name).resolve()
517
517
  self.work = self.root / "work tree"
518
+ # A commit's detached automatic maintenance would still write into .git while a test reads the tree.
519
+ (self.root / "gitconfig").write_text("[maintenance]\n\tauto = false\n", encoding="utf-8")
518
520
  env = {"GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_GLOBAL": str(self.root / "gitconfig"), "GIT_AUTHOR_NAME": "Fixture",
519
521
  "GIT_AUTHOR_EMAIL": "fixture@example.invalid", "GIT_COMMITTER_NAME": "Fixture", "GIT_COMMITTER_EMAIL": "fixture@example.invalid"}
520
522
  self.saved = {key: os.environ.get(key) for key in env}
@@ -543,6 +545,15 @@ class AcceptanceTests(unittest.TestCase):
543
545
  self.g("commit", "-q", "-m", message)
544
546
  return self.g("rev-parse", "HEAD")
545
547
 
548
+ def test_fixture_commit_starts_no_automatic_maintenance(self):
549
+ # Its detached child would still write into .git while a test reads the tree or cleanup removes it.
550
+ from unittest import mock
551
+ trace = self.root / "trace.json"
552
+ with mock.patch.dict(os.environ, GIT_TRACE2_EVENT=str(trace)):
553
+ self.g("commit", "-q", "--allow-empty", "-m", "traced")
554
+ children = [line for line in trace.read_text(encoding="utf-8").splitlines() if '"event":"child_start"' in line]
555
+ self.assertEqual(children, [])
556
+
546
557
  def inputs(self, expected=None, review=()):
547
558
  base = self.g("rev-parse", "HEAD")
548
559
  files = {"docs/specs/l/meta.md": "# meta\n", "docs/specs/l/t/spec.md": "# task R1 R2\n",
@@ -1429,6 +1429,8 @@ def advance(v, row, opts):
1429
1429
  progress(identity, f"delivery {result['status']}")
1430
1430
  if result.get("merge_refused"):
1431
1431
  return f"merge refused: {result['merge_refused']}; a person merges the PR"
1432
+ if waits := result.get("merge_waits"):
1433
+ return f"merge waits: PR is {waits} ({'GitHub has not computed its mergeability yet' if waits == 'UNKNOWN' else 'required checks or reviews not passing yet'}); drain again later, or merge it"
1432
1434
  return None
1433
1435
 
1434
1436
 
@@ -1657,11 +1659,15 @@ def status_summary(v):
1657
1659
  row = next_task(v, set())
1658
1660
  annotate(v, {})
1659
1661
  tasks = [summary(v, r) for r in v["rows"] if r["identity"]]
1662
+ # A task without a resume is no pending delivery, so a cleanup it retained is named here with its own resume.
1663
+ retained = [f"{t['identity']}: {label} {t[key]}" for t in tasks if not t.get("resume")
1664
+ for key, field, label in (("cleanup", "workspace_cleanup", "workspace cleanup"), ("scratch", "scratch_cleanup", "scratch cleanup"))
1665
+ if ((v["states"][t["identity"]]["receipt"] or {}).get(field) or {}).get("reason")]
1660
1666
  return {"status": "OK", **skill_diagnostics(anchor), "counts": counts(v), "next": row["identity"] if row else None,
1661
1667
  "blockers": [f"{t['identity']}: {t['reason']}" for t in tasks if t.get("reason") and t["result"] in {"pending", "active", "blocked"}]
1662
1668
  + [f"legacy row {r['index'] + 1} needs planning: {r['text']}" for r in v["rows"] if not r["identity"] and r["mark"] == " "]
1663
1669
  + [f"unreadable receipt {item}" for item in v["unreadable"]],
1664
- "delivery": [t for t in tasks if t.get("resume")], "cleanup": v["cleanup"]}
1670
+ "delivery": [t for t in tasks if t.get("resume")], "cleanup": v["cleanup"] + retained}
1665
1671
 
1666
1672
 
1667
1673
  def status(args):
@@ -1897,6 +1903,8 @@ class QueueTests(unittest.TestCase):
1897
1903
  "import shutil\nfrom types import SimpleNamespace\n"
1898
1904
  "shutil.disk_usage = lambda path: SimpleNamespace(total=100 * 1024**3, free=100 * 1024**3)\n",
1899
1905
  encoding="utf-8")
1906
+ # A commit's detached automatic maintenance would still write into .git while a test reads the tree.
1907
+ (self.root / "gitconfig").write_text("[maintenance]\n\tauto = false\n", encoding="utf-8")
1900
1908
  self.env = {**os.environ, "GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_GLOBAL": str(self.root / "gitconfig"),
1901
1909
  "GIT_AUTHOR_NAME": "Fixture", "GIT_AUTHOR_EMAIL": "fixture@example.invalid",
1902
1910
  "GIT_COMMITTER_NAME": "Fixture", "GIT_COMMITTER_EMAIL": "fixture@example.invalid"}
@@ -1940,6 +1948,14 @@ class QueueTests(unittest.TestCase):
1940
1948
  path.write_text(text.replace(old, new, 1), encoding="utf-8")
1941
1949
  return mutate
1942
1950
 
1951
+ def test_fixture_commit_starts_no_automatic_maintenance(self):
1952
+ # Its detached child would still write into .git while a test reads the tree or cleanup removes it.
1953
+ trace = self.root / "trace.json"
1954
+ subprocess.run(["git", "-C", str(self.anchor), "commit", "-q", "--allow-empty", "-m", "traced"], check=True,
1955
+ env={**self.env, "GIT_TRACE2_EVENT": str(trace)})
1956
+ children = [line for line in trace.read_text(encoding="utf-8").splitlines() if '"event":"child_start"' in line]
1957
+ self.assertEqual(children, [])
1958
+
1943
1959
  def test_package_validation(self):
1944
1960
  self.assertEqual(self.cli("check", self.meta)["tasks"], ["inv.t1", "inv.t2"])
1945
1961
  manifest = json.loads(JSON_FENCE_RE.search((self.anchor / "docs/specs/inv/meta.md").read_text(encoding="utf-8")).group(1))
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: code-review-standards
3
- description: Severity framework (CRITICAL security, HIGH code quality, MEDIUM best practice, LOW cleanup) and approval criteria for judging a code change. Use when reviewing, auditing or validating a diff, pull request or just-finished implementation, or when deciding whether a change is ready to approve.
3
+ description: Severity framework (CRITICAL security, HIGH correctness and data, MEDIUM best practice, LOW cleanup) and approval criteria for judging a code change. Use when reviewing, auditing or validating a diff, pull request or just-finished implementation, or when deciding whether a change is ready to approve.
4
4
  ---
5
5
  # Code Review Standards
6
6
 
@@ -8,6 +8,8 @@ Severity framework and quality bar for reviewing code changes. Apply this framew
8
8
 
9
9
  ## Severity Framework
10
10
 
11
+ A CRITICAL or HIGH finding names its concrete case: the input, state or path that leads to the harm. A finding that cannot name one is MEDIUM or lower.
12
+
11
13
  ### CRITICAL — Security (blocks approval)
12
14
 
13
15
  - Hardcoded credentials, API keys, tokens, secrets
@@ -17,17 +19,19 @@ Severity framework and quality bar for reviewing code changes. Apply this framew
17
19
  - Insecure dependencies (known CVEs)
18
20
  - Path traversal (unsanitized file paths)
19
21
 
20
- ### HIGH — Code Quality (blocks approval)
22
+ ### HIGH — Correctness and data (blocks approval)
23
+
24
+ - Wrong behavior or results
25
+ - Lost or corrupted data
26
+ - Missing error handling at a boundary, where a failure there gives one of the above
27
+
28
+ ### MEDIUM — Best Practices (fix or justify)
21
29
 
22
30
  - Functions > 50 lines → split
23
31
  - Files > 800 lines → decompose
24
32
  - Nesting > 4 levels → flatten or extract
25
- - Missing error handling at boundaries
26
33
  - `console.log` in production code → remove
27
34
  - Unresolved TODO/FIXME → resolve or remove
28
-
29
- ### MEDIUM — Best Practices (fix or justify)
30
-
31
35
  - Mutation where immutable patterns preferred
32
36
  - Missing tests for new functionality
33
37
  - Accessibility gaps (alt text, ARIA, keyboard nav)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devlyn-cli",
3
- "version": "4.3.30",
3
+ "version": "4.3.32",
4
4
  "description": "Loop & harness engineering for AI coding agents (Claude Code, Codex, and any AGENTS.md-driven agent) — core engineering principles for every session and a loop designer that splits one intent into tasks agents drain hands-free",
5
5
  "homepage": "https://github.com/fysoul17/devlyn-cli#readme",
6
6
  "bin": {
package/release.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "devlyn-cli",
4
- "version": "4.3.30",
4
+ "version": "4.3.32",
5
5
  "principles": {
6
6
  "defaults": "config/skills/_shared/runtime-principles.md",
7
7
  "memory": {
8
8
  "claude": "harness/CLAUDE.md",
9
9
  "agents": "harness/AGENTS.md"
10
10
  },
11
- "sourceBlockSha256": "eaf6d144bcb25ac8c5e628a134dc4422f5af7641f9c34ccdb8f06d1613718c48"
11
+ "sourceBlockSha256": "7a484752888c37d7e91a9edfaa17d36b34ada221fc1d533ab9d73bc08c56ae7e"
12
12
  },
13
13
  "skills": {
14
14
  "root": "config/skills",
@@ -99,12 +99,12 @@
99
99
  "files": [
100
100
  {
101
101
  "path": "AGENTS.md",
102
- "sha256": "df67efd70f4760d2415c414eb96d4cc426277c20e18f17e401257f85b489eb59",
102
+ "sha256": "207efe7b897a2704ec8a22163f02891ac1a17d521e8a44f4556e59d60a6de19f",
103
103
  "executable": false
104
104
  },
105
105
  {
106
106
  "path": "CLAUDE.md",
107
- "sha256": "df67efd70f4760d2415c414eb96d4cc426277c20e18f17e401257f85b489eb59",
107
+ "sha256": "207efe7b897a2704ec8a22163f02891ac1a17d521e8a44f4556e59d60a6de19f",
108
108
  "executable": false
109
109
  },
110
110
  {
@@ -114,7 +114,7 @@
114
114
  },
115
115
  {
116
116
  "path": "README.md",
117
- "sha256": "fa6956e7d769d1b7731b804af07f0a0d30fb775e5be7cf53e3099257f71f7ac8",
117
+ "sha256": "bbc875764d90876e032b71363bf833bc0919368940943bfd66f1fb72391306fe",
118
118
  "executable": false
119
119
  },
120
120
  {
@@ -129,7 +129,7 @@
129
129
  },
130
130
  {
131
131
  "path": "bin/devlyn.js",
132
- "sha256": "d74e237346ffc0966867bbaf3a5c411b5a25888575b6c363f9347cd6a7c90b02",
132
+ "sha256": "3a68ed60da74b66fe6303819924128cb11b1bc64a63518b947dc6b26a631325d",
133
133
  "executable": true
134
134
  },
135
135
  {
@@ -139,7 +139,7 @@
139
139
  },
140
140
  {
141
141
  "path": "bin/harness-activation.js",
142
- "sha256": "e5428bf6fb2dc40e0f7bebcc834b54573c0b8c648570fea8bd51774d5e865727",
142
+ "sha256": "8457005c714c93a31c0b65c26ccd604fdd760f7db978045dbdd1b5724532f742",
143
143
  "executable": false
144
144
  },
145
145
  {
@@ -154,12 +154,12 @@
154
154
  },
155
155
  {
156
156
  "path": "bin/harness-status.js",
157
- "sha256": "7cc1bc83594952806142a7e3bda2430d21a583ae31a3b1800aa2811a645e0ad0",
157
+ "sha256": "6b0b209d77253eef4c92d38b939c4e0828705128d37ed7158d033bdadd762280",
158
158
  "executable": false
159
159
  },
160
160
  {
161
161
  "path": "bin/instruction-templates.json",
162
- "sha256": "752cc4b023930ca696395fb071b93d17a6fabf34aec9e2b993e88f2d2d1673c9",
162
+ "sha256": "6e8998bcfa674c32fc92dc48c3e9b83e07fe7b48c3ae203e0943ae837181f473",
163
163
  "executable": false
164
164
  },
165
165
  {
@@ -174,7 +174,7 @@
174
174
  },
175
175
  {
176
176
  "path": "bin/skill-history.json",
177
- "sha256": "de454d15a5d1e81f0f69f5d1d781ea02d8b19554695458a993d74596d5055146",
177
+ "sha256": "bb5a18a5c7f846c6e3b427a141600a1699dcf01e724193d840f9a10874954057",
178
178
  "executable": false
179
179
  },
180
180
  {
@@ -204,7 +204,7 @@
204
204
  },
205
205
  {
206
206
  "path": "config/skills/_shared/bring-in.py",
207
- "sha256": "754b3892ceb611c855f814e0aa54b645b53de4a67ddec44418f254cb36774527",
207
+ "sha256": "b712de03e30b8a5b29f13f3eb9b0c3787f68edaaa980e0b25fe90885365861d5",
208
208
  "executable": false
209
209
  },
210
210
  {
@@ -259,7 +259,7 @@
259
259
  },
260
260
  {
261
261
  "path": "config/skills/_shared/runtime-principles.md",
262
- "sha256": "a8544f866db7b8e49617f14519908a601cbd8b92786cecb521cba5c28421a7f7",
262
+ "sha256": "7492c2e1854ef6b0aef8cf1f5dd85e612ed954cff90196ec7c17cc47d12c9937",
263
263
  "executable": false
264
264
  },
265
265
  {
@@ -274,12 +274,12 @@
274
274
  },
275
275
  {
276
276
  "path": "config/skills/_shared/task-complete.py",
277
- "sha256": "1f39a27e0dc70c727dc79d47c2b294e75bfd1efbc8df4f0492d68578a29405a2",
277
+ "sha256": "5f893064511e273258ebe721e967166485a812fbe9a9f1e818e2c605ef039abc",
278
278
  "executable": false
279
279
  },
280
280
  {
281
281
  "path": "config/skills/_shared/task-completion.md",
282
- "sha256": "3b75502d363ba5fa3b45c06a1f3e0de7c88e609d4f91c41d75287a0acccdd504",
282
+ "sha256": "26a0634d2c38753b0d226946eac7fc395b6f21b3e460433d2638b7eb6a57ad3a",
283
283
  "executable": false
284
284
  },
285
285
  {
@@ -289,7 +289,7 @@
289
289
  },
290
290
  {
291
291
  "path": "config/skills/_shared/warm-build-dirs.py",
292
- "sha256": "ccc842227dfe8d531b06e0e32a13a580c127af9c354b086548da8c547af6c2b0",
292
+ "sha256": "981cab5ea6629182aef01dca1eb2b410ab91fd4581dd500f58e0a8313b39f245",
293
293
  "executable": false
294
294
  },
295
295
  {
@@ -309,12 +309,12 @@
309
309
  },
310
310
  {
311
311
  "path": "config/skills/devlyn-ideate/references/executor.md",
312
- "sha256": "aa53076dffa1fcf49e2350206b5f0ba73306b92ccce3502160dca4f26113e4be",
312
+ "sha256": "40582ff8fad59f09fe327ac4f232463b6c55a91be1288c7470f7c8c0b3da95fe",
313
313
  "executable": false
314
314
  },
315
315
  {
316
316
  "path": "config/skills/devlyn-ideate/references/loop.md",
317
- "sha256": "ad64d90fb775b05ef774c2457fc9d994b062e17e017da07054be0d93d83e533f",
317
+ "sha256": "1b7f48ddbe5bbdf0145d7e6797784d5e7fa1af548e751ad6e6869a96de65b58f",
318
318
  "executable": false
319
319
  },
320
320
  {
@@ -329,12 +329,12 @@
329
329
  },
330
330
  {
331
331
  "path": "config/skills/devlyn-ideate/scripts/acceptance.py",
332
- "sha256": "5e25ce6fcbd1773e988a1146f0f4a681676936dad113c43c693fdb0925aa168a",
332
+ "sha256": "1c2c173f05f9688839356898dea6e395fea83e78d5c8bc0e00b0d971a33381e9",
333
333
  "executable": false
334
334
  },
335
335
  {
336
336
  "path": "config/skills/devlyn-ideate/scripts/queue.py",
337
- "sha256": "f8447d7f1a3d04332e9aefdd363e15a9351c46ce2b165d4e75cce45906f132cf",
337
+ "sha256": "db80fd2cae92dda70e9b6183e8b9396dca9592358a38ed19fb6893ed3a531dd2",
338
338
  "executable": false
339
339
  },
340
340
  {
@@ -344,17 +344,17 @@
344
344
  },
345
345
  {
346
346
  "path": "harness/AGENTS.md",
347
- "sha256": "68c354a51eae0b77eaa909ec2a11b1ca498c62905e133375929c73085c638d10",
347
+ "sha256": "9c3daa27f67af1feff420f14d7c53cfbc905b7e72e2d32cc47bc8f2a6cbe3555",
348
348
  "executable": false
349
349
  },
350
350
  {
351
351
  "path": "harness/CLAUDE.md",
352
- "sha256": "68c354a51eae0b77eaa909ec2a11b1ca498c62905e133375929c73085c638d10",
352
+ "sha256": "9c3daa27f67af1feff420f14d7c53cfbc905b7e72e2d32cc47bc8f2a6cbe3555",
353
353
  "executable": false
354
354
  },
355
355
  {
356
356
  "path": "native/claude/.claude-plugin/plugin.json",
357
- "sha256": "1c66282653ed10919933b783dbff4353b9a315340d1ceb6d9edb9caf963a23e1",
357
+ "sha256": "ff300febb5b5d8469c3258416f63e156cc05b911ee6f3cf2cd818fbf70f5e80b",
358
358
  "executable": false
359
359
  },
360
360
  {
@@ -379,7 +379,7 @@
379
379
  },
380
380
  {
381
381
  "path": "native/claude/skills/_shared/bring-in.py",
382
- "sha256": "754b3892ceb611c855f814e0aa54b645b53de4a67ddec44418f254cb36774527",
382
+ "sha256": "b712de03e30b8a5b29f13f3eb9b0c3787f68edaaa980e0b25fe90885365861d5",
383
383
  "executable": false
384
384
  },
385
385
  {
@@ -434,7 +434,7 @@
434
434
  },
435
435
  {
436
436
  "path": "native/claude/skills/_shared/runtime-principles.md",
437
- "sha256": "a8544f866db7b8e49617f14519908a601cbd8b92786cecb521cba5c28421a7f7",
437
+ "sha256": "7492c2e1854ef6b0aef8cf1f5dd85e612ed954cff90196ec7c17cc47d12c9937",
438
438
  "executable": false
439
439
  },
440
440
  {
@@ -449,12 +449,12 @@
449
449
  },
450
450
  {
451
451
  "path": "native/claude/skills/_shared/task-complete.py",
452
- "sha256": "1f39a27e0dc70c727dc79d47c2b294e75bfd1efbc8df4f0492d68578a29405a2",
452
+ "sha256": "5f893064511e273258ebe721e967166485a812fbe9a9f1e818e2c605ef039abc",
453
453
  "executable": false
454
454
  },
455
455
  {
456
456
  "path": "native/claude/skills/_shared/task-completion.md",
457
- "sha256": "3b75502d363ba5fa3b45c06a1f3e0de7c88e609d4f91c41d75287a0acccdd504",
457
+ "sha256": "26a0634d2c38753b0d226946eac7fc395b6f21b3e460433d2638b7eb6a57ad3a",
458
458
  "executable": false
459
459
  },
460
460
  {
@@ -464,7 +464,7 @@
464
464
  },
465
465
  {
466
466
  "path": "native/claude/skills/_shared/warm-build-dirs.py",
467
- "sha256": "ccc842227dfe8d531b06e0e32a13a580c127af9c354b086548da8c547af6c2b0",
467
+ "sha256": "981cab5ea6629182aef01dca1eb2b410ab91fd4581dd500f58e0a8313b39f245",
468
468
  "executable": false
469
469
  },
470
470
  {
@@ -484,12 +484,12 @@
484
484
  },
485
485
  {
486
486
  "path": "native/claude/skills/devlyn-ideate/references/executor.md",
487
- "sha256": "aa53076dffa1fcf49e2350206b5f0ba73306b92ccce3502160dca4f26113e4be",
487
+ "sha256": "40582ff8fad59f09fe327ac4f232463b6c55a91be1288c7470f7c8c0b3da95fe",
488
488
  "executable": false
489
489
  },
490
490
  {
491
491
  "path": "native/claude/skills/devlyn-ideate/references/loop.md",
492
- "sha256": "ad64d90fb775b05ef774c2457fc9d994b062e17e017da07054be0d93d83e533f",
492
+ "sha256": "1b7f48ddbe5bbdf0145d7e6797784d5e7fa1af548e751ad6e6869a96de65b58f",
493
493
  "executable": false
494
494
  },
495
495
  {
@@ -504,22 +504,22 @@
504
504
  },
505
505
  {
506
506
  "path": "native/claude/skills/devlyn-ideate/scripts/acceptance.py",
507
- "sha256": "5e25ce6fcbd1773e988a1146f0f4a681676936dad113c43c693fdb0925aa168a",
507
+ "sha256": "1c2c173f05f9688839356898dea6e395fea83e78d5c8bc0e00b0d971a33381e9",
508
508
  "executable": false
509
509
  },
510
510
  {
511
511
  "path": "native/claude/skills/devlyn-ideate/scripts/queue.py",
512
- "sha256": "f8447d7f1a3d04332e9aefdd363e15a9351c46ce2b165d4e75cce45906f132cf",
512
+ "sha256": "db80fd2cae92dda70e9b6183e8b9396dca9592358a38ed19fb6893ed3a531dd2",
513
513
  "executable": false
514
514
  },
515
515
  {
516
516
  "path": "native/codex/.agents/plugins/marketplace.json",
517
- "sha256": "2b589b387dd262bbb68f68738c9da6315dd06595d0af0dc5c088151235a5a7c8",
517
+ "sha256": "ae244d5c77ec77f0e794c358368ef83c01a07383b86be66cd459b23324504e61",
518
518
  "executable": false
519
519
  },
520
520
  {
521
521
  "path": "native/codex/plugins/devlyn/.codex-plugin/plugin.json",
522
- "sha256": "1c66282653ed10919933b783dbff4353b9a315340d1ceb6d9edb9caf963a23e1",
522
+ "sha256": "ff300febb5b5d8469c3258416f63e156cc05b911ee6f3cf2cd818fbf70f5e80b",
523
523
  "executable": false
524
524
  },
525
525
  {
@@ -544,7 +544,7 @@
544
544
  },
545
545
  {
546
546
  "path": "native/codex/plugins/devlyn/skills/_shared/bring-in.py",
547
- "sha256": "754b3892ceb611c855f814e0aa54b645b53de4a67ddec44418f254cb36774527",
547
+ "sha256": "b712de03e30b8a5b29f13f3eb9b0c3787f68edaaa980e0b25fe90885365861d5",
548
548
  "executable": false
549
549
  },
550
550
  {
@@ -599,7 +599,7 @@
599
599
  },
600
600
  {
601
601
  "path": "native/codex/plugins/devlyn/skills/_shared/runtime-principles.md",
602
- "sha256": "a8544f866db7b8e49617f14519908a601cbd8b92786cecb521cba5c28421a7f7",
602
+ "sha256": "7492c2e1854ef6b0aef8cf1f5dd85e612ed954cff90196ec7c17cc47d12c9937",
603
603
  "executable": false
604
604
  },
605
605
  {
@@ -614,12 +614,12 @@
614
614
  },
615
615
  {
616
616
  "path": "native/codex/plugins/devlyn/skills/_shared/task-complete.py",
617
- "sha256": "1f39a27e0dc70c727dc79d47c2b294e75bfd1efbc8df4f0492d68578a29405a2",
617
+ "sha256": "5f893064511e273258ebe721e967166485a812fbe9a9f1e818e2c605ef039abc",
618
618
  "executable": false
619
619
  },
620
620
  {
621
621
  "path": "native/codex/plugins/devlyn/skills/_shared/task-completion.md",
622
- "sha256": "3b75502d363ba5fa3b45c06a1f3e0de7c88e609d4f91c41d75287a0acccdd504",
622
+ "sha256": "26a0634d2c38753b0d226946eac7fc395b6f21b3e460433d2638b7eb6a57ad3a",
623
623
  "executable": false
624
624
  },
625
625
  {
@@ -629,7 +629,7 @@
629
629
  },
630
630
  {
631
631
  "path": "native/codex/plugins/devlyn/skills/_shared/warm-build-dirs.py",
632
- "sha256": "ccc842227dfe8d531b06e0e32a13a580c127af9c354b086548da8c547af6c2b0",
632
+ "sha256": "981cab5ea6629182aef01dca1eb2b410ab91fd4581dd500f58e0a8313b39f245",
633
633
  "executable": false
634
634
  },
635
635
  {
@@ -649,12 +649,12 @@
649
649
  },
650
650
  {
651
651
  "path": "native/codex/plugins/devlyn/skills/devlyn-ideate/references/executor.md",
652
- "sha256": "aa53076dffa1fcf49e2350206b5f0ba73306b92ccce3502160dca4f26113e4be",
652
+ "sha256": "40582ff8fad59f09fe327ac4f232463b6c55a91be1288c7470f7c8c0b3da95fe",
653
653
  "executable": false
654
654
  },
655
655
  {
656
656
  "path": "native/codex/plugins/devlyn/skills/devlyn-ideate/references/loop.md",
657
- "sha256": "ad64d90fb775b05ef774c2457fc9d994b062e17e017da07054be0d93d83e533f",
657
+ "sha256": "1b7f48ddbe5bbdf0145d7e6797784d5e7fa1af548e751ad6e6869a96de65b58f",
658
658
  "executable": false
659
659
  },
660
660
  {
@@ -669,12 +669,12 @@
669
669
  },
670
670
  {
671
671
  "path": "native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/acceptance.py",
672
- "sha256": "5e25ce6fcbd1773e988a1146f0f4a681676936dad113c43c693fdb0925aa168a",
672
+ "sha256": "1c2c173f05f9688839356898dea6e395fea83e78d5c8bc0e00b0d971a33381e9",
673
673
  "executable": false
674
674
  },
675
675
  {
676
676
  "path": "native/codex/plugins/devlyn/skills/devlyn-ideate/scripts/queue.py",
677
- "sha256": "f8447d7f1a3d04332e9aefdd363e15a9351c46ce2b165d4e75cce45906f132cf",
677
+ "sha256": "db80fd2cae92dda70e9b6183e8b9396dca9592358a38ed19fb6893ed3a531dd2",
678
678
  "executable": false
679
679
  },
680
680
  {
@@ -1554,7 +1554,7 @@
1554
1554
  },
1555
1555
  {
1556
1556
  "path": "optional-skills/code-review-standards/SKILL.md",
1557
- "sha256": "3f11f84adb7d3016c4d71bce743c40e35e682d09bc9376b03be957fc9c8d2b62",
1557
+ "sha256": "24b5ffaea6876575cf9ae70ff8fb1f4b5a75633f5a7a976a87da82630d62a34f",
1558
1558
  "executable": false
1559
1559
  },
1560
1560
  {
@@ -1819,12 +1819,12 @@
1819
1819
  },
1820
1820
  {
1821
1821
  "path": "package.json",
1822
- "sha256": "e4f8b96ad2ca5dd7298d1db30e321e3e965f76d1fa0e4fc4a3e4e1012e124822",
1822
+ "sha256": "0c1111039515ac152abe5f3e16b60272753467645bbced1be38936fe909ad04c",
1823
1823
  "executable": false
1824
1824
  }
1825
1825
  ],
1826
1826
  "digest": {
1827
1827
  "algorithm": "sha256",
1828
- "value": "53a2f9f2d3d8cf8cf43391dd92224aa5190e331f0a993649d0a06256ca6a417d"
1828
+ "value": "87b80d4042da531f2cccef9bde9d9d9964a3c34d061be213199d49e117a8bda2"
1829
1829
  }
1830
1830
  }