oasr 0.4.1__tar.gz → 0.4.2__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 (141) hide show
  1. {oasr-0.4.1 → oasr-0.4.2}/CHANGELOG.md +9 -0
  2. {oasr-0.4.1 → oasr-0.4.2}/PKG-INFO +1 -1
  3. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/.INDEX.md +4 -2
  4. oasr-0.4.2/docs/commands/CLEAN.md +13 -0
  5. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/REGISTRY.md +36 -0
  6. {oasr-0.4.1 → oasr-0.4.2}/pyproject.toml +1 -1
  7. {oasr-0.4.1 → oasr-0.4.2}/src/cli.py +1 -1
  8. oasr-0.4.2/src/commands/clean.py +30 -0
  9. {oasr-0.4.1 → oasr-0.4.2}/src/commands/registry.py +144 -0
  10. {oasr-0.4.1 → oasr-0.4.2}/uv.lock +1 -1
  11. oasr-0.4.1/docs/commands/CLEAN.md +0 -11
  12. oasr-0.4.1/doctor/SKILL.md +0 -35
  13. oasr-0.4.1/doctor/assets/schemas/session.schema.yaml +0 -87
  14. oasr-0.4.1/doctor/assets/schemas/treatment.schema.yaml +0 -70
  15. oasr-0.4.1/doctor/references/00_ROUTER.md +0 -104
  16. oasr-0.4.1/doctor/references/01_SUMMARY.md +0 -44
  17. oasr-0.4.1/doctor/references/02_TRIGGERS.md +0 -40
  18. oasr-0.4.1/doctor/references/03_ALWAYS.md +0 -43
  19. oasr-0.4.1/doctor/references/04_NEVER.md +0 -45
  20. oasr-0.4.1/doctor/references/05_PROCEDURE.md +0 -99
  21. oasr-0.4.1/doctor/references/06_FAILURES.md +0 -77
  22. oasr-0.4.1/doctor/scripts/include/.doctor/session.yaml +0 -11
  23. oasr-0.4.1/doctor/scripts/include/doctor_cli.py +0 -357
  24. oasr-0.4.1/doctor/scripts/include/doctor_parse.py +0 -348
  25. oasr-0.4.1/doctor/scripts/include/pyproject.toml +0 -12
  26. oasr-0.4.1/doctor/scripts/include/uv.lock +0 -78
  27. oasr-0.4.1/doctor/scripts/router_checks.sh +0 -87
  28. oasr-0.4.1/doctor/scripts/skill.ps1 +0 -65
  29. oasr-0.4.1/doctor/scripts/skill.sh +0 -57
  30. oasr-0.4.1/src/commands/clean.py +0 -155
  31. {oasr-0.4.1 → oasr-0.4.2}/.gitignore +0 -0
  32. {oasr-0.4.1 → oasr-0.4.2}/CONTRIBUTING.md +0 -0
  33. {oasr-0.4.1 → oasr-0.4.2}/LICENSE +0 -0
  34. {oasr-0.4.1 → oasr-0.4.2}/NOTICE +0 -0
  35. {oasr-0.4.1 → oasr-0.4.2}/README.md +0 -0
  36. {oasr-0.4.1 → oasr-0.4.2}/docs/.INDEX.md +0 -0
  37. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/adapter.png +0 -0
  38. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/add-glob.png +0 -0
  39. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/add-remote.png +0 -0
  40. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/add.png +0 -0
  41. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/find-add.png +0 -0
  42. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/find.png +0 -0
  43. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/help.png +0 -0
  44. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/info.png +0 -0
  45. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/list.png +0 -0
  46. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/rm-glob.png +0 -0
  47. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/rm.png +0 -0
  48. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/status.png +0 -0
  49. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/sync-update.png +0 -0
  50. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/sync.png +0 -0
  51. {oasr-0.4.1 → oasr-0.4.2}/docs/.images/use.png +0 -0
  52. {oasr-0.4.1 → oasr-0.4.2}/docs/QUICKSTART.md +0 -0
  53. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/ADAPTER.md +0 -0
  54. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/ADD.md +0 -0
  55. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/CLONE.md +0 -0
  56. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/CONFIG.md +0 -0
  57. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/DIFF.md +0 -0
  58. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/EXEC.md +0 -0
  59. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/FIND.md +0 -0
  60. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/HELP.md +0 -0
  61. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/INFO.md +0 -0
  62. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/LIST.md +0 -0
  63. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/RM.md +0 -0
  64. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/ROOT.md +0 -0
  65. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/STATUS.md +0 -0
  66. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/SYNC.md +0 -0
  67. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/UPDATE.md +0 -0
  68. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/USE.md +0 -0
  69. {oasr-0.4.1 → oasr-0.4.2}/docs/commands/VALIDATE.md +0 -0
  70. {oasr-0.4.1 → oasr-0.4.2}/docs/validation/.INDEX.md +0 -0
  71. {oasr-0.4.1 → oasr-0.4.2}/docs/validation/ERRORS.md +0 -0
  72. {oasr-0.4.1 → oasr-0.4.2}/docs/validation/INFO.md +0 -0
  73. {oasr-0.4.1 → oasr-0.4.2}/docs/validation/RULES.md +0 -0
  74. {oasr-0.4.1 → oasr-0.4.2}/docs/validation/WARNINGS.md +0 -0
  75. {oasr-0.4.1 → oasr-0.4.2}/install.ps1 +0 -0
  76. {oasr-0.4.1 → oasr-0.4.2}/install.sh +0 -0
  77. {oasr-0.4.1 → oasr-0.4.2}/llms.txt +0 -0
  78. {oasr-0.4.1 → oasr-0.4.2}/scripts/README.md +0 -0
  79. {oasr-0.4.1 → oasr-0.4.2}/scripts/fix.sh +0 -0
  80. {oasr-0.4.1 → oasr-0.4.2}/scripts/lint.sh +0 -0
  81. {oasr-0.4.1 → oasr-0.4.2}/scripts/test.sh +0 -0
  82. {oasr-0.4.1 → oasr-0.4.2}/src/__init__.py +0 -0
  83. {oasr-0.4.1 → oasr-0.4.2}/src/__main__.py +0 -0
  84. {oasr-0.4.1 → oasr-0.4.2}/src/adapter.py +0 -0
  85. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/__init__.py +0 -0
  86. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/base.py +0 -0
  87. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/claude.py +0 -0
  88. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/codex.py +0 -0
  89. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/copilot.py +0 -0
  90. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/cursor.py +0 -0
  91. {oasr-0.4.1 → oasr-0.4.2}/src/adapters/windsurf.py +0 -0
  92. {oasr-0.4.1 → oasr-0.4.2}/src/agents/__init__.py +0 -0
  93. {oasr-0.4.1 → oasr-0.4.2}/src/agents/base.py +0 -0
  94. {oasr-0.4.1 → oasr-0.4.2}/src/agents/claude.py +0 -0
  95. {oasr-0.4.1 → oasr-0.4.2}/src/agents/codex.py +0 -0
  96. {oasr-0.4.1 → oasr-0.4.2}/src/agents/copilot.py +0 -0
  97. {oasr-0.4.1 → oasr-0.4.2}/src/agents/opencode.py +0 -0
  98. {oasr-0.4.1 → oasr-0.4.2}/src/agents/registry.py +0 -0
  99. {oasr-0.4.1 → oasr-0.4.2}/src/commands/__init__.py +0 -0
  100. {oasr-0.4.1 → oasr-0.4.2}/src/commands/adapter.py +0 -0
  101. {oasr-0.4.1 → oasr-0.4.2}/src/commands/add.py +0 -0
  102. {oasr-0.4.1 → oasr-0.4.2}/src/commands/clone.py +0 -0
  103. {oasr-0.4.1 → oasr-0.4.2}/src/commands/config.py +0 -0
  104. {oasr-0.4.1 → oasr-0.4.2}/src/commands/diff.py +0 -0
  105. {oasr-0.4.1 → oasr-0.4.2}/src/commands/exec.py +0 -0
  106. {oasr-0.4.1 → oasr-0.4.2}/src/commands/find.py +0 -0
  107. {oasr-0.4.1 → oasr-0.4.2}/src/commands/help.py +0 -0
  108. {oasr-0.4.1 → oasr-0.4.2}/src/commands/info.py +0 -0
  109. {oasr-0.4.1 → oasr-0.4.2}/src/commands/list.py +0 -0
  110. {oasr-0.4.1 → oasr-0.4.2}/src/commands/rm.py +0 -0
  111. {oasr-0.4.1 → oasr-0.4.2}/src/commands/status.py +0 -0
  112. {oasr-0.4.1 → oasr-0.4.2}/src/commands/sync.py +0 -0
  113. {oasr-0.4.1 → oasr-0.4.2}/src/commands/update.py +0 -0
  114. {oasr-0.4.1 → oasr-0.4.2}/src/commands/use.py +0 -0
  115. {oasr-0.4.1 → oasr-0.4.2}/src/commands/validate.py +0 -0
  116. {oasr-0.4.1 → oasr-0.4.2}/src/config/__init__.py +0 -0
  117. {oasr-0.4.1 → oasr-0.4.2}/src/config/defaults.py +0 -0
  118. {oasr-0.4.1 → oasr-0.4.2}/src/config/schema.py +0 -0
  119. {oasr-0.4.1 → oasr-0.4.2}/src/discovery.py +0 -0
  120. {oasr-0.4.1 → oasr-0.4.2}/src/manifest.py +0 -0
  121. {oasr-0.4.1 → oasr-0.4.2}/src/registry.py +0 -0
  122. {oasr-0.4.1 → oasr-0.4.2}/src/remote.py +0 -0
  123. {oasr-0.4.1 → oasr-0.4.2}/src/skillcopy/__init__.py +0 -0
  124. {oasr-0.4.1 → oasr-0.4.2}/src/skillcopy/local.py +0 -0
  125. {oasr-0.4.1 → oasr-0.4.2}/src/skillcopy/remote.py +0 -0
  126. {oasr-0.4.1 → oasr-0.4.2}/src/tracking.py +0 -0
  127. {oasr-0.4.1 → oasr-0.4.2}/src/validate.py +0 -0
  128. {oasr-0.4.1 → oasr-0.4.2}/tests/conftest.py +0 -0
  129. {oasr-0.4.1 → oasr-0.4.2}/tests/test_adapters.py +0 -0
  130. {oasr-0.4.1 → oasr-0.4.2}/tests/test_agents.py +0 -0
  131. {oasr-0.4.1 → oasr-0.4.2}/tests/test_clone.py +0 -0
  132. {oasr-0.4.1 → oasr-0.4.2}/tests/test_config.py +0 -0
  133. {oasr-0.4.1 → oasr-0.4.2}/tests/test_config_command.py +0 -0
  134. {oasr-0.4.1 → oasr-0.4.2}/tests/test_copy.py +0 -0
  135. {oasr-0.4.1 → oasr-0.4.2}/tests/test_exec.py +0 -0
  136. {oasr-0.4.1 → oasr-0.4.2}/tests/test_help.py +0 -0
  137. {oasr-0.4.1 → oasr-0.4.2}/tests/test_list.py +0 -0
  138. {oasr-0.4.1 → oasr-0.4.2}/tests/test_multi_skill.py +0 -0
  139. {oasr-0.4.1 → oasr-0.4.2}/tests/test_remote.py +0 -0
  140. {oasr-0.4.1 → oasr-0.4.2}/tests/test_tracking.py +0 -0
  141. {oasr-0.4.1 → oasr-0.4.2}/tests/test_use_glob.py +0 -0
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.4.2] - 2026-02-01
8
+
9
+ ### Added
10
+ - **registry prune subcommand**: Added `oasr registry prune` to align with registry command taxonomy
11
+
12
+ ### Changed
13
+ - **clean command**: Deprecated `oasr clean` in favor of `oasr registry prune` (will be removed in v0.6.0)
14
+ - **documentation**: Updated REGISTRY.md with prune subcommand documentation and usage examples
15
+
7
16
  ## [0.4.1] - 2026-02-01
