omniconductor 0.3.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 (118) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +219 -0
  3. package/NOTICE +11 -0
  4. package/README.md +526 -0
  5. package/THIRD_PARTY_NOTICES.md +31 -0
  6. package/TRADEMARKS.md +26 -0
  7. package/VISION.md +106 -0
  8. package/adapters/README.md +121 -0
  9. package/adapters/claude/README.md +102 -0
  10. package/adapters/claude/SUPPORTED-FEATURES.md +66 -0
  11. package/adapters/claude/hookify-templates/.recipe-scoped +9 -0
  12. package/adapters/claude/hookify-templates/README.md +93 -0
  13. package/adapters/claude/hookify-templates/block-completion-claim-without-push.local.md.template +56 -0
  14. package/adapters/claude/hookify-templates/block-direct-push-protected-branch.local.md.template +18 -0
  15. package/adapters/claude/hookify-templates/block-force-push-protected-branch.local.md.template +42 -0
  16. package/adapters/claude/hookify-templates/block-server-secret-in-client.local.md.template +36 -0
  17. package/adapters/claude/hookify-templates/warn-any-type-added.local.md.template +44 -0
  18. package/adapters/claude/hookify-templates/warn-commit-without-pre-commit-review.local.md.template +52 -0
  19. package/adapters/claude/hookify-templates/warn-console-direct.local.md.template +55 -0
  20. package/adapters/claude/hookify-templates/warn-create-table-without-access-control.local.md.template +35 -0
  21. package/adapters/claude/hookify-templates/warn-current-work-without-remaining-tasks.local.md.template +36 -0
  22. package/adapters/claude/hookify-templates/warn-gh-pr-create-without-pre-merge-review.local.md.template +38 -0
  23. package/adapters/claude/hookify-templates/warn-hardcoded-text-without-i18n-key.local.md.template +21 -0
  24. package/adapters/claude/hookify-templates/warn-on-gh-pr-merge.local.md.template +33 -0
  25. package/adapters/claude/hookify-templates/warn-plan-spec-without-remaining-tasks.local.md.template +44 -0
  26. package/adapters/claude/hookify-templates/warn-raw-hex-instead-of-token.local.md.template +21 -0
  27. package/adapters/claude/hookify-templates/warn-security-definer-without-search-path.local.md.template +30 -0
  28. package/adapters/claude/hookify-templates/warn-stop-commit-without-current-work.local.md.template +47 -0
  29. package/adapters/claude/hookify-templates/warn-user-manual-completion.local.md.template +40 -0
  30. package/adapters/claude/transform-spec.md +140 -0
  31. package/adapters/claude/transform.sh +1169 -0
  32. package/adapters/codex/README.md +87 -0
  33. package/adapters/codex/SUPPORTED-FEATURES.md +66 -0
  34. package/adapters/codex/transform-spec.md +90 -0
  35. package/adapters/codex/transform.sh +748 -0
  36. package/adapters/copilot/README.md +88 -0
  37. package/adapters/copilot/SUPPORTED-FEATURES.md +73 -0
  38. package/adapters/copilot/transform-spec.md +111 -0
  39. package/adapters/copilot/transform.sh +757 -0
  40. package/adapters/cursor/README.md +87 -0
  41. package/adapters/cursor/SUPPORTED-FEATURES.md +90 -0
  42. package/adapters/cursor/transform-spec.md +124 -0
  43. package/adapters/cursor/transform.sh +731 -0
  44. package/adapters/gemini/README.md +93 -0
  45. package/adapters/gemini/SUPPORTED-FEATURES.md +80 -0
  46. package/adapters/gemini/transform-spec.md +102 -0
  47. package/adapters/gemini/transform.sh +844 -0
  48. package/adapters/windsurf/README.md +93 -0
  49. package/adapters/windsurf/SUPPORTED-FEATURES.md +67 -0
  50. package/adapters/windsurf/transform-spec.md +99 -0
  51. package/adapters/windsurf/transform.sh +727 -0
  52. package/bin/omniconductor.js +130 -0
  53. package/core/README.md +64 -0
  54. package/core/anti-patterns/README.md +142 -0
  55. package/core/anti-patterns/dynamic-system-prompt.md +113 -0
  56. package/core/anti-patterns/frequent-rule-file-edit.md +83 -0
  57. package/core/anti-patterns/large-file-read-no-range.md +90 -0
  58. package/core/anti-patterns/no-sub-agent-dispatch.md +89 -0
  59. package/core/anti-patterns/single-monolithic-rule-file.md +99 -0
  60. package/core/anti-patterns/skill-eager-load.md +83 -0
  61. package/core/anti-patterns/tool-call-spam.md +93 -0
  62. package/core/docs-templates/CURRENT_WORK.md +64 -0
  63. package/core/docs-templates/INDEX.md +57 -0
  64. package/core/docs-templates/PLANS.md +44 -0
  65. package/core/docs-templates/README.md +40 -0
  66. package/core/docs-templates/REMAINING_TASKS.md +43 -0
  67. package/core/docs-templates/TASKS.md +51 -0
  68. package/core/docs-templates/specs/_example.md +121 -0
  69. package/core/hooks/README.md +62 -0
  70. package/core/hooks/pretool-agent-routing.sh.template +97 -0
  71. package/core/hooks/pretool-commit-current-work-check.sh.template +103 -0
  72. package/core/hooks/pretool-commit-test-coverage-check.sh.template +116 -0
  73. package/core/hooks/pretool-large-file-read-guard.sh.template +117 -0
  74. package/core/hooks/stop-cache-hit-baseline-check.sh.template +133 -0
  75. package/core/hooks/stop-r6-review-check.sh.template +80 -0
  76. package/core/hooks/stop-session-log-check.sh.template +101 -0
  77. package/core/hooks/stop-trajectory-log.sh.template +96 -0
  78. package/core/memory-pattern/EXAMPLES.md +114 -0
  79. package/core/memory-pattern/README.md +133 -0
  80. package/core/recipes/README.md +46 -0
  81. package/core/recipes/auto-mock-data.md +82 -0
  82. package/core/recipes/branch-strategy.md +100 -0
  83. package/core/recipes/coding-conventions.md +123 -0
  84. package/core/recipes/database-discipline.md +65 -0
  85. package/core/recipes/debugging.md +143 -0
  86. package/core/recipes/design-system.md +30 -0
  87. package/core/recipes/i18n.md +118 -0
  88. package/core/recipes/monorepo.md +101 -0
  89. package/core/recipes/self-improvement.md +61 -0
  90. package/core/recipes/tdd.md +128 -0
  91. package/core/recipes/web-mobile-parity.md +87 -0
  92. package/core/reflector/SCHEDULING.md +83 -0
  93. package/core/reflector/prune-lessons.sh +105 -0
  94. package/core/reflector/reflect-brief.md +11 -0
  95. package/core/reflector/reflect.command.md +13 -0
  96. package/core/reflector/run-weekly.sh +54 -0
  97. package/core/reflector/trajectory-log.sh +55 -0
  98. package/core/roles/README.md +61 -0
  99. package/core/roles/builder.md +75 -0
  100. package/core/roles/designer.md +93 -0
  101. package/core/roles/helper.md +70 -0
  102. package/core/roles/planner.md +123 -0
  103. package/core/roles/reflector.md +72 -0
  104. package/core/roles/reviewer.md +104 -0
  105. package/core/roles/scribe.md +89 -0
  106. package/core/universal-rules/README.md +71 -0
  107. package/core/universal-rules/meta-discipline.md +292 -0
  108. package/core/universal-rules/operations.md +162 -0
  109. package/core/universal-rules/quality-gates.md +191 -0
  110. package/core/universal-rules/spec-as-you-go.md +123 -0
  111. package/core/universal-rules/workflow.md +153 -0
  112. package/core/workflow/PHASES.md +134 -0
  113. package/core/workflow/README.md +56 -0
  114. package/docs/MANUAL-INSTALL.md +456 -0
  115. package/package.json +52 -0
  116. package/tools/check-framework-purity.sh +91 -0
  117. package/tools/measure-tokens.sh +169 -0
  118. package/tools/validate-adapter-output.sh +611 -0
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # CONDUCTOR universal hook template
4
+ # hook_id: stop-cache-hit-baseline-check
5
+ # trigger: stop
6
+ # action: Read latest Claude Code session JSONL, compute cache hit rate, emit
7
+ # a non-blocking diagnostic reminder when below baseline.
8
+ # compile_targets: claude
9
+ # fallback: rule-text-reminder
10
+ #
11
+ # Generated by adapters/<tool>/transform.sh.
12
+ #
13
+ # Enforces:
14
+ # - meta-discipline.md token-economy section (cache hit baseline)
15
+ #
16
+ # Behavior:
17
+ # 1. Locate latest session JSONL under ~/.claude/projects/<encoded>/*.jsonl.
18
+ # 2. Sum cache_read_input_tokens vs uncached input_tokens via python3.
19
+ # 3. If hit_rate < ${CONDUCTOR_CACHE_HIT_FLOOR_PERCENT}% AND total
20
+ # effective input tokens >= ${CONDUCTOR_CACHE_TOTAL_FLOOR}, emit a
21
+ # stderr reminder listing the 5 candidate anti-patterns.
22
+ # 4. exit 0 (non-blocking).
23
+ #
24
+ # Override (silence reminder, e.g. CI sessions):
25
+ # ${CONDUCTOR_CACHE_SKIP_ENV}=1
26
+ #
27
+ # Skip conditions:
28
+ # - python3 missing
29
+ # - no session JSONL found
30
+ # - session token volume below floor (too short to draw conclusions)
31
+ # - skip env var set
32
+
33
+ set -u
34
+
35
+ # Placeholders filled by adapters/<tool>/transform.sh:
36
+ # ${CONDUCTOR_CACHE_HIT_FLOOR_PERCENT} — target floor (default 80)
37
+ # ${CONDUCTOR_CACHE_TOTAL_FLOOR} — minimum total tokens before report (default 5000)
38
+ # ${CONDUCTOR_CACHE_SKIP_ENV} — env var to silence (default CONDUCTOR_SKIP_CACHE_CHECK)
39
+ # ${CONDUCTOR_ANTI_PATTERNS_PATH} — relative path to anti-patterns doc
40
+
41
+ FLOOR_PCT="${CONDUCTOR_CACHE_HIT_FLOOR_PERCENT:-80}"
42
+ TOTAL_FLOOR="${CONDUCTOR_CACHE_TOTAL_FLOOR:-5000}"
43
+ SKIP_ENV_NAME="${CONDUCTOR_CACHE_SKIP_ENV:-CONDUCTOR_SKIP_CACHE_CHECK}"
44
+ ANTI_PATTERNS_DOC="${CONDUCTOR_ANTI_PATTERNS_PATH:-core/anti-patterns/README.md}"
45
+
46
+ # Honor user opt-out without inspecting payload.
47
+ SKIP_VAL="$(/usr/bin/printenv "$SKIP_ENV_NAME" 2>/dev/null || true)"
48
+ [ "$SKIP_VAL" = "1" ] && exit 0
49
+
50
+ command -v python3 >/dev/null 2>&1 || exit 0
51
+
52
+ # Allow tests to inject a fixture directly.
53
+ FIXTURE="${CONDUCTOR_CACHE_TEST_FIXTURE:-}"
54
+ SESSION_PATH=""
55
+
56
+ if [ -n "$FIXTURE" ]; then
57
+ [ -f "$FIXTURE" ] || exit 0
58
+ SESSION_PATH="$FIXTURE"
59
+ else
60
+ # Find newest *.jsonl under ~/.claude/projects/.
61
+ if [ ! -d "$HOME/.claude/projects" ]; then
62
+ exit 0
63
+ fi
64
+ SESSION_PATH=$(/usr/bin/find "$HOME/.claude/projects" -name '*.jsonl' -type f 2>/dev/null \
65
+ | while IFS= read -r f; do
66
+ m=$(/usr/bin/stat -f '%m' "$f" 2>/dev/null || /usr/bin/stat -c '%Y' "$f" 2>/dev/null || echo 0)
67
+ printf '%s\t%s\n' "$m" "$f"
68
+ done \
69
+ | /usr/bin/sort -rn \
70
+ | /usr/bin/head -n 1 \
71
+ | /usr/bin/cut -f2-)
72
+ [ -n "$SESSION_PATH" ] && [ -f "$SESSION_PATH" ] || exit 0
73
+ fi
74
+
75
+ # Parse + decide. python3 prints a single line: "<hit_rate> <total_eff>".
76
+ RESULT=$(SESSION="$SESSION_PATH" python3 - <<'PYEOF' 2>/dev/null
77
+ import json, os, sys
78
+ path = os.environ.get("SESSION", "")
79
+ total_input = 0
80
+ total_cache_read = 0
81
+ try:
82
+ with open(path, "r", errors="replace") as f:
83
+ for line in f:
84
+ line = line.strip()
85
+ if not line:
86
+ continue
87
+ try:
88
+ obj = json.loads(line)
89
+ except Exception:
90
+ continue
91
+ usage = (obj.get("message") or {}).get("usage") or {}
92
+ total_input += usage.get("input_tokens") or 0
93
+ total_cache_read += usage.get("cache_read_input_tokens") or 0
94
+ except Exception:
95
+ sys.exit(0)
96
+ total_eff = total_input + total_cache_read
97
+ hit = (total_cache_read / total_eff * 100.0) if total_eff > 0 else 100.0
98
+ print(f"{hit:.1f} {total_eff}")
99
+ PYEOF
100
+ )
101
+
102
+ [ -n "$RESULT" ] || exit 0
103
+
104
+ HIT_RATE="${RESULT% *}"
105
+ TOTAL_EFF="${RESULT##* }"
106
+
107
+ # Floor check (integer compare on TOTAL_EFF).
108
+ case "$TOTAL_EFF" in
109
+ ''|*[!0-9]*) exit 0 ;;
110
+ esac
111
+ [ "$TOTAL_EFF" -lt "$TOTAL_FLOOR" ] && exit 0
112
+
113
+ # Compare HIT_RATE (float) to FLOOR_PCT (int) using awk.
114
+ BELOW=$(/usr/bin/awk -v h="$HIT_RATE" -v f="$FLOOR_PCT" 'BEGIN { print (h+0 < f+0) ? "1" : "0" }')
115
+ [ "$BELOW" = "1" ] || exit 0
116
+
117
+ # Emit non-blocking reminder to stderr (Stop hook stderr is surfaced to user).
118
+ /bin/cat >&2 <<EOF
119
+
120
+ [stop-hook cache-baseline] Session cache hit rate: ${HIT_RATE}% (floor ${FLOOR_PCT}%, eff input ${TOTAL_EFF} tokens).
121
+
122
+ Likely causes (top 5 anti-patterns):
123
+ 1. Dynamic prompt prefix — values change every turn, breaking cache key.
124
+ 2. Large-file Read without offset/limit — pulls entire file into context.
125
+ 3. Monolithic rule file edited mid-session — invalidates cached system prompt.
126
+ 4. No sub-agent isolation — long-running task accumulates context in main thread.
127
+ 5. Frequent CLAUDE.md / settings edits during session — busts the prefix cache.
128
+
129
+ Diagnostic guide: ${ANTI_PATTERNS_DOC}
130
+ Silence (intentional): export ${SKIP_ENV_NAME}=1
131
+
132
+ EOF
133
+ exit 0
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # CONDUCTOR universal hook template
4
+ # hook_id: stop-r6-review-check
5
+ # trigger: stop
6
+ # action: Remind to run pre-merge code review (Q2) when feature/fix/chore branch
7
+ # has a recently-pushed open PR.
8
+ # compile_targets: claude
9
+ # fallback: rule-text-reminder
10
+ #
11
+ # Generated by adapters/<tool>/transform.sh.
12
+ #
13
+ # Enforces:
14
+ # - quality-gates.md Q2 (pre-merge code review on open PR)
15
+ #
16
+ # Skip conditions:
17
+ # - current branch is in CONDUCTOR_DIRECT_PUSH_BRANCHES (no PR expected)
18
+ # - no open PR for current branch
19
+ # - no push in last STALE_MINUTES (nothing new to review)
20
+ # - cool-down flag present (review reminder already shown recently)
21
+
22
+ set -u
23
+
24
+ # Placeholders filled by adapters/<tool>/transform.sh:
25
+ # ${CONDUCTOR_DIRECT_PUSH_BRANCHES} — pipe-separated branch list (default: develop|main|release|HEAD)
26
+ # ${CONDUCTOR_STALE_MINUTES} — recent-push window (default 30)
27
+ # ${CONDUCTOR_COOLDOWN_SECONDS} — cool-down per PR (default 1800 = 30 min)
28
+ # ${CONDUCTOR_REVIEW_COMMAND} — slash command or script to run review (default /code-review)
29
+
30
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
31
+ cd "$REPO_ROOT" || exit 0
32
+
33
+ command -v git >/dev/null 2>&1 || exit 0
34
+ command -v gh >/dev/null 2>&1 || exit 0
35
+
36
+ DIRECT_PUSH="${CONDUCTOR_DIRECT_PUSH_BRANCHES:-develop|main|release|HEAD}"
37
+ STALE_MINUTES="${CONDUCTOR_STALE_MINUTES:-30}"
38
+ COOLDOWN="${CONDUCTOR_COOLDOWN_SECONDS:-1800}"
39
+ REVIEW_COMMAND="${CONDUCTOR_REVIEW_COMMAND:-/code-review}"
40
+
41
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
42
+ [ -n "$BRANCH" ] || exit 0
43
+
44
+ # Skip direct-push branches.
45
+ if echo "$BRANCH" | /usr/bin/grep -qE "^(${DIRECT_PUSH})$"; then
46
+ exit 0
47
+ fi
48
+
49
+ # Recent-push detection.
50
+ THIRTY_MIN_AGO=$(date -v-"${STALE_MINUTES}"M '+%s' 2>/dev/null || date -d "${STALE_MINUTES} minutes ago" '+%s' 2>/dev/null)
51
+ [ -n "$THIRTY_MIN_AGO" ] || exit 0
52
+
53
+ RECENT_PUSH=$(git reflog --date=unix 2>/dev/null \
54
+ | /usr/bin/awk -v t="$THIRTY_MIN_AGO" '
55
+ /push/ {
56
+ if (match($0, /\{([0-9]+)\}/, m)) {
57
+ if (m[1]+0 >= t+0) { print; exit }
58
+ }
59
+ }')
60
+ [ -n "$RECENT_PUSH" ] || exit 0
61
+
62
+ # Open PR for current branch.
63
+ PR_JSON=$(gh pr list --head "$BRANCH" --state open --json url,number --limit 1 2>/dev/null)
64
+ [ -n "$PR_JSON" ] && [ "$PR_JSON" != "[]" ] || exit 0
65
+
66
+ PR_URL=$(printf '%s' "$PR_JSON" | /usr/bin/sed -n 's/.*"url":"\([^"]*\)".*/\1/p')
67
+ PR_NUM=$(printf '%s' "$PR_JSON" | /usr/bin/sed -n 's/.*"number":\([0-9]*\).*/\1/p')
68
+ [ -n "$PR_NUM" ] || exit 0
69
+
70
+ # Cool-down per PR.
71
+ FLAG="/tmp/conductor-q2-flag-${USER:-unknown}-${PR_NUM}"
72
+ if [ -f "$FLAG" ]; then
73
+ FLAG_AGE=$(( $(date +%s) - $(/usr/bin/stat -f %m "$FLAG" 2>/dev/null || /usr/bin/stat -c %Y "$FLAG" 2>/dev/null || echo 0) ))
74
+ [ "$FLAG_AGE" -lt "$COOLDOWN" ] && exit 0
75
+ fi
76
+ touch "$FLAG"
77
+
78
+ /bin/cat <<EOF
79
+ {"decision":"block","reason":"[stop-hook Q2] Open PR #${PR_NUM} on branch \`${BRANCH}\` with recent push. Run \`${REVIEW_COMMAND} ${PR_URL}\` before merge per universal-rules/quality-gates.md Q2 (pre-merge code review). Docs-only PRs are exempt."}
80
+ EOF
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # CONDUCTOR universal hook template
4
+ # hook_id: stop-session-log-check
5
+ # trigger: stop
6
+ # action: Block stop when recent commits exist but CURRENT_WORK.md or specs are stale.
7
+ # compile_targets: claude
8
+ # fallback: rule-text-reminder
9
+ #
10
+ # Generated by adapters/<tool>/transform.sh.
11
+ #
12
+ # Enforces:
13
+ # - operations.md O2 (CURRENT_WORK.md must update when work happens)
14
+ # - spec-as-you-go.md W3 (source change → spec update in same turn)
15
+ #
16
+ # Exit code meaning in Stop hooks (Claude Code):
17
+ # 0 with no JSON output → allow stop (default)
18
+ # 0 with {"decision":"block"} → inject reason, continue turn
19
+
20
+ set -u
21
+
22
+ # Placeholders filled by adapters/<tool>/transform.sh:
23
+ # ${CONDUCTOR_PROJECT_DIR} — absolute path to project root
24
+ # ${CONDUCTOR_STALE_MINUTES} — staleness threshold (default 30)
25
+ # ${CONDUCTOR_COOLDOWN_SECONDS} — cool-down between reminders (default 600)
26
+ # ${CONDUCTOR_SOURCE_GLOB} — file extensions tracked as source (default ts|tsx)
27
+ # ${CONDUCTOR_SPEC_PATH} — path prefix that counts as spec update (default docs/specs/)
28
+ # ${CONDUCTOR_PLAN_THRESHOLD} — source-file count above which a .plan.md is required (default 5)
29
+
30
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
31
+ cd "$REPO_ROOT" || exit 0
32
+
33
+ CURRENT_WORK="docs/CURRENT_WORK.md"
34
+ [ -f "$CURRENT_WORK" ] || exit 0
35
+
36
+ STALE_MINUTES="${CONDUCTOR_STALE_MINUTES:-30}"
37
+ COOLDOWN="${CONDUCTOR_COOLDOWN_SECONDS:-600}"
38
+ SRC_GLOB="${CONDUCTOR_SOURCE_GLOB:-ts|tsx}"
39
+ SPEC_PATH="${CONDUCTOR_SPEC_PATH:-docs/specs/}"
40
+ PLAN_THRESHOLD="${CONDUCTOR_PLAN_THRESHOLD:-5}"
41
+
42
+ RECENT_COMMITS=$(git log --since="${STALE_MINUTES} minutes ago" --oneline 2>/dev/null | /usr/bin/wc -l | /usr/bin/tr -d ' ')
43
+ if [ "$RECENT_COMMITS" -eq 0 ]; then
44
+ exit 0
45
+ fi
46
+
47
+ # Cool-down: avoid double-reminding within COOLDOWN seconds.
48
+ FLAG="/tmp/conductor-stop-doc-flag-${USER:-unknown}"
49
+ if [ -f "$FLAG" ]; then
50
+ LAST=$(cat "$FLAG" 2>/dev/null || echo 0)
51
+ NOW=$(date +%s)
52
+ DELTA=$((NOW - LAST))
53
+ if [ "$DELTA" -lt "$COOLDOWN" ]; then
54
+ exit 0
55
+ fi
56
+ fi
57
+
58
+ # Check 1: CURRENT_WORK.md freshness.
59
+ WORK_STALE=0
60
+ if [ -z "$(/usr/bin/find "$CURRENT_WORK" -mmin -"${STALE_MINUTES}" 2>/dev/null)" ]; then
61
+ WORK_STALE=1
62
+ fi
63
+
64
+ # Check 2: Spec-as-you-go (source files changed but no spec touched).
65
+ SPEC_STALE=0
66
+ SRC_CHANGES=$(git diff --name-only HEAD~"${RECENT_COMMITS}"..HEAD 2>/dev/null | /usr/bin/grep -cE "\\.(${SRC_GLOB})$" || echo 0)
67
+ SPEC_CHANGES=$(git diff --name-only HEAD~"${RECENT_COMMITS}"..HEAD 2>/dev/null | /usr/bin/grep -c "${SPEC_PATH}" || echo 0)
68
+ if [ "$SRC_CHANGES" -gt 3 ] && [ "$SPEC_CHANGES" -eq 0 ]; then
69
+ SPEC_STALE=1
70
+ fi
71
+
72
+ # Check 3: Plan-first (W1.1) — Medium/Large scope source changes require a .plan.md.
73
+ # Mirrors the reference adopter's stop-session-log-check Check 4. Per workflow.md W1.1,
74
+ # 5+ source-file changes signal Medium scope or larger; orchestrator must produce a .plan.md
75
+ # before implementation. Hook fires post-hoc when no plan file exists in the diff.
76
+ PLAN_STALE=0
77
+ PLAN_CHANGES=$(git diff --name-only HEAD~"${RECENT_COMMITS}"..HEAD 2>/dev/null | /usr/bin/grep -c "\\.plan\\.md$" || echo 0)
78
+ if [ "$SRC_CHANGES" -ge "$PLAN_THRESHOLD" ] && [ "$PLAN_CHANGES" -eq 0 ]; then
79
+ PLAN_STALE=1
80
+ fi
81
+
82
+ REASONS=""
83
+ if [ "$WORK_STALE" -eq 1 ]; then
84
+ REASONS="${REASONS}[CURRENT_WORK.md stale] Update docs/CURRENT_WORK.md with session log. "
85
+ fi
86
+ if [ "$SPEC_STALE" -eq 1 ]; then
87
+ REASONS="${REASONS}[SPEC-AS-YOU-GO] ${SRC_CHANGES} source files changed but 0 spec files updated. Update relevant ${SPEC_PATH}*.md files to reflect new/changed features. "
88
+ fi
89
+ if [ "$PLAN_STALE" -eq 1 ]; then
90
+ REASONS="${REASONS}[PLAN-FIRST] ${SRC_CHANGES} source files changed (>=${PLAN_THRESHOLD}) with no .plan.md in diff. Per workflow.md W1.1, Medium/Large scope requires a .plan.md before implementation. Add one retroactively or split the change. "
91
+ fi
92
+
93
+ if [ -z "$REASONS" ]; then
94
+ exit 0
95
+ fi
96
+
97
+ date +%s > "$FLAG"
98
+
99
+ /bin/cat <<JSON
100
+ {"decision":"block","reason":"[stop-hook] ${RECENT_COMMITS} commit(s) in last ${STALE_MINUTES} min. ${REASONS}Per universal-rules/operations.md O2 + spec-as-you-go.md W3 + workflow.md W1.1."}
101
+ JSON
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # CONDUCTOR universal hook template
4
+ # hook_id: stop-trajectory-log
5
+ # trigger: stop
6
+ # action: On session stop, append a normalized trajectory pointer record to
7
+ # .conductor/trajectories/index.jsonl for the Reflector to consume.
8
+ # compile_targets: claude
9
+ # fallback: rule-text-reminder
10
+ #
11
+ # Generated by adapters/<tool>/transform.sh.
12
+ #
13
+ # Enforces:
14
+ # - recipes/self-improvement.md (Observe step)
15
+ #
16
+ # Behavior (fail-open, non-blocking):
17
+ # 1. Read the Stop hook's stdin JSON (Claude provides session_id + transcript_path).
18
+ # 2. UPSERT one pointer record per session into the trajectory index.
19
+ # 3. Always exit 0. Never block session stop.
20
+ #
21
+ # Reading transcript_path from stdin (rather than scanning ~/.claude/projects for the
22
+ # newest *.jsonl) makes provenance exact — a concurrent session in another project can
23
+ # no longer be mis-recorded as this project's trajectory. This matches the stdin-based
24
+ # portable logger used by the non-Claude adapters (core/reflector/trajectory-log.sh).
25
+ #
26
+ # Override (disable logging):
27
+ # set CONDUCTOR_SKIP_TRAJLOG=1 (or the name in CONDUCTOR_TRAJLOG_SKIP_ENV)
28
+ #
29
+ # Skip conditions: self-improvement recipe not installed (no .conductor/reflect/);
30
+ # no stdin JSON; not inside a project dir.
31
+
32
+ set -u
33
+
34
+ # Runtime env overrides (defaults apply if unset — these are NOT compile-time
35
+ # placeholders; the hook reads them at runtime):
36
+ # CONDUCTOR_TRAJLOG_SKIP_ENV name of the opt-out var (default CONDUCTOR_SKIP_TRAJLOG)
37
+ # CONDUCTOR_TRAJ_DIR trajectory dir (default .conductor/trajectories)
38
+ # CONDUCTOR_REFLECT_DIR opt-in gate dir (default .conductor/reflect)
39
+ # CONDUCTOR_TRAJ_TEST_FIXTURE test mode: bypass the cwd anchor + opt-in gate
40
+ SKIP_ENV_NAME="${CONDUCTOR_TRAJLOG_SKIP_ENV:-CONDUCTOR_SKIP_TRAJLOG}"
41
+ TRAJ_DIR="${CONDUCTOR_TRAJ_DIR:-.conductor/trajectories}"
42
+
43
+ # Honor user opt-out.
44
+ SKIP_VAL="$(/usr/bin/printenv "$SKIP_ENV_NAME" 2>/dev/null || true)"
45
+ [ "$SKIP_VAL" = "1" ] && exit 0
46
+
47
+ # Anchor to the project root. A hook's cwd is not guaranteed to be the project
48
+ # root; the emitted hook lives at <project>/.claude/hooks/, so ../.. is the root.
49
+ # This makes the opt-in gate and the write path resolve correctly regardless of
50
+ # the session's cwd. Test mode (CONDUCTOR_TRAJ_TEST_FIXTURE set) keeps the current
51
+ # directory so tests control the layout.
52
+ if [ -z "${CONDUCTOR_TRAJ_TEST_FIXTURE:-}" ]; then
53
+ _self_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" || exit 0
54
+ _proj_root="$(cd "$_self_dir/../.." 2>/dev/null && pwd)" || exit 0
55
+ cd "$_proj_root" || exit 0
56
+ fi
57
+
58
+ # Opt-in gate: the self-improvement recipe creates .conductor/reflect/ at install.
59
+ # Without it this hook is a no-op — trajectory logging is the "observe" step of an
60
+ # opt-in capability, so it must not fire for adopters who did not opt in. Test mode
61
+ # bypasses the gate.
62
+ REFLECT_DIR="${CONDUCTOR_REFLECT_DIR:-.conductor/reflect}"
63
+ if [ -z "${CONDUCTOR_TRAJ_TEST_FIXTURE:-}" ] && [ ! -d "$REFLECT_DIR" ]; then
64
+ exit 0
65
+ fi
66
+
67
+ # Read the Stop hook's stdin JSON (Claude pipes it). A manual run with no piped stdin
68
+ # is a no-op; a test pipes the same JSON.
69
+ [ -t 0 ] && exit 0
70
+ INPUT="$(/bin/cat 2>/dev/null || true)"
71
+ [ -n "$INPUT" ] || exit 0
72
+
73
+ # Tolerant flat-JSON string extraction (snake/camel).
74
+ jval() { printf '%s' "$1" | /usr/bin/grep -oE "\"($2)\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | /usr/bin/head -n1 | /usr/bin/sed -E 's/^.*:[[:space:]]*"([^"]*)"$/\1/'; }
75
+ TRANSCRIPT="$(jval "$INPUT" 'transcript_path|transcriptPath')"
76
+ SESSION_ID="$(jval "$INPUT" 'session_id|sessionId')"
77
+ [ -n "$SESSION_ID" ] || SESSION_ID="unknown"
78
+
79
+ # UPSERT one record per session (a session may stop more than once).
80
+ esc() { printf '%s' "$1" | /usr/bin/sed 's/\\/\\\\/g; s/"/\\"/g'; }
81
+ /bin/mkdir -p "$TRAJ_DIR" 2>/dev/null || exit 0
82
+ TS="$(/bin/date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || echo unknown)"
83
+ GIT_HEAD="$(git rev-parse --short HEAD 2>/dev/null || echo none)"
84
+ CWD="$(pwd)"
85
+ LINE="$(printf '{"ts":"%s","session":"%s","transcript":"%s","git_head":"%s","cwd":"%s"}' \
86
+ "$TS" "$(esc "$SESSION_ID")" "$(esc "$TRANSCRIPT")" "$GIT_HEAD" "$(esc "$CWD")")"
87
+
88
+ IDX="$TRAJ_DIR/index.jsonl"
89
+ if [ -f "$IDX" ]; then
90
+ _tmp="$IDX.$$.tmp"
91
+ /usr/bin/grep -vF "\"session\":\"$(esc "$SESSION_ID")\"" "$IDX" > "$_tmp" 2>/dev/null || : > "$_tmp"
92
+ /bin/mv "$_tmp" "$IDX" 2>/dev/null || true
93
+ fi
94
+ printf '%s\n' "$LINE" >> "$IDX"
95
+
96
+ exit 0
@@ -0,0 +1,114 @@
1
+ # Memory pattern — worked examples (PLACEHOLDER — P1 fills with sanitized real examples)
2
+
3
+ > **Status (P0 foundation)**: this file shows the SHAPE of each memory type via skeleton examples. P1 will fill with sanitized real examples derived from the reference adopter's accumulated memory.
4
+
5
+ ## Example 1 — type: `user`
6
+
7
+ **Filename**: `user_profile.md`
8
+
9
+ ```markdown
10
+ ---
11
+ name: user-profile
12
+ description: who the user is and how they collaborate
13
+ type: user
14
+ ---
15
+
16
+ - Korean speaker; bilingual onboarding preferred for headline material.
17
+ - Senior developer; can read code in TS / Python / Go / Rust without explanation.
18
+ - New to <some-specific-area>; benefits from concrete examples there.
19
+ - Prefers terse responses; no trailing summary unless asked.
20
+ - Reviews PRs same day; expects fast iteration.
21
+ ```
22
+
23
+ **Use it for**: knowing how to format responses, what background context to assume, what NOT to over-explain.
24
+
25
+ ---
26
+
27
+ ## Example 2 — type: `feedback`
28
+
29
+ **Filename**: `feedback_no_silent_recovery.md`
30
+
31
+ ```markdown
32
+ ---
33
+ name: no-silent-recovery
34
+ description: when a rule is broken mid-turn, surface it explicitly; never silently fix and move on
35
+ type: feedback
36
+ ---
37
+
38
+ When you realize you broke a rule mid-turn (skipped a phase, used the wrong agent type, etc.), STOP and call it out in the next user-facing message. Then fix the gap. Continue.
39
+
40
+ **Why**: silent recovery hides a class of recurring bugs from the user, who then can't help correct the upstream cause. Surfaced violations build trust over time.
41
+
42
+ **How to apply**: in the next message after the violation, lead with one line acknowledging the rule + the fix. Don't bury it in a bullet at the end. Don't omit it.
43
+ ```
44
+
45
+ **Use it for**: any rule violation. Read this memory before deciding to "just quietly do better next time".
46
+
47
+ ---
48
+
49
+ ## Example 3 — type: `project`
50
+
51
+ **Filename**: `project_launch_blockers.md`
52
+
53
+ ```markdown
54
+ ---
55
+ name: launch-blockers
56
+ description: pre-launch blockers and their resolution dates
57
+ type: project
58
+ ---
59
+
60
+ - **Payment-provider live activation**: blocked on business registration. Resolved YYYY-MM-DD. NOW UNBLOCKED.
61
+ - **Bank-aggregator production**: deferred to post-launch (manual entry MVP first). NOT a launch blocker.
62
+ - **iOS push notifications**: pending app store review. Target: YYYY-MM-DD.
63
+
64
+ **Why**: avoids re-asking the user the same status question every session.
65
+
66
+ **How to apply**: before recommending work on a blocked item, check this list. If the entry says BLOCKED, surface the blocker before doing the work.
67
+ ```
68
+
69
+ **Use it for**: project-state questions. Decay fast — verify before acting on entries older than 2 weeks.
70
+
71
+ ---
72
+
73
+ ## Example 4 — type: `reference`
74
+
75
+ **Filename**: `reference_external_systems.md`
76
+
77
+ ```markdown
78
+ ---
79
+ name: external-systems
80
+ description: where information lives in external systems
81
+ type: reference
82
+ ---
83
+
84
+ - **Payment provider live IDs (products, prices, webhooks)**: provider dashboard → Live mode → Products. Backup: `<your-secrets-vault>/payment-live.json`.
85
+ - **DNS records**: DNS provider account `<your-dns-org>`. CNAME / A records documented in `docs/legal/dns-snapshot-YYYY-MM-DD.md`.
86
+ - **Email infra dashboard**: <your-email-provider>.com console.
87
+ - **Cron monitoring**: hosting provider's deployments tab → Cron Jobs.
88
+ ```
89
+
90
+ **Use it for**: "where do I find X?" questions. NEVER include actual secrets in memory entries — only pointer to the source-of-truth.
91
+
92
+ ---
93
+
94
+ ## MEMORY.md index — example
95
+
96
+ When you save a memory file, add a one-line pointer to `MEMORY.md`:
97
+
98
+ ```markdown
99
+ - [User Profile](user_profile.md) — Korean senior dev; terse responses; bilingual onboarding
100
+ - [No Silent Recovery](feedback_no_silent_recovery.md) — surface rule violations explicitly
101
+ - [Launch Blockers](project_launch_blockers.md) — payment-provider live UNBLOCKED; iOS push pending
102
+ - [External Systems](reference_external_systems.md) — pointers to payment / DNS / hosting dashboards
103
+ ```
104
+
105
+ The index is ALWAYS LOADED at session start (when the tool supports it). Keep ≤ 200 lines. Archive older entries by removing them from the index when no longer relevant; the source files stay on disk in case you need to retrieve.
106
+
107
+ ## Pattern conventions
108
+
109
+ - File names: `<type>_<short-slug>.md` (snake_case).
110
+ - Title in body: human-readable.
111
+ - Frontmatter `description:` is what the index uses; keep ≤ 80 chars.
112
+ - For `feedback` and `project`: always include **Why** and **How to apply** lines. Without these, the entry is just trivia.
113
+ - For `user`: bullet list of facts. No need for Why/How.
114
+ - For `reference`: bullet list of pointers. NEVER inline the secret/data — just pointer to source.
@@ -0,0 +1,133 @@
1
+ # `core/memory-pattern/` — 4-type memory pattern (universal)
2
+
3
+ CONDUCTOR's memory pattern. Tool-agnostic in *intent*; tool-native in *mechanism*.
4
+
5
+ ## The 4 types
6
+
7
+ | Type | When to save | Example |
8
+ |---|---|---|
9
+ | **user** | Learn role, preferences, knowledge level | "Senior Go dev, new to React" |
10
+ | **feedback** | User corrects OR validates an approach | "Don't mock the DB in integration tests — burned by mock/prod divergence" |
11
+ | **project** | Who's doing what, why, by when (convert relative dates to absolute) | "Merge freeze begins 2026-03-05 for mobile release" |
12
+ | **reference** | Where info lives in external systems | "Pipeline bugs tracked in Linear project INGEST" |
13
+
14
+ ## What NOT to save
15
+
16
+ - Code patterns / conventions / file paths (read the code).
17
+ - Git history (use `git log`).
18
+ - Debugging fix recipes (the fix is in the commit).
19
+ - Anything in CLAUDE.md / `.cursorrules` / equivalent (those rules are universal).
20
+ - Ephemeral state (use TaskCreate or `docs/CURRENT_WORK.md` instead).
21
+
22
+ ## Where memory lives — per tool
23
+
24
+ | Tool | Built-in directory? | Recommended path |
25
+ |---|---|---|
26
+ | Claude Code | ✅ | `~/.claude/projects/<encoded-project-path>/memory/` |
27
+ | Cursor | ❌ | `.memory/` at project root (gitignored) — DIY |
28
+ | Copilot | ❌ | `.memory/` (DIY) |
29
+ | Gemini CLI | ❌ | `.memory/` (DIY) |
30
+ | Codex | ❌ | `.memory/` (DIY) |
31
+ | Windsurf | ❌ | `.memory/` (DIY) |
32
+
33
+ The pattern is the same. The directory location varies. On non-Claude tools, add `.memory/` to your `.gitignore` so personal memory entries don't leak into the repo.
34
+
35
+ ## File structure
36
+
37
+ Inside the memory directory:
38
+
39
+ ```
40
+ memory/
41
+ ├── MEMORY.md # Index (always loaded into context, ≤ 200 lines)
42
+ ├── user_*.md # User profile, preferences, role, knowledge
43
+ ├── feedback_*.md # Corrections + validated approaches
44
+ ├── project_*.md # Ongoing work, goals, deadlines
45
+ └── reference_*.md # Pointers to external systems
46
+ ```
47
+
48
+ ## How to save
49
+
50
+ 1. Write content to its own file with frontmatter:
51
+
52
+ ```markdown
53
+ ---
54
+ name: short-name
55
+ description: one-line for relevance matching
56
+ type: user|feedback|project|reference
57
+ ---
58
+
59
+ Body. For feedback/project: lead with rule, then **Why:** and **How to apply:** lines.
60
+ ```
61
+
62
+ 2. Add one-line pointer to `MEMORY.md`: `- [Title](file.md) — one-line hook`
63
+
64
+ ## Lessons (Reflector-produced feedback)
65
+
66
+ Lessons distilled by the `reflector` role are a specialization of the `feedback`
67
+ type. File name: `feedback_lesson-<slug>.md`. They carry the standard three keys
68
+ plus reflector bookkeeping keys:
69
+
70
+ ```markdown
71
+ ---
72
+ name: lesson-<slug>
73
+ description: one-line for relevance matching
74
+ type: feedback
75
+ id: lesson-<slug> # stable id for delta ops
76
+ added: <YYYY-MM-DD>
77
+ source: <session-id | commit | retro-line> # provenance (required)
78
+ hits: 1 # times reinforced
79
+ last_used: <YYYY-MM-DD>
80
+ status: active # active | stale | merged
81
+ confidence: medium # low | medium | high
82
+ ---
83
+
84
+ <the lesson, one paragraph>
85
+
86
+ **Why:** <why this matters>
87
+ **How to apply:** <the concrete change to make next time>
88
+ ```
89
+
90
+ Delta operations (applied by a human, or by the orchestrator on explicit GO):
91
+ - `ADD` — new `feedback_lesson-*.md`.
92
+ - `UPDATE` — bump `hits`, raise `confidence`, or refine wording of an existing lesson.
93
+ - `STALE` — set `status: stale`; keep the file, drop its `MEMORY.md` index line.
94
+
95
+ Proposals are staged (not applied) in `docs/REFLECTION-PROPOSALS.md`. The
96
+ deterministic prune script (`.conductor/reflect/prune-lessons.sh`) keeps the
97
+ active set bounded: it marks decayed and dead-path lessons `status: stale`
98
+ (non-destructive) and removes only exact byte-duplicate files.
99
+
100
+ ## Anti-staleness
101
+
102
+ Before recommending FROM memory, verify it's still true:
103
+ - File path mentioned? Check it exists (`ls`, `Glob`).
104
+ - Function/flag mentioned? `Grep` for it.
105
+ - Recent activity claim? Prefer `git log` over recalling.
106
+
107
+ "The memory says X exists" ≠ "X exists now."
108
+
109
+ ## Relationship to in-repo `docs/`
110
+
111
+ | | `docs/` (in repo) | memory/ (per-user) |
112
+ |---|---|---|
113
+ | Travels with code | YES | NO |
114
+ | Shared with collaborators | YES | NO |
115
+ | Persists for the user | (if not deleted) | YES, across sessions/branches/clones |
116
+ | Contains personal taste | NO (project conventions only) | YES |
117
+ | Contains feedback history | NO | YES |
118
+
119
+ The two are complementary. `docs/` is the project's brain; memory is YOUR brain on top of the project.
120
+
121
+ ## Tool-specific enforcement
122
+
123
+ > **Claude-only mechanism**: Claude Code auto-loads `MEMORY.md` at session start (when configured) and surfaces relevant `*.md` files based on the user's question.
124
+
125
+ > **Other tools**: paste relevant memory entries into your prompt manually, or use the tool's "include this file" feature (Cursor: @-mention; Copilot: workspace context).
126
+
127
+ ## Examples
128
+
129
+ See `EXAMPLES.md` for tool-agnostic worked examples of each memory type.
130
+
131
+ ## Status (P0 foundation)
132
+
133
+ `EXAMPLES.md` is a placeholder. P1 fills with sanitized real examples derived from the reference adopter.