boost-skill-cli 1.0.9__tar.gz → 1.0.11__tar.gz

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 (86) hide show
  1. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  4. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_frontmatter.py +103 -0
  5. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/.gitignore +0 -0
  6. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/CLAUDE.md +0 -0
  7. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/CONTRIBUTING.md +0 -0
  8. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/LICENSE +0 -0
  9. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/MANIFEST.in +0 -0
  10. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/Makefile +0 -0
  11. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/README.md +0 -0
  12. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/SECURITY.md +0 -0
  13. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost +0 -0
  14. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/__init__.py +0 -0
  15. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/__main__.py +0 -0
  16. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/cli.py +0 -0
  17. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/__init__.py +0 -0
  18. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/configuration.py +0 -0
  19. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/discovery.py +0 -0
  20. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/info.py +0 -0
  21. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/intelligence.py +0 -0
  22. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/pkg.py +0 -0
  23. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/quality.py +0 -0
  24. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/taps.py +0 -0
  25. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/commands/team.py +0 -0
  26. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/__init__.py +0 -0
  27. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/agents.py +0 -0
  28. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/ai.py +0 -0
  29. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/catalog.py +0 -0
  30. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/config.py +0 -0
  31. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/frontmatter.py +0 -0
  32. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/gitutil.py +0 -0
  33. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/journal.py +0 -0
  34. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/lockfile.py +0 -0
  35. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/logs.py +0 -0
  36. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/output.py +0 -0
  37. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/paths.py +0 -0
  38. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/policy.py +0 -0
  39. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/registry.py +0 -0
  40. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/store.py +0 -0
  41. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/core/util.py +0 -0
  42. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/data/registries.json +0 -0
  43. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_cli/errors.py +0 -0
  44. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  45. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  46. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  47. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/boost_skill_cli.egg-info/top_level.txt +0 -0
  48. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/.claude/settings.local.json +0 -0
  49. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/DEBUGGING.md +0 -0
  50. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/demo.gif +0 -0
  51. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/demo.tape +0 -0
  52. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/index.html +0 -0
  53. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/docs/rag-architecture.md +0 -0
  54. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/pyproject.toml +0 -0
  55. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/scripts/build_registries.py +0 -0
  56. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/scripts/mutation_gate.py +0 -0
  57. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/setup.cfg +0 -0
  58. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/conftest.py +0 -0
  59. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_configuration.py +0 -0
  60. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_discovery.py +0 -0
  61. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_info.py +0 -0
  62. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_intelligence.py +0 -0
  63. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_pkg.py +0 -0
  64. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_quality.py +0 -0
  65. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_taps.py +0 -0
  66. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_cli_team.py +0 -0
  67. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/functional/test_everyday_loop.py +0 -0
  68. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/make_fixture.py +0 -0
  69. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/smoke.sh +0 -0
  70. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_agents.py +0 -0
  71. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_ai.py +0 -0
  72. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_catalog.py +0 -0
  73. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_config.py +0 -0
  74. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_errors_and_cli_table.py +0 -0
  75. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_gitutil.py +0 -0
  76. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_journal.py +0 -0
  77. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_lockfile.py +0 -0
  78. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_logs.py +0 -0
  79. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_mutation_hardening.py +0 -0
  80. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_output.py +0 -0
  81. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_paths.py +0 -0
  82. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_policy.py +0 -0
  83. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_registry.py +0 -0
  84. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_store.py +0 -0
  85. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_util.py +0 -0
  86. {boost_skill_cli-1.0.9 → boost_skill_cli-1.0.11}/tests/unit/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.9
3
+ Version: 1.0.11
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.0.9'
22
- __version_tuple__ = version_tuple = (1, 0, 9)
21
+ __version__ = version = '1.0.11'
22
+ __version_tuple__ = version_tuple = (1, 0, 11)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.9
3
+ Version: 1.0.11
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -193,3 +193,106 @@ class TestDump:
193
193
  def test_dump_quotes_colon_values(self):
194
194
  text = frontmatter.dump({"desc": "a: b"})
195
195
  assert '"a: b"' in text