8
17
 
9
18
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oasr
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: CLI for managing agent skills across IDE integrations
5
5
  Project-URL: Homepage, https://github.com/jgodau/asr
6
6
  Project-URL: Repository, https://github.com/jgodau/asr
@@ -3,7 +3,7 @@
3
3
  ## Core Commands (v0.4.0)
4
4
 
5
5
  - [oasr](ROOT.md) - Global flags and options
6
- - [oasr registry](REGISTRY.md) - Manage skill registry (validate, add, remove, list, sync)
6
+ - [oasr registry](REGISTRY.md) - Manage skill registry (validate, add, remove, list, sync, prune)
7
7
  - [oasr diff](DIFF.md) - Show status of tracked skills
8
8
  - [oasr sync](SYNC.md) - Refresh outdated tracked skills
9
9
  - [oasr config](CONFIG.md) - Manage configuration (NEW in v0.4.0)
@@ -11,7 +11,6 @@
11
11
  - [oasr exec](EXEC.md) - Execute skills as CLI tools (NEW in v0.4.0)
12
12
  - [oasr find](FIND.md) - Find/discover skills in your file system
13
13
  - [oasr validate](VALIDATE.md) - Validate a skill
14
- - [oasr clean](CLEAN.md) - Clean up the registry
15
14
  - [oasr adapter](ADAPTER.md) - Generate IDE/Tooling adapters
