devrites 1.19.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 (232) hide show
  1. package/.claude-plugin/marketplace.json +24 -0
  2. package/.claude-plugin/plugin.json +43 -0
  3. package/CHANGELOG.md +391 -0
  4. package/LICENSE +56 -0
  5. package/NOTICE.md +18 -0
  6. package/README.md +582 -0
  7. package/SECURITY.md +193 -0
  8. package/bin/devrites.mjs +100 -0
  9. package/docs/architecture.md +272 -0
  10. package/docs/cli-mcp.md +57 -0
  11. package/docs/command-map.md +143 -0
  12. package/docs/flow.md +360 -0
  13. package/docs/release.md +29 -0
  14. package/docs/skills.md +214 -0
  15. package/docs/usage.md +325 -0
  16. package/install.sh +359 -0
  17. package/mcp/devrites-mcp.mjs +103 -0
  18. package/pack/.claude/agents/devrites-code-reviewer.md +50 -0
  19. package/pack/.claude/agents/devrites-doubt-reviewer.md +55 -0
  20. package/pack/.claude/agents/devrites-frontend-reviewer.md +52 -0
  21. package/pack/.claude/agents/devrites-performance-reviewer.md +47 -0
  22. package/pack/.claude/agents/devrites-plan-reviewer.md +79 -0
  23. package/pack/.claude/agents/devrites-security-auditor.md +53 -0
  24. package/pack/.claude/agents/devrites-simplifier-reviewer.md +75 -0
  25. package/pack/.claude/agents/devrites-slice-wright.md +181 -0
  26. package/pack/.claude/agents/devrites-spec-reviewer.md +72 -0
  27. package/pack/.claude/agents/devrites-strategy-reviewer.md +62 -0
  28. package/pack/.claude/agents/devrites-test-analyst.md +47 -0
  29. package/pack/.claude/hooks/devrites-a1-guard.sh +81 -0
  30. package/pack/.claude/hooks/devrites-allow.sh +44 -0
  31. package/pack/.claude/hooks/devrites-cursor.sh +28 -0
  32. package/pack/.claude/hooks/devrites-orient.sh +53 -0
  33. package/pack/.claude/hooks/devrites-redwatch.sh +39 -0
  34. package/pack/.claude/hooks/devrites-refresh-indexes.sh +127 -0
  35. package/pack/.claude/hooks/devrites-reviewer-readonly.sh +28 -0
  36. package/pack/.claude/hooks/devrites-statusline.sh +18 -0
  37. package/pack/.claude/hooks/devrites-stop-gate.sh +45 -0
  38. package/pack/.claude/hooks/devrites-wright-scope.sh +35 -0
  39. package/pack/.claude/hooks/hooks.json +52 -0
  40. package/pack/.claude/rules/README.md +48 -0
  41. package/pack/.claude/rules/afk-hitl.md +245 -0
  42. package/pack/.claude/rules/agents.md +98 -0
  43. package/pack/.claude/rules/anti-patterns.md +48 -0
  44. package/pack/.claude/rules/code-review.md +38 -0
  45. package/pack/.claude/rules/coding-style.md +55 -0
  46. package/pack/.claude/rules/context-hygiene.md +97 -0
  47. package/pack/.claude/rules/core.md +119 -0
  48. package/pack/.claude/rules/development-workflow.md +40 -0
  49. package/pack/.claude/rules/documentation.md +27 -0
  50. package/pack/.claude/rules/error-handling.md +33 -0
  51. package/pack/.claude/rules/git-workflow.md +35 -0
  52. package/pack/.claude/rules/hooks.md +38 -0
  53. package/pack/.claude/rules/patterns.md +45 -0
  54. package/pack/.claude/rules/performance.md +27 -0
  55. package/pack/.claude/rules/prose-style.md +101 -0
  56. package/pack/.claude/rules/security.md +63 -0
  57. package/pack/.claude/rules/testing.md +88 -0
  58. package/pack/.claude/rules/tooling.md +72 -0
  59. package/pack/.claude/settings.json +53 -0
  60. package/pack/.claude/skills/devrites-api-interface/SKILL.md +45 -0
  61. package/pack/.claude/skills/devrites-audit/SKILL.md +73 -0
  62. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +38 -0
  63. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +50 -0
  64. package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +47 -0
  65. package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +17 -0
  66. package/pack/.claude/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
  67. package/pack/.claude/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
  68. package/pack/.claude/skills/devrites-debug-recovery/reference/regression-test.md +31 -0
  69. package/pack/.claude/skills/devrites-doubt/SKILL.md +75 -0
  70. package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +96 -0
  71. package/pack/.claude/skills/devrites-frontend-craft/reference/craft.md +59 -0
  72. package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +116 -0
  73. package/pack/.claude/skills/devrites-frontend-craft/reference/fullstack.md +45 -0
  74. package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +215 -0
  75. package/pack/.claude/skills/devrites-frontend-craft/reference/reuse-first.md +59 -0
  76. package/pack/.claude/skills/devrites-frontend-craft/reference/shape.md +60 -0
  77. package/pack/.claude/skills/devrites-interview/SKILL.md +81 -0
  78. package/pack/.claude/skills/devrites-lib/SKILL.md +76 -0
  79. package/pack/.claude/skills/devrites-lib/scripts/analyze.sh +78 -0
  80. package/pack/.claude/skills/devrites-lib/scripts/check-acceptance.sh +75 -0
  81. package/pack/.claude/skills/devrites-lib/scripts/close-out.sh +47 -0
  82. package/pack/.claude/skills/devrites-lib/scripts/conventions.py +273 -0
  83. package/pack/.claude/skills/devrites-lib/scripts/coverage.sh +51 -0
  84. package/pack/.claude/skills/devrites-lib/scripts/devrites.sh +69 -0
  85. package/pack/.claude/skills/devrites-lib/scripts/doctor.sh +92 -0
  86. package/pack/.claude/skills/devrites-lib/scripts/evidence-fresh.sh +63 -0
  87. package/pack/.claude/skills/devrites-lib/scripts/footprint.sh +45 -0
  88. package/pack/.claude/skills/devrites-lib/scripts/learnings.sh +74 -0
  89. package/pack/.claude/skills/devrites-lib/scripts/mutation-gate.sh +52 -0
  90. package/pack/.claude/skills/devrites-lib/scripts/package-existence.sh +68 -0
  91. package/pack/.claude/skills/devrites-lib/scripts/preamble.sh +76 -0
  92. package/pack/.claude/skills/devrites-lib/scripts/progress.sh +103 -0
  93. package/pack/.claude/skills/devrites-lib/scripts/readiness.sh +62 -0
  94. package/pack/.claude/skills/devrites-lib/scripts/reconcile.sh +123 -0
  95. package/pack/.claude/skills/devrites-lib/scripts/resolve.sh +279 -0
  96. package/pack/.claude/skills/devrites-lib/scripts/stuck.sh +67 -0
  97. package/pack/.claude/skills/devrites-lib/scripts/test-integrity.sh +87 -0
  98. package/pack/.claude/skills/devrites-lib/scripts/tick-afk.sh +52 -0
  99. package/pack/.claude/skills/devrites-prose-craft/SKILL.md +105 -0
  100. package/pack/.claude/skills/devrites-prose-craft/reference/banned-phrases.md +95 -0
  101. package/pack/.claude/skills/devrites-prose-craft/reference/examples.md +88 -0
  102. package/pack/.claude/skills/devrites-prose-craft/reference/structures.md +134 -0
  103. package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +54 -0
  104. package/pack/.claude/skills/devrites-source-driven/SKILL.md +36 -0
  105. package/pack/.claude/skills/devrites-ux-shape/SKILL.md +121 -0
  106. package/pack/.claude/skills/devrites-ux-shape/reference/brief-template.md +93 -0
  107. package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
  108. package/pack/.claude/skills/rite/SKILL.md +135 -0
  109. package/pack/.claude/skills/rite/reference/menu.md +32 -0
  110. package/pack/.claude/skills/rite-adopt/SKILL.md +83 -0
  111. package/pack/.claude/skills/rite-adopt/reference/adoption.md +58 -0
  112. package/pack/.claude/skills/rite-adopt/reference/anti-patterns.md +19 -0
  113. package/pack/.claude/skills/rite-autocomplete/SKILL.md +96 -0
  114. package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +35 -0
  115. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +54 -0
  116. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +59 -0
  117. package/pack/.claude/skills/rite-build/SKILL.md +261 -0
  118. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +145 -0
  119. package/pack/.claude/skills/rite-build/reference/anti-patterns.md +25 -0
  120. package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +149 -0
  121. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +32 -0
  122. package/pack/.claude/skills/rite-build/reference/frontend-trigger.md +39 -0
  123. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +38 -0
  124. package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +43 -0
  125. package/pack/.claude/skills/rite-build/reference/tdd.md +26 -0
  126. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +115 -0
  127. package/pack/.claude/skills/rite-define/SKILL.md +157 -0
  128. package/pack/.claude/skills/rite-define/reference/anti-patterns.md +25 -0
  129. package/pack/.claude/skills/rite-define/reference/gates.md +152 -0
  130. package/pack/.claude/skills/rite-define/reference/plan-template.md +65 -0
  131. package/pack/.claude/skills/rite-doctor/SKILL.md +50 -0
  132. package/pack/.claude/skills/rite-frame/SKILL.md +116 -0
  133. package/pack/.claude/skills/rite-frame/reference/failure-modes.md +68 -0
  134. package/pack/.claude/skills/rite-handoff/SKILL.md +95 -0
  135. package/pack/.claude/skills/rite-handoff/reference/handoff-template.md +34 -0
  136. package/pack/.claude/skills/rite-learn/SKILL.md +82 -0
  137. package/pack/.claude/skills/rite-plan/SKILL.md +82 -0
  138. package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +24 -0
  139. package/pack/.claude/skills/rite-plan/reference/dependency-graph.md +33 -0
  140. package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +42 -0
  141. package/pack/.claude/skills/rite-plan/reference/slicing.md +52 -0
  142. package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +34 -0
  143. package/pack/.claude/skills/rite-polish/SKILL.md +90 -0
  144. package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +177 -0
  145. package/pack/.claude/skills/rite-polish/reference/anti-patterns.md +27 -0
  146. package/pack/.claude/skills/rite-polish/reference/backend-polish.md +80 -0
  147. package/pack/.claude/skills/rite-polish/reference/browser-polish-evidence.md +31 -0
  148. package/pack/.claude/skills/rite-polish/reference/code.md +85 -0
  149. package/pack/.claude/skills/rite-polish/reference/design-system-discovery.md +35 -0
  150. package/pack/.claude/skills/rite-polish/reference/harden-checklist.md +109 -0
  151. package/pack/.claude/skills/rite-polish/reference/ui.md +136 -0
  152. package/pack/.claude/skills/rite-pressure-test/SKILL.md +43 -0
  153. package/pack/.claude/skills/rite-prototype/SKILL.md +87 -0
  154. package/pack/.claude/skills/rite-prove/SKILL.md +120 -0
  155. package/pack/.claude/skills/rite-prove/reference/anti-patterns.md +25 -0
  156. package/pack/.claude/skills/rite-prove/reference/browser-proof.md +26 -0
  157. package/pack/.claude/skills/rite-prove/reference/failure-triage.md +25 -0
  158. package/pack/.claude/skills/rite-prove/reference/proof-ladder.md +26 -0
  159. package/pack/.claude/skills/rite-prove/reference/test-command-discovery.md +30 -0
  160. package/pack/.claude/skills/rite-quick/SKILL.md +81 -0
  161. package/pack/.claude/skills/rite-resolve/SKILL.md +113 -0
  162. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +114 -0
  163. package/pack/.claude/skills/rite-review/SKILL.md +170 -0
  164. package/pack/.claude/skills/rite-review/reference/anti-patterns.md +32 -0
  165. package/pack/.claude/skills/rite-review/reference/cognitive-load.md +90 -0
  166. package/pack/.claude/skills/rite-review/reference/feature-scoped-review.md +26 -0
  167. package/pack/.claude/skills/rite-review/reference/five-axis-review.md +46 -0
  168. package/pack/.claude/skills/rite-review/reference/nielsen-heuristics.md +130 -0
  169. package/pack/.claude/skills/rite-review/reference/parallel-dispatch.md +62 -0
  170. package/pack/.claude/skills/rite-review/reference/performance-review.md +28 -0
  171. package/pack/.claude/skills/rite-review/reference/security-review.md +32 -0
  172. package/pack/.claude/skills/rite-seal/SKILL.md +183 -0
  173. package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +27 -0
  174. package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +63 -0
  175. package/pack/.claude/skills/rite-seal/reference/final-evidence.md +72 -0
  176. package/pack/.claude/skills/rite-seal/reference/go-no-go.md +37 -0
  177. package/pack/.claude/skills/rite-seal/reference/parallel-dispatch.md +69 -0
  178. package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +30 -0
  179. package/pack/.claude/skills/rite-seal/reference/seal-template.md +36 -0
  180. package/pack/.claude/skills/rite-ship/SKILL.md +120 -0
  181. package/pack/.claude/skills/rite-ship/reference/anti-patterns.md +25 -0
  182. package/pack/.claude/skills/rite-ship/reference/close-out.md +31 -0
  183. package/pack/.claude/skills/rite-ship/reference/design-memory.md +120 -0
  184. package/pack/.claude/skills/rite-ship/reference/git-ship.md +42 -0
  185. package/pack/.claude/skills/rite-ship/reference/ship-template.md +33 -0
  186. package/pack/.claude/skills/rite-spec/SKILL.md +126 -0
  187. package/pack/.claude/skills/rite-spec/reference/acceptance-criteria.md +31 -0
  188. package/pack/.claude/skills/rite-spec/reference/anti-patterns.md +25 -0
  189. package/pack/.claude/skills/rite-spec/reference/interview-patterns.md +56 -0
  190. package/pack/.claude/skills/rite-spec/reference/investigation.md +64 -0
  191. package/pack/.claude/skills/rite-spec/reference/question-protocol.md +61 -0
  192. package/pack/.claude/skills/rite-spec/reference/references-intake.md +57 -0
  193. package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +73 -0
  194. package/pack/.claude/skills/rite-spec/reference/spec-template.md +124 -0
  195. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +159 -0
  196. package/pack/.claude/skills/rite-status/SKILL.md +101 -0
  197. package/pack/.claude/skills/rite-temper/SKILL.md +119 -0
  198. package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +29 -0
  199. package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +65 -0
  200. package/pack/.claude/skills/rite-temper/reference/scope-modes.md +53 -0
  201. package/pack/.claude/skills/rite-temper/reference/significance.md +46 -0
  202. package/pack/.claude/skills/rite-temper/reference/strategy-template.md +90 -0
  203. package/pack/.claude/skills/rite-vet/SKILL.md +155 -0
  204. package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +29 -0
  205. package/pack/.claude/skills/rite-vet/reference/artifacts.md +135 -0
  206. package/pack/.claude/skills/rite-vet/reference/cross-model.md +41 -0
  207. package/pack/.claude/skills/rite-vet/reference/depth.md +53 -0
  208. package/pack/.claude/skills/rite-vet/reference/eng-lenses.md +48 -0
  209. package/pack/.claude/skills/rite-vet/reference/review-axes.md +167 -0
  210. package/pack/.claude/skills/rite-zoom-out/SKILL.md +75 -0
  211. package/package.json +68 -0
  212. package/scripts/build-release-tarball.sh +74 -0
  213. package/scripts/check-cross-refs.py +121 -0
  214. package/scripts/check-no-global-writes.sh +44 -0
  215. package/scripts/check-rule-uniqueness.sh +73 -0
  216. package/scripts/devrites-detect.sh +175 -0
  217. package/scripts/eval-runner.py +273 -0
  218. package/scripts/grade-feature.sh +104 -0
  219. package/scripts/install-lib.sh +83 -0
  220. package/scripts/pin.sh +166 -0
  221. package/scripts/render-eval-summary.py +48 -0
  222. package/scripts/run-evals.sh +149 -0
  223. package/scripts/run-outcome-evals.sh +49 -0
  224. package/scripts/scan-pack-security.py +209 -0
  225. package/scripts/scan-supply-chain-iocs.py +127 -0
  226. package/scripts/supply-chain-iocs.json +11 -0
  227. package/scripts/sync-version.sh +56 -0
  228. package/scripts/validate-frontmatter.py +149 -0
  229. package/scripts/validate-workflow-security.py +86 -0
  230. package/scripts/validate.sh +234 -0
  231. package/uninstall.sh +137 -0
  232. package/update.sh +196 -0
