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.
- package/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +43 -0
- package/CHANGELOG.md +391 -0
- package/LICENSE +56 -0
- package/NOTICE.md +18 -0
- package/README.md +582 -0
- package/SECURITY.md +193 -0
- package/bin/devrites.mjs +100 -0
- package/docs/architecture.md +272 -0
- package/docs/cli-mcp.md +57 -0
- package/docs/command-map.md +143 -0
- package/docs/flow.md +360 -0
- package/docs/release.md +29 -0
- package/docs/skills.md +214 -0
- package/docs/usage.md +325 -0
- package/install.sh +359 -0
- package/mcp/devrites-mcp.mjs +103 -0
- package/pack/.claude/agents/devrites-code-reviewer.md +50 -0
- package/pack/.claude/agents/devrites-doubt-reviewer.md +55 -0
- package/pack/.claude/agents/devrites-frontend-reviewer.md +52 -0
- package/pack/.claude/agents/devrites-performance-reviewer.md +47 -0
- package/pack/.claude/agents/devrites-plan-reviewer.md +79 -0
- package/pack/.claude/agents/devrites-security-auditor.md +53 -0
- package/pack/.claude/agents/devrites-simplifier-reviewer.md +75 -0
- package/pack/.claude/agents/devrites-slice-wright.md +181 -0
- package/pack/.claude/agents/devrites-spec-reviewer.md +72 -0
- package/pack/.claude/agents/devrites-strategy-reviewer.md +62 -0
- package/pack/.claude/agents/devrites-test-analyst.md +47 -0
- package/pack/.claude/hooks/devrites-a1-guard.sh +81 -0
- package/pack/.claude/hooks/devrites-allow.sh +44 -0
- package/pack/.claude/hooks/devrites-cursor.sh +28 -0
- package/pack/.claude/hooks/devrites-orient.sh +53 -0
- package/pack/.claude/hooks/devrites-redwatch.sh +39 -0
- package/pack/.claude/hooks/devrites-refresh-indexes.sh +127 -0
- package/pack/.claude/hooks/devrites-reviewer-readonly.sh +28 -0
- package/pack/.claude/hooks/devrites-statusline.sh +18 -0
- package/pack/.claude/hooks/devrites-stop-gate.sh +45 -0
- package/pack/.claude/hooks/devrites-wright-scope.sh +35 -0
- package/pack/.claude/hooks/hooks.json +52 -0
- package/pack/.claude/rules/README.md +48 -0
- package/pack/.claude/rules/afk-hitl.md +245 -0
- package/pack/.claude/rules/agents.md +98 -0
- package/pack/.claude/rules/anti-patterns.md +48 -0
- package/pack/.claude/rules/code-review.md +38 -0
- package/pack/.claude/rules/coding-style.md +55 -0
- package/pack/.claude/rules/context-hygiene.md +97 -0
- package/pack/.claude/rules/core.md +119 -0
- package/pack/.claude/rules/development-workflow.md +40 -0
- package/pack/.claude/rules/documentation.md +27 -0
- package/pack/.claude/rules/error-handling.md +33 -0
- package/pack/.claude/rules/git-workflow.md +35 -0
- package/pack/.claude/rules/hooks.md +38 -0
- package/pack/.claude/rules/patterns.md +45 -0
- package/pack/.claude/rules/performance.md +27 -0
- package/pack/.claude/rules/prose-style.md +101 -0
- package/pack/.claude/rules/security.md +63 -0
- package/pack/.claude/rules/testing.md +88 -0
- package/pack/.claude/rules/tooling.md +72 -0
- package/pack/.claude/settings.json +53 -0
- package/pack/.claude/skills/devrites-api-interface/SKILL.md +45 -0
- package/pack/.claude/skills/devrites-audit/SKILL.md +73 -0
- package/pack/.claude/skills/devrites-browser-proof/SKILL.md +38 -0
- package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +50 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +47 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +17 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
- package/pack/.claude/skills/devrites-debug-recovery/reference/regression-test.md +31 -0
- package/pack/.claude/skills/devrites-doubt/SKILL.md +75 -0
- package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +96 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/craft.md +59 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +116 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/fullstack.md +45 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +215 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/reuse-first.md +59 -0
- package/pack/.claude/skills/devrites-frontend-craft/reference/shape.md +60 -0
- package/pack/.claude/skills/devrites-interview/SKILL.md +81 -0
- package/pack/.claude/skills/devrites-lib/SKILL.md +76 -0
- package/pack/.claude/skills/devrites-lib/scripts/analyze.sh +78 -0
- package/pack/.claude/skills/devrites-lib/scripts/check-acceptance.sh +75 -0
- package/pack/.claude/skills/devrites-lib/scripts/close-out.sh +47 -0
- package/pack/.claude/skills/devrites-lib/scripts/conventions.py +273 -0
- package/pack/.claude/skills/devrites-lib/scripts/coverage.sh +51 -0
- package/pack/.claude/skills/devrites-lib/scripts/devrites.sh +69 -0
- package/pack/.claude/skills/devrites-lib/scripts/doctor.sh +92 -0
- package/pack/.claude/skills/devrites-lib/scripts/evidence-fresh.sh +63 -0
- package/pack/.claude/skills/devrites-lib/scripts/footprint.sh +45 -0
- package/pack/.claude/skills/devrites-lib/scripts/learnings.sh +74 -0
- package/pack/.claude/skills/devrites-lib/scripts/mutation-gate.sh +52 -0
- package/pack/.claude/skills/devrites-lib/scripts/package-existence.sh +68 -0
- package/pack/.claude/skills/devrites-lib/scripts/preamble.sh +76 -0
- package/pack/.claude/skills/devrites-lib/scripts/progress.sh +103 -0
- package/pack/.claude/skills/devrites-lib/scripts/readiness.sh +62 -0
- package/pack/.claude/skills/devrites-lib/scripts/reconcile.sh +123 -0
- package/pack/.claude/skills/devrites-lib/scripts/resolve.sh +279 -0
- package/pack/.claude/skills/devrites-lib/scripts/stuck.sh +67 -0
- package/pack/.claude/skills/devrites-lib/scripts/test-integrity.sh +87 -0
- package/pack/.claude/skills/devrites-lib/scripts/tick-afk.sh +52 -0
- package/pack/.claude/skills/devrites-prose-craft/SKILL.md +105 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/banned-phrases.md +95 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/examples.md +88 -0
- package/pack/.claude/skills/devrites-prose-craft/reference/structures.md +134 -0
- package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +54 -0
- package/pack/.claude/skills/devrites-source-driven/SKILL.md +36 -0
- package/pack/.claude/skills/devrites-ux-shape/SKILL.md +121 -0
- package/pack/.claude/skills/devrites-ux-shape/reference/brief-template.md +93 -0
- package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
- package/pack/.claude/skills/rite/SKILL.md +135 -0
- package/pack/.claude/skills/rite/reference/menu.md +32 -0
- package/pack/.claude/skills/rite-adopt/SKILL.md +83 -0
- package/pack/.claude/skills/rite-adopt/reference/adoption.md +58 -0
- package/pack/.claude/skills/rite-adopt/reference/anti-patterns.md +19 -0
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +96 -0
- package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +35 -0
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +54 -0
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +59 -0
- package/pack/.claude/skills/rite-build/SKILL.md +261 -0
- package/pack/.claude/skills/rite-build/reference/afk-discipline.md +145 -0
- package/pack/.claude/skills/rite-build/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +149 -0
- package/pack/.claude/skills/rite-build/reference/evidence-standard.md +32 -0
- package/pack/.claude/skills/rite-build/reference/frontend-trigger.md +39 -0
- package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +38 -0
- package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +43 -0
- package/pack/.claude/skills/rite-build/reference/tdd.md +26 -0
- package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +115 -0
- package/pack/.claude/skills/rite-define/SKILL.md +157 -0
- package/pack/.claude/skills/rite-define/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-define/reference/gates.md +152 -0
- package/pack/.claude/skills/rite-define/reference/plan-template.md +65 -0
- package/pack/.claude/skills/rite-doctor/SKILL.md +50 -0
- package/pack/.claude/skills/rite-frame/SKILL.md +116 -0
- package/pack/.claude/skills/rite-frame/reference/failure-modes.md +68 -0
- package/pack/.claude/skills/rite-handoff/SKILL.md +95 -0
- package/pack/.claude/skills/rite-handoff/reference/handoff-template.md +34 -0
- package/pack/.claude/skills/rite-learn/SKILL.md +82 -0
- package/pack/.claude/skills/rite-plan/SKILL.md +82 -0
- package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +24 -0
- package/pack/.claude/skills/rite-plan/reference/dependency-graph.md +33 -0
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +42 -0
- package/pack/.claude/skills/rite-plan/reference/slicing.md +52 -0
- package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +34 -0
- package/pack/.claude/skills/rite-polish/SKILL.md +90 -0
- package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +177 -0
- package/pack/.claude/skills/rite-polish/reference/anti-patterns.md +27 -0
- package/pack/.claude/skills/rite-polish/reference/backend-polish.md +80 -0
- package/pack/.claude/skills/rite-polish/reference/browser-polish-evidence.md +31 -0
- package/pack/.claude/skills/rite-polish/reference/code.md +85 -0
- package/pack/.claude/skills/rite-polish/reference/design-system-discovery.md +35 -0
- package/pack/.claude/skills/rite-polish/reference/harden-checklist.md +109 -0
- package/pack/.claude/skills/rite-polish/reference/ui.md +136 -0
- package/pack/.claude/skills/rite-pressure-test/SKILL.md +43 -0
- package/pack/.claude/skills/rite-prototype/SKILL.md +87 -0
- package/pack/.claude/skills/rite-prove/SKILL.md +120 -0
- package/pack/.claude/skills/rite-prove/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-prove/reference/browser-proof.md +26 -0
- package/pack/.claude/skills/rite-prove/reference/failure-triage.md +25 -0
- package/pack/.claude/skills/rite-prove/reference/proof-ladder.md +26 -0
- package/pack/.claude/skills/rite-prove/reference/test-command-discovery.md +30 -0
- package/pack/.claude/skills/rite-quick/SKILL.md +81 -0
- package/pack/.claude/skills/rite-resolve/SKILL.md +113 -0
- package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +114 -0
- package/pack/.claude/skills/rite-review/SKILL.md +170 -0
- package/pack/.claude/skills/rite-review/reference/anti-patterns.md +32 -0
- package/pack/.claude/skills/rite-review/reference/cognitive-load.md +90 -0
- package/pack/.claude/skills/rite-review/reference/feature-scoped-review.md +26 -0
- package/pack/.claude/skills/rite-review/reference/five-axis-review.md +46 -0
- package/pack/.claude/skills/rite-review/reference/nielsen-heuristics.md +130 -0
- package/pack/.claude/skills/rite-review/reference/parallel-dispatch.md +62 -0
- package/pack/.claude/skills/rite-review/reference/performance-review.md +28 -0
- package/pack/.claude/skills/rite-review/reference/security-review.md +32 -0
- package/pack/.claude/skills/rite-seal/SKILL.md +183 -0
- package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +27 -0
- package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +63 -0
- package/pack/.claude/skills/rite-seal/reference/final-evidence.md +72 -0
- package/pack/.claude/skills/rite-seal/reference/go-no-go.md +37 -0
- package/pack/.claude/skills/rite-seal/reference/parallel-dispatch.md +69 -0
- package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +30 -0
- package/pack/.claude/skills/rite-seal/reference/seal-template.md +36 -0
- package/pack/.claude/skills/rite-ship/SKILL.md +120 -0
- package/pack/.claude/skills/rite-ship/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-ship/reference/close-out.md +31 -0
- package/pack/.claude/skills/rite-ship/reference/design-memory.md +120 -0
- package/pack/.claude/skills/rite-ship/reference/git-ship.md +42 -0
- package/pack/.claude/skills/rite-ship/reference/ship-template.md +33 -0
- package/pack/.claude/skills/rite-spec/SKILL.md +126 -0
- package/pack/.claude/skills/rite-spec/reference/acceptance-criteria.md +31 -0
- package/pack/.claude/skills/rite-spec/reference/anti-patterns.md +25 -0
- package/pack/.claude/skills/rite-spec/reference/interview-patterns.md +56 -0
- package/pack/.claude/skills/rite-spec/reference/investigation.md +64 -0
- package/pack/.claude/skills/rite-spec/reference/question-protocol.md +61 -0
- package/pack/.claude/skills/rite-spec/reference/references-intake.md +57 -0
- package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +73 -0
- package/pack/.claude/skills/rite-spec/reference/spec-template.md +124 -0
- package/pack/.claude/skills/rite-spec/reference/state-workspace.md +159 -0
- package/pack/.claude/skills/rite-status/SKILL.md +101 -0
- package/pack/.claude/skills/rite-temper/SKILL.md +119 -0
- package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +29 -0
- package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +65 -0
- package/pack/.claude/skills/rite-temper/reference/scope-modes.md +53 -0
- package/pack/.claude/skills/rite-temper/reference/significance.md +46 -0
- package/pack/.claude/skills/rite-temper/reference/strategy-template.md +90 -0
- package/pack/.claude/skills/rite-vet/SKILL.md +155 -0
- package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +29 -0
- package/pack/.claude/skills/rite-vet/reference/artifacts.md +135 -0
- package/pack/.claude/skills/rite-vet/reference/cross-model.md +41 -0
- package/pack/.claude/skills/rite-vet/reference/depth.md +53 -0
- package/pack/.claude/skills/rite-vet/reference/eng-lenses.md +48 -0
- package/pack/.claude/skills/rite-vet/reference/review-axes.md +167 -0
- package/pack/.claude/skills/rite-zoom-out/SKILL.md +75 -0
- package/package.json +68 -0
- package/scripts/build-release-tarball.sh +74 -0
- package/scripts/check-cross-refs.py +121 -0
- package/scripts/check-no-global-writes.sh +44 -0
- package/scripts/check-rule-uniqueness.sh +73 -0
- package/scripts/devrites-detect.sh +175 -0
- package/scripts/eval-runner.py +273 -0
- package/scripts/grade-feature.sh +104 -0
- package/scripts/install-lib.sh +83 -0
- package/scripts/pin.sh +166 -0
- package/scripts/render-eval-summary.py +48 -0
- package/scripts/run-evals.sh +149 -0
- package/scripts/run-outcome-evals.sh +49 -0
- package/scripts/scan-pack-security.py +209 -0
- package/scripts/scan-supply-chain-iocs.py +127 -0
- package/scripts/supply-chain-iocs.json +11 -0
- package/scripts/sync-version.sh +56 -0
- package/scripts/validate-frontmatter.py +149 -0
- package/scripts/validate-workflow-security.py +86 -0
- package/scripts/validate.sh +234 -0
- package/uninstall.sh +137 -0
- 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
|