196
+
197
+
198
+ class TestMutationPrecision:
199
+ """Exact-output tests pinning behaviour that substring `in` checks miss.
200
+
201
+ Each targets a specific mutmut survivor class in frontmatter.py; the
202
+ assertions are equalities (not `in`) so a mutated literal is observable.
203
+ """
204
+
205
+ # --- split() -------------------------------------------------------
206
+ def test_body_lstrip_only_strips_newlines(self):
207
+ # body begins with 'X'; lstrip must strip newlines only, not any char
208
+ _, body = frontmatter.parse("---\nname: a\n---\nXeno body")
209
+ assert body == "Xeno body"
210
+
211
+ # --- _scalar() -----------------------------------------------------
212
+ def test_scalar_only_quote_chars_unwrap(self):
213
+ # a value fenced by a non-quote char stays literal
214
+ assert frontmatter._scalar("XfooX") == "XfooX"
215
+
216
+ # --- _split_commas() ----------------------------------------------
217
+ def test_flow_list_non_quote_char_does_not_open_quote(self):
218
+ meta, _ = frontmatter.parse("---\ntags: [X, y]\n---\n")
219
+ assert meta["tags"] == ["X", "y"] # 'X' is not a quote opener
220
+
221
+ def test_flow_list_quote_midtoken_keeps_buffer(self):
222
+ # a quote in the middle of a token must not reset the accumulated buf
223
+ meta, _ = frontmatter.parse('---\ntags: [x"y"]\n---\n')
224
+ assert meta["tags"] == ['x"y"']
225
+
226
+ def test_flow_list_multichar_unquoted_items(self):
227
+ meta, _ = frontmatter.parse("---\ntags: [abc, def]\n---\n")
228
+ assert meta["tags"] == ["abc", "def"]
229
+
230
+ # --- parse_block(): control flow ----------------------------------
231
+ def test_blank_line_is_skipped_not_terminal(self):
232
+ meta, _ = frontmatter.parse("---\nname: a\n\nversion: 2\n---\n")
233
+ assert meta == {"name": "a", "version": 2} # blank didn't stop parse
234
+
235
+ def test_comment_with_colon_is_ignored(self):
236
+ meta, _ = frontmatter.parse("---\n# note: hi\nname: x\n---\n")
237
+ assert meta == {"name": "x"} # '# note' not a key
238
+
239
+ def test_bare_dash_list_item_is_empty_string(self):
240
+ meta, _ = frontmatter.parse("---\nreq:\n -\n - a\n---\n")
241
+ assert meta["req"] == ["", "a"]
242
+
243
+ def test_continuation_folds_at_single_space_indent(self):
244
+ meta, _ = frontmatter.parse("---\ndesc: hello\n world\n---\n")
245
+ assert meta["desc"] == "hello world" # indent > 0, not > 1
246
+
247
+ def test_indented_colon_line_is_a_key_not_a_fold(self):
248
+ meta, _ = frontmatter.parse("---\ndesc: hello\n key: val\n---\n")
249
+ assert meta["desc"] == "hello"
250
+ assert meta["key"] == "val"
251
+
252
+ def test_unindented_colonless_word_is_skipped_not_terminal(self):
253
+ # a bare word at indent 0 is skipped; parsing continues past it
254
+ meta, _ = frontmatter.parse("---\nname: a\nbareword\nversion: 2\n---\n")
255
+ assert meta == {"name": "a", "version": 2}
256
+
257
+ def test_fold_then_next_key_both_survive(self):
258
+ meta, _ = frontmatter.parse(
259
+ "---\ndesc: hello\n world\nversion: 2\n---\n")
260
+ assert meta["desc"] == "hello world"
261
+ assert meta["version"] == 2 # parsing continued
262
+
263
+ # --- parse_block(): comment stripping -----------------------------
264
+ def test_double_quoted_value_keeps_inline_hash(self):
265
+ meta, _ = frontmatter.parse('---\nname: "foo # bar"\n---\n')
266
+ assert meta["name"] == "foo # bar"
267
+
268
+ def test_comment_strip_splits_on_first_space_hash_only(self):
269
+ meta, _ = frontmatter.parse("---\nname: foo bar # c\n---\n")
270
+ assert meta["name"] == "foo bar" # keeps internal space
271
+
272
+ def test_comment_strip_uses_leftmost_hash(self):
273
+ meta, _ = frontmatter.parse("---\nname: a # b # c\n---\n")
274
+ assert meta["name"] == "a" # split, not rsplit
275
+
276
+ def test_flow_list_needs_both_brackets(self):
277
+ meta, _ = frontmatter.parse("---\ntags: [unclosed\n---\n")
278
+ assert meta["tags"] == "[unclosed" # not parsed as a list
279
+
280
+ # --- dump(): exact lines ------------------------------------------
281
+ def test_dump_list_exact(self):
282
+ assert frontmatter.dump({"tags": ["a"]}) == "---\ntags:\n - a\n---"
283
+
284
+ def test_dump_bool_true_exact(self):
285
+ assert frontmatter.dump({"x": True}) == "---\nx: true\n---"
286
+
287
+ def test_dump_bool_false_exact(self):
288
+ assert frontmatter.dump({"x": False}) == "---\nx: false\n---"
289
+
290
+ def test_dump_none_exact(self):
291
+ assert frontmatter.dump({"x": None}) == "---\nx:\n---"
292
+
293
+ def test_dump_colon_value_quoted_exact(self):
294
+ assert frontmatter.dump({"d": "a: b"}) == '---\nd: "a: b"\n---'
295
+
296
+ def test_dump_escapes_embedded_quote_exact(self):
297
+ # value has a quote AND a colon -> quoted branch escapes the quote
298
+ assert frontmatter.dump({"d": 'a": b'}) == '---\nd: "a\\": b"\n---'
File without changes