16
15
  - [oasr update](UPDATE.md) - Update the `oasr` CLI
17
16
  - [oasr info](INFO.md) - Show detailed information about a skill
@@ -19,6 +18,9 @@
19
18
 
20
19
  ## Deprecated Commands
21
20
 
21
+ ### v0.4.1 Deprecations
22
+ - [oasr clean](CLEAN.md) - **Deprecated**, use `oasr registry prune` instead (will be removed in v0.6.0)
23
+
22
24
  ### v0.4.0 Deprecations
23
25
  - [oasr use](USE.md) - **Deprecated**, use `oasr clone` instead (will be removed in v0.5.0)
24
26
 
@@ -0,0 +1,13 @@
1
+ # `oasr clean` (DEPRECATED)
2
+
3
+ > **⚠️ Warning: This command is deprecated and will be removed in v0.6.0.**
4
+ > Use `oasr registry prune` instead.
5
+
6
+ Remove orphaned manifests and entries for missing skills.
7
+
8
+ ```bash
9
+ oasr clean # Shows deprecation warning
10
+ oasr registry prune # New command (recommended)
11
+ ```
12
+
13
+ This command now delegates to `oasr registry prune`. See [REGISTRY.md](./REGISTRY.md#oasr-registry-prune) for full documentation.
@@ -105,6 +105,40 @@ Syncing remote skills...
105
105
  Synced: 2 skills
106
106
  ```
107
107
 
108
+ ### `oasr registry prune`
109
+
110
+ Clean up corrupted/missing skills and orphaned artifacts:
111
+
112
+ ```bash
113
+ oasr registry prune # Interactive cleanup
114
+ oasr registry prune -y # Skip confirmation
115
+ oasr registry prune --dry-run # Show what would be cleaned
116
+ oasr registry prune --json # JSON output
117
+ ```
118
+
119
+ This command:
120
+ - Removes skills whose source files/URLs are no longer accessible
121
+ - Removes orphaned manifest files not in the registry
122
+ - Requires confirmation unless `-y` flag is used
123
+
124
+ **Example output:**
125
+ ```bash
126
+ $ oasr registry prune
127
+ Checking 3 remote skill(s)...
128
+ ↓ python-analyzer (checking GitHub...)
129
+ ✓ python-analyzer (checked)
130
+
131
+ The following will be cleaned:
132
+
133
+ Skills with missing sources:
134
+ ✗ old-skill (/path/to/missing)
135
+
136
+ Proceed with cleanup? [y/N] y
137
+ Removed skill: old-skill
138
+
139
+ Cleaned 1 skill(s), 0 manifest(s)
140
+ ```
141
+
108
142
  ## Migration from v0.2.0
109
143
 
110
144
  The v0.3.0 CLI taxonomy reorganizes commands under the `registry` subcommand:
@@ -117,3 +151,5 @@ The v0.3.0 CLI taxonomy reorganizes commands under the `registry` subcommand:
117
151
  | `oasr status` | `oasr registry -v` |
118
152
  | `oasr sync` (manifest validation) | `oasr registry` |
119
153
  | `oasr sync --update` (remote sync) | `oasr registry sync` |
154
+
155
+ **v0.4.1 update:** `oasr clean` → `oasr registry prune`
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oasr"
7
- version = "0.4.1"
7
+ version = "0.4.2"
8
8
  description = "CLI for managing agent skills across IDE integrations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
  from commands import adapter, clean, clone, config, diff, exec, find, registry, sync, update, use, validate
14
14
  from commands import help as help_cmd
15
15
 
16
- __version__ = "0.4.1"
16
+ __version__ = "0.4.2"
17
17
 
18
18
 
19
19
  def main(argv: list[str] | None = None) -> int:
@@ -0,0 +1,30 @@
1
+ """`asr clean` command - DEPRECATED, use `oasr registry prune` instead."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
8
+
9
+ def register(subparsers) -> None:
10
+ p = subparsers.add_parser(
11
+ "clean",
12
+ help="(Deprecated) Clean up corrupted/missing skills - use 'oasr registry prune'",
13
+ )
14
+ p.add_argument("-y", "--yes", action="store_true", help="Skip confirmation prompt")
15
+ p.add_argument("--json", action="store_true", help="Output in JSON format")
16
+ p.add_argument("--dry-run", action="store_true", help="Show what would be cleaned without doing it")
17
+ p.set_defaults(func=run)
18
+
19
+
20
+ def run(args: argparse.Namespace) -> int:
21
+ """Delegate to registry prune with deprecation warning."""
22
+ # Show deprecation warning unless --json or --quiet
23
+ if not args.json:
24
+ print("⚠ Warning: 'oasr clean' is deprecated. Use 'oasr registry prune' instead.", file=sys.stderr)
25
+ print(" This command will be removed in v0.6.0.\n", file=sys.stderr)
26
+
27
+ # Delegate to registry prune
28
+ from commands.registry import run_prune
29
+
30
+ return run_prune(args)
@@ -64,6 +64,13 @@ def register(subparsers) -> None:
64
64
  sync_p.add_argument("--config", type=Path, help="Override config file path")
65
65
  sync_p.set_defaults(func=run_sync)
66
66
 
67
+ # registry prune
68
+ prune_p = registry_subparsers.add_parser("prune", help="Clean up corrupted/missing skills and orphaned artifacts")
69
+ prune_p.add_argument("-y", "--yes", action="store_true", help="Skip confirmation prompt")
70
+ prune_p.add_argument("--json", action="store_true", help="Output in JSON format")
71
+ prune_p.add_argument("--dry-run", action="store_true", help="Show what would be cleaned without doing it")
72
+ prune_p.set_defaults(func=run_prune)
73
+
67
74
 
68
75
  def run_validate(args: argparse.Namespace) -> int:
69
76
  """Validate registry manifests (default oasr registry behavior)."""
@@ -301,3 +308,140 @@ def run_sync(args: argparse.Namespace) -> int:
301
308
  print(f"{len(pruned)} skill(s) pruned")
302
309
 
303
310
  return 1 if missing_count > 0 else 0
311
+
312
+
313
+ def run_prune(args: argparse.Namespace) -> int:
314
+ """Clean up corrupted/missing skills and orphaned artifacts (oasr registry prune)."""
315
+ from manifest import delete_manifest, list_manifests
316
+
317
+ entries = load_registry()
318
+ registered_names = {e.name for e in entries}
319
+ manifest_names = set(list_manifests())
320
+
321
+ to_remove_skills = []
322
+ to_remove_manifests = []
323
+
324
+ # Check for remote skills and show progress header
325
+ remote_count = 0
326
+ for entry in entries:
327
+ manifest = load_manifest(entry.name)
328
+ if manifest and is_remote_source(manifest.source_path):
329
+ remote_count += 1
330
+
331
+ if remote_count > 0 and not args.json:
332
+ print(f"Checking {remote_count} remote skill(s)...", file=sys.stderr)
333
+
334
+ for entry in entries:
335
+ manifest = load_manifest(entry.name)
336
+ if manifest:
337
+ # Show progress for remote skills
338
+ is_remote = is_remote_source(manifest.source_path)
339
+ if is_remote and not args.json:
340
+ platform = (
341
+ "GitHub"
342
+ if "github.com" in manifest.source_path
343
+ else "GitLab"
344
+ if "gitlab.com" in manifest.source_path
345
+ else "remote"
346
+ )
347
+ print(f" ↓ {entry.name} (checking {platform}...)", file=sys.stderr, flush=True)
348
+
349
+ status = check_manifest(manifest)
350
+
351
+ if is_remote and not args.json:
352
+ print(f" ✓ {entry.name} (checked)", file=sys.stderr)
353
+
354
+ if status.status == "missing":
355
+ to_remove_skills.append(
356
+ {
357
+ "name": entry.name,
358
+ "reason": "source missing",
359
+ "path": entry.path,
360
+ }
361
+ )
362
+
363
+ orphaned = manifest_names - registered_names
364
+ for name in orphaned:
365
+ to_remove_manifests.append(
366
+ {
367
+ "name": name,
368
+ "reason": "orphaned manifest (not in registry)",
369
+ }
370
+ )
371
+
372
+ if not to_remove_skills and not to_remove_manifests:
373
+ if args.json:
374
+ print(json.dumps({"cleaned": 0, "message": "nothing to clean"}))
375
+ else:
376
+ print("Nothing to clean.")
377
+ return 0
378
+
379
+ if args.json:
380
+ result = {
381
+ "skills_to_remove": to_remove_skills,
382
+ "manifests_to_remove": to_remove_manifests,
383
+ "dry_run": args.dry_run,
384
+ }
385
+ if not args.dry_run and not args.yes:
386
+ result["requires_confirmation"] = True
387
+ print(json.dumps(result, indent=2))
388
+ if args.dry_run:
389
+ return 0
390
+ else:
391
+ print("The following will be cleaned:\n")
392
+
393
+ if to_remove_skills:
394
+ print("Skills with missing sources:")
395
+ for s in to_remove_skills:
396
+ print(f" ✗ {s['name']} ({s['path']})")
397
+
398
+ if to_remove_manifests:
399
+ print("\nOrphaned manifests:")
400
+ for m in to_remove_manifests:
401
+ print(f" ✗ {m['name']}")
402
+
403
+ print()
404
+
405
+ if args.dry_run:
406
+ print("(dry run - no changes made)")
407
+ return 0
408
+
409
+ if not args.yes and not args.json:
410
+ try:
411
+ response = input("Proceed with cleanup? [y/N] ").strip().lower()
412
+ if response not in ("y", "yes"):
413
+ print("Aborted.")
414
+ return 1
415
+ except (EOFError, KeyboardInterrupt):
416
+ print("\nAborted.")
417
+ return 1
418
+
419
+ removed_skills = []
420
+ removed_manifests = []
421
+
422
+ for s in to_remove_skills:
423
+ remove_skill(s["name"])
424
+ removed_skills.append(s["name"])
425
+
426
+ for m in to_remove_manifests:
427
+ delete_manifest(m["name"])
428
+ removed_manifests.append(m["name"])
429
+
430
+ if args.json:
431
+ print(
432
+ json.dumps(
433
+ {
434
+ "removed_skills": removed_skills,
435
+ "removed_manifests": removed_manifests,
436
+ },
437
+ indent=2,
438
+ )
439
+ )
440
+ else:
441
+ for name in removed_skills:
442
+ print(f"Removed skill: {name}")
443
+ for name in removed_manifests:
444
+ print(f"Removed manifest: {name}")
445
+ print(f"\nCleaned {len(removed_skills)} skill(s), {len(removed_manifests)} manifest(s)")
446
+
447
+ return 0
@@ -138,7 +138,7 @@ wheels = [
138
138
 
139
139
  [[package]]
140
140
  name = "oasr"
141
- version = "0.4.0"
141
+ version = "0.4.2"
142
142
  source = { editable = "." }
143
143
  dependencies = [
144
144
  { name = "pyyaml" },
@@ -1,11 +0,0 @@
1
- # `oasr clean`
2
-
3
- Remove orphaned manifests and entries for missing skills.
4
-
5
- ```bash
6
- oasr clean
7
- oasr clean --dry-run
8
- ```
9
-
10
- > **note**
11
- > The same behaviour can be achieved using `oasr sync --prune`
@@ -1,35 +0,0 @@
1
- ---
2
- name: doctor
3
- license: MIT
4
- description: 'Diagnoses software failures by combining deterministic evidence gathering
5
- with agent judgment. Models failures as medical cases. Idempotent — run repeatedly
6
- until confident diagnosis, then generate schema-based treatment.
7
-
8
- '
9
- metadata:
10
- author: Jordan Godau
11
- version: 0.2.0
12
- references:
13
- - 00_ROUTER.md
14
- - 01_SUMMARY.md
15
- - 02_TRIGGERS.md
16
- - 03_ALWAYS.md
17
- - 04_NEVER.md
18
- - 05_PROCEDURE.md
19
- - 06_FAILURES.md
20
- keywords:
21
- - diagnose
22
- - debug
23
- - investigate
24
- - evidence
25
- - hypothesis
26
- - treatment
27
- oasr:
28
- hash: sha256:f9fda45b7797923e9379e36c1b519c40b09f05f78bfa172a9d006c14b7283535
29
- source: /home/jgodau/work/personal/skills/doctor/doctor
30
- synced: '2026-02-01T06:35:54.685306Z'
31
- ---
32
-
33
- # INSTRUCTIONS
34
-
35
- 1. Refer to `metadata.references`.
@@ -1,87 +0,0 @@
1
- # Doctor Session Schema
2
- # Artifact: .doctor/session.yaml
3
-
4
- type: object
5
- required:
6
- - status
7
- - created_at
8
-
9
- properties:
10
- status:
11
- type: string
12
- enum: [investigating, diagnosed, treated, abandoned]
13
- description: Current session status
14
-
15
- created_at:
16
- type: string
17
- format: date-time
18
- description: RFC3339 UTC timestamp
19
-
20
- updated_at:
21
- type: string
22
- format: date-time
23
- description: RFC3339 UTC timestamp of last update
24
-
25
- patient:
26
- type: string
27
- description: Repository or system name
28
-
29
- symptoms:
30
- type: array
31
- items:
32
- type: object
33
- properties:
34
- description:
35
- type: string
36
- category:
37
- type: string
38
- enum: [error, timeout, crash, wrong_output, performance, unknown]
39
- evidence:
40
- type: string
41
- description: Observed symptoms
42
-
43
- hypotheses:
44
- type: array
45
- items:
46
- type: object
47
- properties:
48
- description:
49
- type: string
50
- confidence:
51
- type: integer
52
- minimum: 0
53
- maximum: 100
54
- evidence_for:
55
- type: array
56
- items:
57
- type: string
58
- evidence_against:
59
- type: array
60
- items:
61
- type: string
62
- falsifiable_by:
63
- type: string
64
- description: Working hypotheses with confidence
65
-
66
- diagnosis:
67
- type: object
68
- properties:
69
- summary:
70
- type: string
71
- confidence:
72
- type: integer
73
- minimum: 0
74
- maximum: 100
75
- root_cause:
76
- type: string
77
- contributing_factors:
78
- type: array
79
- items:
80
- type: string
81
- description: Final diagnosis (when confident)
82
-
83
- evidence_files:
84
- type: array
85
- items:
86
- type: string
87
- description: Paths to evidence snapshots in .doctor/evidence/
@@ -1,70 +0,0 @@
1
- # Treatment Plan Schema
2
- # Artifact: .doctor/treatment.md (generated from this schema)
3
-
4
- type: object
5
- required:
6
- - diagnosis_summary
7
- - confidence
8
- - options
9
-
10
- properties:
11
- diagnosis_summary:
12
- type: string
13
- description: One-line diagnosis
14
-
15
- confidence:
16
- type: integer
17
- minimum: 0
18
- maximum: 100
19
- description: Diagnosis confidence percentage
20
-
21
- root_cause:
22
- type: string
23
- description: Identified root cause
24
-
25
- options:
26
- type: array
27
- minItems: 1
28
- items:
29
- type: object
30
- required:
31
- - name
32
- - description
33
- - risk
34
- properties:
35
- name:
36
- type: string
37
- description: Short option name
38
- description:
39
- type: string
40
- description: What this option does
41
- risk:
42
- type: string
43
- enum: [low, medium, high]
44
- effort:
45
- type: string
46
- enum: [trivial, small, medium, large]
47
- reversible:
48
- type: boolean
49
- steps:
50
- type: array
51
- items:
52
- type: string
53
- description: Ordered implementation steps
54
- description: Treatment options (at least one required)
55
-
56
- recommended:
57
- type: string
58
- description: Name of recommended option
59
-
60
- caveats:
61
- type: array
62
- items:
63
- type: string
64
- description: Warnings or considerations
65
-
66
- follow_up:
67
- type: array
68
- items:
69
- type: string
70
- description: Suggested follow-up actions
@@ -1,104 +0,0 @@
1
- ---
2
- description: Conditional dispatch for which reference files to load.
3
- index:
4
- - Preconditions
5
- - Routes
6
- ---
7
-
8
- # Router
9
-
10
- ---
11
-
12
- ## Preconditions
13
-
14
- ### Execute
15
-
16
- 1. scripts/router_checks.sh --check session
17
- 2. scripts/router_checks.sh --check treatment
18
-
19
- ### Fresh Start Override
20
-
21
- If the user explicitly requests a fresh start, force the router into the `default` route by making the checks fail deterministically:
22
-
23
- 1. Set `DOCTOR_FRESH_START=1` for the router check invocation, **or**
24
- 2. Pass `--fresh-start` to `scripts/router_checks.sh`
25
-
26
- ### Check
27
-
28
- - If user explicitly requests a fresh start, treat as `default` even if artifacts exist.
29
-
30
- ---
31
-
32
- ## Routes
33
-
34
- 1. treatment-complete
35
- 2. session-active
36
- 3. default
37
-
38
- ---
39
-
40
- ### treatment-complete
41
-
42
- Resume after a treatment plan has already been generated.
43
-
44
- **When:**
45
-
46
- - `scripts/router_checks.sh --check treatment` exits 0
47
-
48
- **Read:**
49
-
50
- 1. 01_SUMMARY.md
51
-
52
- **Ignore:**
53
-
54
- 1. 02_TRIGGERS.md
55
- 2. 03_ALWAYS.md
56
- 3. 04_NEVER.md
57
- 4. 05_PROCEDURE.md
58
- 5. 06_FAILURES.md
59
-
60
- ---
61
-
62
- ### session-active
63
-
64
- Resume mid-investigation when a session exists but treatment is not yet generated.
65
-
66
- **When:**
67
-
68
- - `scripts/router_checks.sh --check session` exits 0
69
- - `scripts/router_checks.sh --check treatment` exits non-zero
70
-
71
- **Read:**
72
-
73
- 1. 01_SUMMARY.md
74
- 2. 03_ALWAYS.md
75
- 3. 05_PROCEDURE.md
76
-
77
- **Ignore:**
78
-
79
- 1. 02_TRIGGERS.md
80
- 2. 04_NEVER.md
81
- 3. 06_FAILURES.md
82
-
83
- ---
84
-
85
- ### default
86
-
87
- Fresh invocation — read all references in order.
88
-
89
- **When:**
90
-
91
- - No other route matches
92
-
93
- **Read:**
94
-
95
- 1. 01_SUMMARY.md
96
- 2. 02_TRIGGERS.md
97
- 3. 03_ALWAYS.md
98
- 4. 04_NEVER.md
99
- 5. 05_PROCEDURE.md
100
- 6. 06_FAILURES.md
101
-
102
- **Ignore:**
103
-
104
- (none)
@@ -1,44 +0,0 @@
1
- ---
2
- description: What this skill is and is not.
3
- index:
4
- - What It Does
5
- - What Problems It Solves
6
- - What It Is Not
7
- - Key Invariant
8
- - Artifact Location
9
- ---
10
-
11
- # Summary
12
-
13
- The **doctor** skill diagnoses software failures by combining deterministic evidence gathering with agent judgment.
14
-
15
- ## What It Does
16
-
17
- - Models software failures as medical cases
18
- - Gathers evidence through parameterized search (agent provides terms, script returns matches)
19
- - Tracks symptoms, hypotheses, and confidence levels
20
- - Produces schema-based treatment plans when diagnosis is confident
21
-
22
- ## What Problems It Solves
23
-
24
- - Prevents premature action on incomplete understanding
25
- - Separates observation from interpretation
26
- - Makes uncertainty explicit (confidence percentages)
27
- - Creates reviewable artifacts for handoff
28
-
29
- ## What It Is Not
30
-
31
- - Not a fix-it skill (produces plans, not changes)
32
- - Not a sequential pipeline (idempotent, run until confident)
33
- - Not purely deterministic (balances scripts with agent reasoning)
34
-
35
- ## Key Invariant
36
-
37
- **Execution means investigation, not implementation.** The skill gathers evidence and produces treatment plans. It does not execute fixes.
38
-
39
- ## Artifact Location
40
-
41
- All artifacts stored in `.doctor/`:
42
- - `session.yaml` — Current diagnosis state
43
- - `evidence/` — Evidence snapshots
44
- - `treatment.md` — Generated treatment plan