package/uninstall.sh ADDED
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env bash
2
+ # uninstall.sh — remove DevRites from a project. Removes ONLY the files listed in
3
+ # .claude/devrites.manifest (plus the manifest itself) and prunes dirs left empty.
4
+ # Never touches your feature data in .devrites/work/.
5
+ #
6
+ # ./uninstall.sh uninstall from the current directory
7
+ # ./uninstall.sh --target DIR uninstall from DIR
8
+ # ./uninstall.sh --dry-run show what would be removed, change nothing
9
+ #
10
+ # Network uninstall (no git clone needed):
11
+ # curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/uninstall.sh | bash
12
+ # curl -fsSL https://raw.githubusercontent.com/ViktorsBaikers/DevRites/main/uninstall.sh | bash -s -- --target /path
13
+
14
+ set -u
15
+ SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" 2>/dev/null && pwd -P)" || SELF_DIR=""
16
+
17
+ # ---- bootstrap (curl | bash) --------------------------------------------
18
+ # Same pattern as install.sh: when piped from curl there are no sibling files,
19
+ # so download a tarball and re-exec.
20
+ DEVRITES_REPO="${DEVRITES_REPO:-ViktorsBaikers/DevRites}"
21
+ DEVRITES_REF="${DEVRITES_REF:-}"
22
+ if [ -z "$SELF_DIR" ] || [ ! -r "$SELF_DIR/scripts/install-lib.sh" ]; then
23
+ if [ "${DEVRITES_BOOTSTRAPPED:-0}" = "1" ]; then
24
+ echo "error: bootstrap re-exec did not find scripts/install-lib.sh — aborting." >&2
25
+ exit 1
26
+ fi
27
+ command -v curl >/dev/null 2>&1 || { echo "error: curl is required for the network uninstaller." >&2; exit 1; }
28
+ command -v tar >/dev/null 2>&1 || { echo "error: tar is required for the network uninstaller." >&2; exit 1; }
29
+
30
+ BOOT_TMP="$(mktemp -d 2>/dev/null || echo "${TMPDIR:-/tmp}/devrites-bootstrap.$$")"
31
+ if [ -n "$DEVRITES_REF" ]; then
32
+ BOOT_TAG="$DEVRITES_REF"
33
+ else
34
+ BOOT_TAG="$(curl -fsSL "https://api.github.com/repos/$DEVRITES_REPO/releases/latest" 2>/dev/null \
35
+ | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)"
36
+ fi
37
+ BOOT_DOWNLOADED=0
38
+ if [ -n "$BOOT_TAG" ]; then
39
+ BOOT_URL="https://github.com/$DEVRITES_REPO/releases/download/$BOOT_TAG/devrites-$BOOT_TAG.tar.gz"
40
+ curl -fsSL -o "$BOOT_TMP/devrites.tar.gz" "$BOOT_URL" 2>/dev/null && BOOT_DOWNLOADED=1
41
+ if [ "$BOOT_DOWNLOADED" -ne 1 ]; then
42
+ BOOT_URL="https://github.com/$DEVRITES_REPO/archive/refs/tags/$BOOT_TAG.tar.gz"
43
+ curl -fsSL -o "$BOOT_TMP/devrites.tar.gz" "$BOOT_URL" 2>/dev/null && BOOT_DOWNLOADED=1
44
+ fi
45
+ fi
46
+ if [ "$BOOT_DOWNLOADED" -ne 1 ]; then
47
+ BOOT_URL="https://github.com/$DEVRITES_REPO/archive/refs/heads/main.tar.gz"
48
+ curl -fsSL -o "$BOOT_TMP/devrites.tar.gz" "$BOOT_URL" || { echo "error: could not download DevRites from $BOOT_URL" >&2; exit 1; }
49
+ fi
50
+ tar -C "$BOOT_TMP" -xzf "$BOOT_TMP/devrites.tar.gz" || { echo "error: could not extract DevRites tarball" >&2; exit 1; }
51
+ BOOT_BUNDLE="$(find "$BOOT_TMP" -mindepth 1 -maxdepth 1 -type d | head -n1)"
52
+ [ -n "$BOOT_BUNDLE" ] && [ -f "$BOOT_BUNDLE/uninstall.sh" ] || { echo "error: extracted bundle is missing uninstall.sh" >&2; exit 1; }
53
+ chmod +x "$BOOT_BUNDLE/uninstall.sh" "$BOOT_BUNDLE"/scripts/*.sh 2>/dev/null || true
54
+ export DEVRITES_BOOTSTRAPPED=1
55
+ exec bash "$BOOT_BUNDLE/uninstall.sh" "$@"
56
+ fi
57
+
58
+ . "$SELF_DIR/scripts/install-lib.sh"
59
+
60
+ TARGET="$PWD"
61
+ DRYRUN=0
62
+ while [ $# -gt 0 ]; do
63
+ case "$1" in
64
+ --target) shift; [ $# -gt 0 ] || dr_die "--target needs a directory"; TARGET="$1" ;;
65
+ --target=*) TARGET="${1#*=}" ;;
66
+ --dry-run) DRYRUN=1 ;;
67
+ -h|--help) sed -n '2,11p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
68
+ *) dr_die "unknown option: $1 (try --help)" ;;
69
+ esac
70
+ shift
71
+ done
72
+
73
+ [ -d "$TARGET" ] || dr_die "target is not a directory: $TARGET"
74
+ TARGET="$(dr_abspath_dir "$TARGET")" || dr_die "cannot resolve target: $TARGET"
75
+ MF="$TARGET/$DR_MANIFEST_NAME"
76
+ [ -f "$MF" ] || dr_die "no DevRites manifest at $MF — nothing to uninstall."
77
+
78
+ dr_info "DevRites uninstaller"
79
+ dr_say " target : $TARGET"
80
+ dr_say " manifest: $MF"
81
+ [ "$DRYRUN" -eq 1 ] && dr_info " (dry run — no changes)"
82
+ dr_say ""
83
+
84
+ N_REMOVED=0; N_MISSING=0
85
+ PRUNE_TMP="$(mktemp 2>/dev/null || echo "${TMPDIR:-/tmp}/devrites-prune.$$")"
86
+ : > "$PRUNE_TMP"
87
+ trap 'rm -f "$PRUNE_TMP"' EXIT
88
+
89
+ # Remove each manifest-listed file.
90
+ while IFS= read -r rel; do
91
+ case "$rel" in ''|\#*) continue ;; esac # skip blanks/comments
92
+ case "$rel" in /*|*..*) dr_warn "ignoring suspicious manifest entry: $rel"; continue ;; esac
93
+ dest="$TARGET/$rel"
94
+ if [ -e "$dest" ] || [ -L "$dest" ]; then
95
+ if [ "$DRYRUN" -eq 1 ]; then
96
+ dr_say " [remove] $rel"
97
+ else
98
+ rm -f "$dest" || dr_warn "could not remove $dest"
99
+ fi
100
+ printf '%s\n' "$(dirname "$dest")" >> "$PRUNE_TMP"
101
+ N_REMOVED=$((N_REMOVED+1))
102
+ else
103
+ N_MISSING=$((N_MISSING+1))
104
+ fi
105
+ done < "$MF"
106
+
107
+ # Remove the manifest itself.
108
+ if [ "$DRYRUN" -eq 1 ]; then
109
+ dr_say " [remove] $DR_MANIFEST_NAME"
110
+ else
111
+ rm -f "$MF"
112
+ printf '%s\n' "$(dirname "$MF")" >> "$PRUNE_TMP"
113
+ fi
114
+
115
+ # Prune directories left empty (rmdir only removes empty dirs — safe). Two passes
116
+ # walk up to catch parents. Never removes .devrites/work or any non-empty dir.
117
+ if [ "$DRYRUN" -eq 0 ]; then
118
+ pass=0
119
+ while [ "$pass" -lt 6 ]; do
120
+ sort -u "$PRUNE_TMP" | awk '{ print length, $0 }' | sort -rn | cut -d' ' -f2- \
121
+ | while IFS= read -r d; do
122
+ case "$d" in "$TARGET"|"$TARGET"/) continue ;; esac
123
+ [ -d "$d" ] && rmdir "$d" 2>/dev/null && printf '%s\n' "$(dirname "$d")" >> "$PRUNE_TMP.next"
124
+ done
125
+ [ -f "$PRUNE_TMP.next" ] || break
126
+ cat "$PRUNE_TMP.next" >> "$PRUNE_TMP"; rm -f "$PRUNE_TMP.next"
127
+ pass=$((pass+1))
128
+ done
129
+ fi
130
+
131
+ dr_say ""
132
+ dr_ok "DevRites $([ "$DRYRUN" -eq 1 ] && echo 'uninstall plan complete (dry run)' || echo uninstalled)"
133
+ dr_say " removed: $N_REMOVED already-absent: $N_MISSING"
134
+ [ -d "$TARGET/.devrites/work" ] && dr_say " ${DR_Y}kept${DR_R} .devrites/work/ (your feature data) — delete it manually if you want it gone."
135
+ [ -f "$TARGET/.devrites/ACTIVE" ] && dr_say " ${DR_Y}kept${DR_R} .devrites/ACTIVE (active-feature cursor) — runtime state."
136
+ [ -f "$TARGET/.devrites/AFK" ] && dr_say " ${DR_Y}kept${DR_R} .devrites/AFK (per-developer AFK sentinel) — runtime state."
137
+ exit 0
package/update.sh ADDED
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env bash
2
+ # update.sh — upgrade an existing DevRites install to the latest GitHub Release.
3
+ #
4
+ # ./update.sh upgrade the install in the current directory
5
+ # ./update.sh --target DIR upgrade the install in DIR
6
+ # ./update.sh --to vX.Y.Z pin to a specific release tag instead of latest
7
+ # ./update.sh --check report installed vs latest, do not change anything
8
+ # ./update.sh --force re-install even if already at the latest version
9
+ # ./update.sh --pre allow pre-release tags (default: stable only)
10
+ #
11
+ # Env:
12
+ # DEVRITES_UPDATE_BUNDLE=PATH use a local .tar.gz instead of downloading
13
+ # (air-gapped upgrades; also used by tests)
14
+ #
15
+ # How it works:
16
+ # 1. Reads the installed version + flags from .claude/devrites.manifest.
17
+ # 2. Asks the GitHub API for the latest release tag (or the tag passed via --to).
18
+ # 3. If newer, downloads the release tarball, extracts to a temp dir,
19
+ # and re-runs the bundled install.sh with the same flags the user
20
+ # originally installed with — preserving .devrites/ feature state.
21
+ #
22
+ # Requires: curl, tar. (jq optional; falls back to sed parsing.)
23
+
24
+ set -u
25
+
26
+ REPO="ViktorsBaikers/DevRites"
27
+ API="https://api.github.com/repos/$REPO"
28
+
29
+ # ---- args ----------------------------------------------------------------
30
+ TARGET="$PWD"
31
+ PIN_TAG=""
32
+ CHECK_ONLY=0
33
+ FORCE=0
34
+ ALLOW_PRE=0
35
+
36
+ while [ $# -gt 0 ]; do
37
+ case "$1" in
38
+ --target) shift; [ $# -gt 0 ] || { echo "error: --target needs a directory" >&2; exit 1; }; TARGET="$1" ;;
39
+ --target=*) TARGET="${1#*=}" ;;
40
+ --to) shift; [ $# -gt 0 ] || { echo "error: --to needs a tag" >&2; exit 1; }; PIN_TAG="$1" ;;
41
+ --to=*) PIN_TAG="${1#*=}" ;;
42
+ --check) CHECK_ONLY=1 ;;
43
+ --force) FORCE=1 ;;
44
+ --pre) ALLOW_PRE=1 ;;
45
+ -h|--help) sed -n '2,22p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
46
+ *) echo "error: unknown option: $1 (try --help)" >&2; exit 1 ;;
47
+ esac
48
+ shift
49
+ done
50
+
51
+ # ---- pretty -------------------------------------------------------------
52
+ if [ -t 1 ]; then
53
+ B="$(printf '\033[1m')"; R="$(printf '\033[0m')"
54
+ G="$(printf '\033[32m')"; C="$(printf '\033[36m')"; Y="$(printf '\033[33m')"
55
+ else
56
+ B=""; R=""; G=""; C=""; Y=""
57
+ fi
58
+ say() { printf '%s\n' "$*"; }
59
+ info() { printf '%s%s%s\n' "$C" "$*" "$R"; }
60
+ ok() { printf '%s%s%s\n' "$G" "$*" "$R"; }
61
+ warn() { printf '%swarning:%s %s\n' "$Y" "$R" "$*" >&2; }
62
+ die() { printf 'error: %s\n' "$*" >&2; exit 1; }
63
+
64
+ # ---- prerequisites -------------------------------------------------------
65
+ command -v curl >/dev/null 2>&1 || die "curl is required"
66
+ command -v tar >/dev/null 2>&1 || die "tar is required"
67
+
68
+ # ---- locate install ------------------------------------------------------
69
+ [ -d "$TARGET" ] || die "target is not a directory: $TARGET"
70
+ TARGET="$(cd "$TARGET" && pwd -P)"
71
+ MANIFEST="$TARGET/.claude/devrites.manifest"
72
+ [ -f "$MANIFEST" ] || die "no DevRites install found at $TARGET (missing .claude/devrites.manifest). Run install.sh first."
73
+
74
+ INSTALLED_VERSION="$(sed -n 's/^# devrites-version:[[:space:]]*//p' "$MANIFEST" | head -n1)"
75
+ INSTALL_FLAGS="$(sed -n 's/^# devrites-flags:[[:space:]]*//p' "$MANIFEST" | head -n1)"
76
+ [ -n "$INSTALLED_VERSION" ] || INSTALLED_VERSION="unknown"
77
+
78
+ info "DevRites update"
79
+ say " project: $TARGET"
80
+ say " installed: ${B}$INSTALLED_VERSION${R}"
81
+ [ -n "$INSTALL_FLAGS" ] && say " flags: $INSTALL_FLAGS"
82
+
83
+ # ---- resolve target tag --------------------------------------------------
84
+ if [ -n "$PIN_TAG" ]; then
85
+ LATEST_TAG="$PIN_TAG"
86
+ else
87
+ if [ "$ALLOW_PRE" -eq 1 ]; then
88
+ # All releases, take the first one
89
+ LATEST_TAG="$(curl -fsSL "$API/releases" 2>/dev/null \
90
+ | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
91
+ | head -n1)"
92
+ else
93
+ LATEST_TAG="$(curl -fsSL "$API/releases/latest" 2>/dev/null \
94
+ | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
95
+ | head -n1)"
96
+ fi
97
+ [ -n "$LATEST_TAG" ] || die "could not resolve the latest release tag from GitHub. Check connectivity, or pass --to vX.Y.Z."
98
+ fi
99
+ LATEST_VERSION="${LATEST_TAG#v}"
100
+ say " latest: ${B}$LATEST_VERSION${R}"
101
+
102
+ # ---- semver compare ------------------------------------------------------
103
+ # Returns 0 if $1 > $2, 1 if equal, 2 if $1 < $2. Pre-release tags compare as lower.
104
+ semver_cmp() {
105
+ _a="${1%%-*}"; _b="${2%%-*}"
106
+ _ap="${1#${_a}}"; _bp="${2#${_b}}"
107
+ IFS=. read -r a1 a2 a3 <<EOF
108
+ $_a
109
+ EOF
110
+ IFS=. read -r b1 b2 b3 <<EOF
111
+ $_b
112
+ EOF
113
+ a1=${a1:-0}; a2=${a2:-0}; a3=${a3:-0}
114
+ b1=${b1:-0}; b2=${b2:-0}; b3=${b3:-0}
115
+ if [ "$a1" -gt "$b1" ]; then return 0
116
+ elif [ "$a1" -lt "$b1" ]; then return 2
117
+ elif [ "$a2" -gt "$b2" ]; then return 0
118
+ elif [ "$a2" -lt "$b2" ]; then return 2
119
+ elif [ "$a3" -gt "$b3" ]; then return 0
120
+ elif [ "$a3" -lt "$b3" ]; then return 2
121
+ fi
122
+ # core equal — pre-release < release
123
+ if [ -z "$_ap" ] && [ -n "$_bp" ]; then return 0
124
+ elif [ -n "$_ap" ] && [ -z "$_bp" ]; then return 2
125
+ fi
126
+ return 1
127
+ }
128
+
129
+ NEEDS_UPDATE=0
130
+ if [ "$INSTALLED_VERSION" = "unknown" ]; then
131
+ NEEDS_UPDATE=1
132
+ warn "installed version unknown — treating as out-of-date."
133
+ else
134
+ semver_cmp "$LATEST_VERSION" "$INSTALLED_VERSION"
135
+ case $? in
136
+ 0) NEEDS_UPDATE=1 ;;
137
+ 1) NEEDS_UPDATE=0 ;;
138
+ 2) warn "installed version ($INSTALLED_VERSION) is newer than latest release ($LATEST_VERSION)." ;;
139
+ esac
140
+ fi
141
+
142
+ if [ "$CHECK_ONLY" -eq 1 ]; then
143
+ if [ "$NEEDS_UPDATE" -eq 1 ]; then
144
+ info "update available: $INSTALLED_VERSION → $LATEST_VERSION"
145
+ exit 10
146
+ else
147
+ ok "up to date."
148
+ exit 0
149
+ fi
150
+ fi
151
+
152
+ if [ "$NEEDS_UPDATE" -eq 0 ] && [ "$FORCE" -eq 0 ]; then
153
+ ok "already at $LATEST_VERSION — nothing to do (use --force to reinstall)."
154
+ exit 0
155
+ fi
156
+
157
+ # ---- download release tarball -------------------------------------------
158
+ TMP="$(mktemp -d 2>/dev/null || echo "${TMPDIR:-/tmp}/devrites-update.$$")"
159
+ mkdir -p "$TMP"
160
+ cleanup() { rm -rf "$TMP"; }
161
+ trap cleanup EXIT
162
+
163
+ ARTIFACT="devrites-${LATEST_TAG}.tar.gz"
164
+ URL="https://github.com/$REPO/releases/download/$LATEST_TAG/$ARTIFACT"
165
+ SRC_TARBALL_URL="https://github.com/$REPO/archive/refs/tags/$LATEST_TAG.tar.gz"
166
+
167
+ # DEVRITES_UPDATE_BUNDLE — optional escape hatch for air-gapped upgrades and
168
+ # tests: a readable local .tar.gz to use instead of downloading from GitHub.
169
+ if [ -n "${DEVRITES_UPDATE_BUNDLE:-}" ]; then
170
+ [ -r "$DEVRITES_UPDATE_BUNDLE" ] || die "DEVRITES_UPDATE_BUNDLE not readable: $DEVRITES_UPDATE_BUNDLE"
171
+ info "using local bundle $DEVRITES_UPDATE_BUNDLE (DEVRITES_UPDATE_BUNDLE set) …"
172
+ cp "$DEVRITES_UPDATE_BUNDLE" "$TMP/$ARTIFACT" || die "could not copy $DEVRITES_UPDATE_BUNDLE"
173
+ else
174
+ info "downloading $ARTIFACT …"
175
+ if ! curl -fsSL -o "$TMP/$ARTIFACT" "$URL" 2>/dev/null; then
176
+ warn "release artifact $ARTIFACT not found; falling back to the source tarball ($LATEST_TAG)."
177
+ ARTIFACT="src-$LATEST_TAG.tar.gz"
178
+ curl -fsSL -o "$TMP/$ARTIFACT" "$SRC_TARBALL_URL" || die "could not download $SRC_TARBALL_URL"
179
+ fi
180
+ fi
181
+
182
+ tar -C "$TMP" -xzf "$TMP/$ARTIFACT"
183
+ EXTRACTED="$(find "$TMP" -maxdepth 1 -mindepth 1 -type d | head -n1)"
184
+ [ -n "$EXTRACTED" ] && [ -f "$EXTRACTED/install.sh" ] || die "extracted bundle has no install.sh: $EXTRACTED"
185
+ # GitHub source tarballs strip +x; restore it before re-exec.
186
+ chmod +x "$EXTRACTED/install.sh" "$EXTRACTED"/scripts/*.sh 2>/dev/null || true
187
+
188
+ # ---- re-run installer with the original flags + --force -----------------
189
+ info "running installer (with --force) — preserving .devrites/ feature state …"
190
+ # shellcheck disable=SC2086
191
+ bash "$EXTRACTED/install.sh" --target "$TARGET" --force $INSTALL_FLAGS \
192
+ || die "installer failed; the previous install is still in place."
193
+
194
+ ok "DevRites upgraded: $INSTALLED_VERSION → $LATEST_VERSION"
195
+ say " run ${C}/rite${R} or ${C}/rite-status${R} to continue where you left off."
196
+ exit 0