devlog-tracker 0.22.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/LICENSE +201 -0
- package/README.md +234 -0
- package/bin/devlog-tracker.js +51 -0
- package/cli/init.js +55 -0
- package/cli/init.test.js +37 -0
- package/cli/merge-hooks.js +60 -0
- package/cli/merge-hooks.test.js +187 -0
- package/cli/platforms/codex.js +13 -0
- package/cli/platforms/cursor.js +13 -0
- package/cli/status.js +14 -0
- package/cli/status.test.js +33 -0
- package/cli/vendor.js +37 -0
- package/cli/vendor.test.js +84 -0
- package/codex/hooks/on-pre-tool.sh +19 -0
- package/codex/hooks/on-session-end.sh +31 -0
- package/codex/hooks/on-session-start.sh +37 -0
- package/codex/hooks/on-stop.sh +18 -0
- package/codex/hooks/on-user-prompt-submit.sh +15 -0
- package/codex/hooks/project-dir.sh +13 -0
- package/codex/hooks/test-adapters.sh +98 -0
- package/codex/hooks.json +54 -0
- package/commands/checkpoint.md +17 -0
- package/commands/clean.md +50 -0
- package/commands/compact.md +24 -0
- package/commands/continue.md +30 -0
- package/commands/keep.md +100 -0
- package/commands/lessons-drift.md +19 -0
- package/commands/lessons-off.md +16 -0
- package/commands/lessons-on.md +20 -0
- package/commands/lessons.md +20 -0
- package/commands/overview.md +32 -0
- package/commands/pause.md +20 -0
- package/commands/resume.md +18 -0
- package/commands/segment-watch.md +21 -0
- package/commands/span.md +13 -0
- package/commands/start.md +19 -0
- package/commands/status.md +14 -0
- package/cursor/hooks/on-pre-tool.sh +24 -0
- package/cursor/hooks/on-session-end.sh +11 -0
- package/cursor/hooks/on-session-start.sh +15 -0
- package/cursor/hooks/on-stop.sh +44 -0
- package/cursor/hooks/on-submit-prompt.sh +28 -0
- package/cursor/hooks/on-tool-failure.sh +16 -0
- package/cursor/hooks/project-dir.sh +10 -0
- package/cursor/hooks/test-adapters.sh +201 -0
- package/cursor/hooks.json +26 -0
- package/hooks/scripts/await-open.sh +23 -0
- package/hooks/scripts/checkpoint-set.sh +44 -0
- package/hooks/scripts/clean-devlog.sh +69 -0
- package/hooks/scripts/close-open-round.sh +186 -0
- package/hooks/scripts/compact-devlog.sh +72 -0
- package/hooks/scripts/detect-pending-question.sh +31 -0
- package/hooks/scripts/devlog-lock.sh +38 -0
- package/hooks/scripts/devlog-md.sh +222 -0
- package/hooks/scripts/devlog-path.sh +70 -0
- package/hooks/scripts/enforce-devlog.sh +629 -0
- package/hooks/scripts/files-snapshot.sh +70 -0
- package/hooks/scripts/json-field.sh +76 -0
- package/hooks/scripts/keep-move.sh +155 -0
- package/hooks/scripts/kept-list.sh +40 -0
- package/hooks/scripts/lessons-append.sh +93 -0
- package/hooks/scripts/lessons-drift-set.sh +42 -0
- package/hooks/scripts/lessons-off.sh +15 -0
- package/hooks/scripts/lessons-on.sh +21 -0
- package/hooks/scripts/lessons-read.sh +60 -0
- package/hooks/scripts/on-session-end.sh +14 -0
- package/hooks/scripts/on-stop-failure.sh +18 -0
- package/hooks/scripts/on-tool-failure.sh +25 -0
- package/hooks/scripts/pause-devlog.sh +13 -0
- package/hooks/scripts/redact-prompt.sh +19 -0
- package/hooks/scripts/resume-devlog.sh +41 -0
- package/hooks/scripts/round-start.sh +333 -0
- package/hooks/scripts/run-tests.sh +26 -0
- package/hooks/scripts/segment-watch-set.sh +47 -0
- package/hooks/scripts/segment-watch.sh +197 -0
- package/hooks/scripts/session-start-devlog.sh +157 -0
- package/hooks/scripts/span-close.sh +9 -0
- package/hooks/scripts/span-open.sh +21 -0
- package/hooks/scripts/start-devlog.sh +24 -0
- package/hooks/scripts/status-devlog.sh +43 -0
- package/hooks/scripts/tests/test-await-open.sh +112 -0
- package/hooks/scripts/tests/test-branch-scoped-integration.sh +108 -0
- package/hooks/scripts/tests/test-checkpoint-set.sh +36 -0
- package/hooks/scripts/tests/test-clean-devlog.sh +160 -0
- package/hooks/scripts/tests/test-cli-init-e2e.sh +37 -0
- package/hooks/scripts/tests/test-close-open-round.sh +325 -0
- package/hooks/scripts/tests/test-compact-devlog.sh +62 -0
- package/hooks/scripts/tests/test-devlog-lock.sh +37 -0
- package/hooks/scripts/tests/test-devlog-md.sh +530 -0
- package/hooks/scripts/tests/test-devlog-path.sh +118 -0
- package/hooks/scripts/tests/test-enforce-devlog-files.sh +233 -0
- package/hooks/scripts/tests/test-enforce-devlog-handoff-order.sh +223 -0
- package/hooks/scripts/tests/test-enforce-devlog-workspace.sh +333 -0
- package/hooks/scripts/tests/test-enforce-devlog.sh +1290 -0
- package/hooks/scripts/tests/test-files-snapshot.sh +142 -0
- package/hooks/scripts/tests/test-json-field.sh +57 -0
- package/hooks/scripts/tests/test-keep-move.sh +127 -0
- package/hooks/scripts/tests/test-kept-list.sh +80 -0
- package/hooks/scripts/tests/test-lessons-append.sh +138 -0
- package/hooks/scripts/tests/test-lessons-drift-set.sh +36 -0
- package/hooks/scripts/tests/test-lessons-on-off.sh +75 -0
- package/hooks/scripts/tests/test-lessons-read.sh +97 -0
- package/hooks/scripts/tests/test-on-interrupt.sh +186 -0
- package/hooks/scripts/tests/test-redact-prompt.sh +27 -0
- package/hooks/scripts/tests/test-resume-devlog.sh +35 -0
- package/hooks/scripts/tests/test-round-start.sh +825 -0
- package/hooks/scripts/tests/test-segment-watch-set.sh +75 -0
- package/hooks/scripts/tests/test-segment-watch.sh +468 -0
- package/hooks/scripts/tests/test-session-start-devlog.sh +508 -0
- package/hooks/scripts/tests/test-start-pause-devlog.sh +84 -0
- package/hooks/scripts/tests/test-status-span.sh +50 -0
- package/hooks/scripts/tests/test-workspace-snapshot.sh +130 -0
- package/hooks/scripts/workspace-snapshot.sh +69 -0
- package/package.json +37 -0
- package/skills/devlog-tracker/SKILL.md +411 -0
- package/skills/devlog-tracker/references/checkpoint-mode.md +42 -0
- package/skills/devlog-tracker/references/lessons-mode.md +32 -0
- package/skills/devlog-tracker/references/reply-fold.md +129 -0
- package/skills/devlog-tracker/references/round-segments.md +55 -0
- package/skills/devlog-tracker/references/span-mode.md +65 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Self-check for workspace-snapshot.sh's workspace_snapshot(), covering the
|
|
3
|
+
# seven canonical `#### 工作區` formats from skills/devlog-tracker/SKILL.md.
|
|
4
|
+
# No framework — plain assert-and-exit, matching this repo's existing style.
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
. "$SCRIPT_DIR/workspace-snapshot.sh"
|
|
9
|
+
. "$SCRIPT_DIR/devlog-md.sh"
|
|
10
|
+
|
|
11
|
+
TMP_ROOT="$(mktemp -d)"
|
|
12
|
+
trap 'rm -rf "$TMP_ROOT"' EXIT
|
|
13
|
+
|
|
14
|
+
FAIL=0
|
|
15
|
+
assert_eq() {
|
|
16
|
+
local desc="$1" expected="$2" actual="$3"
|
|
17
|
+
if [ "$actual" = "$expected" ]; then
|
|
18
|
+
echo "PASS: $desc"
|
|
19
|
+
else
|
|
20
|
+
echo "FAIL: $desc"
|
|
21
|
+
printf ' expected: %s\n' "$expected"
|
|
22
|
+
printf ' actual: %s\n' "$actual"
|
|
23
|
+
FAIL=1
|
|
24
|
+
fi
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# --- non-git directory ----------------------------------------------------
|
|
28
|
+
NONGIT="$TMP_ROOT/nongit"
|
|
29
|
+
mkdir -p "$NONGIT"
|
|
30
|
+
OUT="$(workspace_snapshot "$NONGIT")"
|
|
31
|
+
assert_eq "non-git directory" "非 git 工作區" "$OUT"
|
|
32
|
+
|
|
33
|
+
# --- clean branch -----------------------------------------------------------
|
|
34
|
+
REPO="$TMP_ROOT/repo"
|
|
35
|
+
mkdir -p "$REPO"
|
|
36
|
+
git -C "$REPO" init -q -b main
|
|
37
|
+
git -C "$REPO" config user.email test@example.com
|
|
38
|
+
git -C "$REPO" config user.name test
|
|
39
|
+
echo hello > "$REPO/a.txt"
|
|
40
|
+
git -C "$REPO" add a.txt
|
|
41
|
+
git -C "$REPO" commit -q -m init
|
|
42
|
+
HASH="$(git -C "$REPO" rev-parse --short HEAD)"
|
|
43
|
+
OUT="$(workspace_snapshot "$REPO")"
|
|
44
|
+
assert_eq "clean branch" "main @ ${HASH},工作樹乾淨" "$OUT"
|
|
45
|
+
|
|
46
|
+
# --- dirty branch, two files -------------------------------------------------
|
|
47
|
+
echo change >> "$REPO/a.txt"
|
|
48
|
+
echo new > "$REPO/b.txt"
|
|
49
|
+
OUT="$(workspace_snapshot "$REPO")"
|
|
50
|
+
EXPECTED="main @ ${HASH}
|
|
51
|
+
未提交:a.txt, b.txt"
|
|
52
|
+
assert_eq "dirty branch, two files" "$EXPECTED" "$OUT"
|
|
53
|
+
|
|
54
|
+
# --- detached, clean ----------------------------------------------------------
|
|
55
|
+
git -C "$REPO" reset --hard -q "$HASH"
|
|
56
|
+
git -C "$REPO" clean -fdq
|
|
57
|
+
git -C "$REPO" checkout -q "$HASH" 2>/dev/null
|
|
58
|
+
OUT="$(workspace_snapshot "$REPO")"
|
|
59
|
+
assert_eq "detached, clean" "HEAD detached @ ${HASH}" "$OUT"
|
|
60
|
+
|
|
61
|
+
# --- detached, dirty -----------------------------------------------------------
|
|
62
|
+
echo dirty >> "$REPO/a.txt"
|
|
63
|
+
OUT="$(workspace_snapshot "$REPO")"
|
|
64
|
+
EXPECTED="HEAD detached @ ${HASH}
|
|
65
|
+
未提交:a.txt"
|
|
66
|
+
assert_eq "detached, dirty" "$EXPECTED" "$OUT"
|
|
67
|
+
|
|
68
|
+
# --- unborn branch (git init, zero commits), clean --------------------------
|
|
69
|
+
UNBORN="$TMP_ROOT/unborn"
|
|
70
|
+
mkdir -p "$UNBORN"
|
|
71
|
+
git -C "$UNBORN" init -q -b main
|
|
72
|
+
OUT="$(workspace_snapshot "$UNBORN")"
|
|
73
|
+
assert_eq "unborn branch, clean" "main @ (尚無 commit),工作樹乾淨" "$OUT"
|
|
74
|
+
|
|
75
|
+
# --- unborn branch, dirty (untracked file, still no commits) ----------------
|
|
76
|
+
echo new > "$UNBORN/c.txt"
|
|
77
|
+
OUT="$(workspace_snapshot "$UNBORN")"
|
|
78
|
+
EXPECTED_UNBORN="main @ (尚無 commit)
|
|
79
|
+
未提交:c.txt"
|
|
80
|
+
assert_eq "unborn branch, dirty" "$EXPECTED_UNBORN" "$OUT"
|
|
81
|
+
|
|
82
|
+
CLI_UNBORN="$(bash "$SCRIPT_DIR/workspace-snapshot.sh" "$UNBORN")"
|
|
83
|
+
FUNC_UNBORN="$(workspace_snapshot "$UNBORN")"
|
|
84
|
+
assert_eq "cli matches function (unborn dirty)" "$FUNC_UNBORN" "$CLI_UNBORN"
|
|
85
|
+
|
|
86
|
+
# --- executable entry matches the sourced function --------------------------
|
|
87
|
+
CLI_NONGIT="$(bash "$SCRIPT_DIR/workspace-snapshot.sh" "$NONGIT")"
|
|
88
|
+
assert_eq "cli non-git directory" "非 git 工作區" "$CLI_NONGIT"
|
|
89
|
+
|
|
90
|
+
CLI_DETACHED="$(bash "$SCRIPT_DIR/workspace-snapshot.sh" "$REPO")"
|
|
91
|
+
FUNC_DETACHED="$(workspace_snapshot "$REPO")"
|
|
92
|
+
assert_eq "cli matches function (detached dirty)" "$FUNC_DETACHED" "$CLI_DETACHED"
|
|
93
|
+
|
|
94
|
+
DEFAULT_DIR="$TMP_ROOT/default-dir"
|
|
95
|
+
mkdir -p "$DEFAULT_DIR"
|
|
96
|
+
CLI_DEFAULT="$(CLAUDE_PROJECT_DIR="$DEFAULT_DIR" bash "$SCRIPT_DIR/workspace-snapshot.sh")"
|
|
97
|
+
assert_eq "cli default dir is CLAUDE_PROJECT_DIR" "非 git 工作區" "$CLI_DEFAULT"
|
|
98
|
+
|
|
99
|
+
# --- claim state vs live snapshot ------------------------------------------
|
|
100
|
+
LIVE_NOW="$(workspace_snapshot "$REPO")"
|
|
101
|
+
cat > "$TMP_ROOT/round.md" <<EOF
|
|
102
|
+
## Round 1 — 2026-09-11T00:00:00+08:00
|
|
103
|
+
|
|
104
|
+
### Handoff
|
|
105
|
+
#### 工作區
|
|
106
|
+
${LIVE_NOW}
|
|
107
|
+
|
|
108
|
+
### Status
|
|
109
|
+
IN_PROGRESS
|
|
110
|
+
EOF
|
|
111
|
+
assert_eq "claim MATCH on live snapshot" "MATCH" "$(workspace_claim_state "$REPO" "$TMP_ROOT/round.md")"
|
|
112
|
+
cat > "$TMP_ROOT/stale.md" <<'EOF'
|
|
113
|
+
## Round 1 — 2026-09-11T00:00:00+08:00
|
|
114
|
+
|
|
115
|
+
### Handoff
|
|
116
|
+
#### 工作區
|
|
117
|
+
main @ deadbeef,工作樹乾淨
|
|
118
|
+
|
|
119
|
+
### Status
|
|
120
|
+
IN_PROGRESS
|
|
121
|
+
EOF
|
|
122
|
+
assert_eq "claim MISMATCH on stale hash" "MISMATCH" "$(workspace_claim_state "$REPO" "$TMP_ROOT/stale.md")"
|
|
123
|
+
|
|
124
|
+
if [ "$FAIL" -eq 0 ]; then
|
|
125
|
+
echo "All checks passed."
|
|
126
|
+
exit 0
|
|
127
|
+
else
|
|
128
|
+
echo "Some checks FAILED."
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# shellcheck shell=bash
|
|
3
|
+
# Sourced by enforce-devlog.sh (write-time Stop check) and executed by
|
|
4
|
+
# continue / resume (read-time verify). Computes the canonical `#### 工作區`
|
|
5
|
+
# text using the seven output formats defined in skills/devlog-tracker/SKILL.md.
|
|
6
|
+
# This function is the only machine producer — do not re-encode in command docs.
|
|
7
|
+
#
|
|
8
|
+
# Usage (sourced): workspace_snapshot "$PROJECT_DIR"
|
|
9
|
+
# Usage (executed): bash workspace-snapshot.sh [dir]
|
|
10
|
+
# dir defaults to ${CLAUDE_PROJECT_DIR:-.}
|
|
11
|
+
# Echoes 1 line (clean / non-git / detached-clean / unborn-clean) or 2 lines
|
|
12
|
+
# (dirty / detached-dirty / unborn-dirty). Never fails: any git command error
|
|
13
|
+
# degrades toward "非 git 工作區", matching this hook suite's fail-open design.
|
|
14
|
+
#
|
|
15
|
+
# Known limitation: a dirty file path containing a space is not exactly
|
|
16
|
+
# reversible from `git status --short`'s last-field extraction below — same
|
|
17
|
+
# limitation the hand-written 工作區 convention already has.
|
|
18
|
+
workspace_snapshot() {
|
|
19
|
+
local dir="${1:-.}"
|
|
20
|
+
if ! git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
21
|
+
printf '非 git 工作區\n'
|
|
22
|
+
return 0
|
|
23
|
+
fi
|
|
24
|
+
local branch hash label status_out dirty_files
|
|
25
|
+
branch="$(git -C "$dir" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')"
|
|
26
|
+
hash="$(git -C "$dir" rev-parse --short HEAD 2>/dev/null || echo '')"
|
|
27
|
+
if [ -z "$hash" ]; then
|
|
28
|
+
# No commits yet (unborn branch, e.g. right after `git init`) is a valid
|
|
29
|
+
# git workspace, not "非 git 工作區" — reserve that message for a
|
|
30
|
+
# genuinely broken/non-git state. An unborn branch still resolves a
|
|
31
|
+
# symbolic HEAD (`git symbolic-ref` succeeds, unlike `rev-parse
|
|
32
|
+
# --abbrev-ref HEAD` which fails on it too); if symbolic-ref also fails,
|
|
33
|
+
# fall through to the original fail-open message.
|
|
34
|
+
local unborn_branch
|
|
35
|
+
unborn_branch="$(git -C "$dir" symbolic-ref -q --short HEAD 2>/dev/null || echo '')"
|
|
36
|
+
if [ -z "$unborn_branch" ]; then
|
|
37
|
+
printf '非 git 工作區\n'
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
status_out="$(git -C "$dir" status --short 2>/dev/null || echo '')"
|
|
41
|
+
if [ -z "$status_out" ]; then
|
|
42
|
+
printf '%s @ (尚無 commit),工作樹乾淨\n' "$unborn_branch"
|
|
43
|
+
else
|
|
44
|
+
dirty_files="$(printf '%s\n' "$status_out" | awk '{printf "%s%s", (NR>1?", ":""), $NF}')"
|
|
45
|
+
printf '%s @ (尚無 commit)\n未提交:%s\n' "$unborn_branch" "$dirty_files"
|
|
46
|
+
fi
|
|
47
|
+
return 0
|
|
48
|
+
fi
|
|
49
|
+
if [ "$branch" = "HEAD" ] || [ -z "$branch" ]; then
|
|
50
|
+
label="HEAD detached"
|
|
51
|
+
else
|
|
52
|
+
label="$branch"
|
|
53
|
+
fi
|
|
54
|
+
status_out="$(git -C "$dir" status --short 2>/dev/null || echo '')"
|
|
55
|
+
if [ -z "$status_out" ]; then
|
|
56
|
+
if [ "$label" = "HEAD detached" ]; then
|
|
57
|
+
printf '%s @ %s\n' "$label" "$hash"
|
|
58
|
+
else
|
|
59
|
+
printf '%s @ %s,工作樹乾淨\n' "$label" "$hash"
|
|
60
|
+
fi
|
|
61
|
+
else
|
|
62
|
+
dirty_files="$(printf '%s\n' "$status_out" | awk '{printf "%s%s", (NR>1?", ":""), $NF}')"
|
|
63
|
+
printf '%s @ %s\n未提交:%s\n' "$label" "$hash" "$dirty_files"
|
|
64
|
+
fi
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
68
|
+
workspace_snapshot "${1:-${CLAUDE_PROJECT_DIR:-.}}"
|
|
69
|
+
fi
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devlog-tracker",
|
|
3
|
+
"version": "0.22.0",
|
|
4
|
+
"description": "npx installer for the devlog-tracker Claude Code plugin's Cursor and Codex adapters.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"devlog-tracker": "bin/devlog-tracker.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"cli",
|
|
11
|
+
"hooks/scripts",
|
|
12
|
+
"codex/hooks",
|
|
13
|
+
"cursor/hooks",
|
|
14
|
+
"skills",
|
|
15
|
+
"commands",
|
|
16
|
+
"codex/hooks.json",
|
|
17
|
+
"cursor/hooks.json"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "node --test cli/*.test.js scripts/*.test.js",
|
|
24
|
+
"version": "node scripts/sync-version.js && git add .claude-plugin/plugin.json .claude-plugin/marketplace.json README.md"
|
|
25
|
+
},
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"author": {
|
|
28
|
+
"name": "gogogohuang"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/gogogohuang/devlog-tracker.git"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"devlog"
|
|
36
|
+
]
|
|
37
|
+
}
|