trellis 3.1.20 → 3.1.30
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/README.md +25 -1
- package/dist/cli/index.js +193 -25
- package/dist/cli/repo-path.d.ts.map +1 -1
- package/dist/db/index.js +4 -4
- package/dist/federation/remote-manager.d.ts +30 -0
- package/dist/federation/remote-manager.d.ts.map +1 -0
- package/dist/federation/types.d.ts +41 -0
- package/dist/federation/types.d.ts.map +1 -0
- package/dist/index-4gknc19b.js +166 -0
- package/dist/{index-3qrxzwe4.js → index-ncckgtrk.js} +1198 -157
- package/dist/index.js +2 -1
- package/dist/remote-manager-n71bmcy1.js +214 -0
- package/dist/scaffold/write.d.ts.map +1 -1
- package/dist/server/index.js +4 -4
- package/package.json +1 -1
|
@@ -619,6 +619,44 @@ var init_profile = () => {};
|
|
|
619
619
|
// src/scaffold/write.ts
|
|
620
620
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync3 } from "fs";
|
|
621
621
|
import { join as join4 } from "path";
|
|
622
|
+
function writeTrellisHooks(rootPath, ide) {
|
|
623
|
+
const hooksDir = join4(rootPath, ".cursor", "hooks");
|
|
624
|
+
const trellisHarnessDir = join4(hooksDir, "trellis-harness");
|
|
625
|
+
const adaptersDir = join4(hooksDir, "adapters");
|
|
626
|
+
if (!existsSync3(trellisHarnessDir)) {
|
|
627
|
+
mkdirSync2(trellisHarnessDir, { recursive: true });
|
|
628
|
+
}
|
|
629
|
+
if (!existsSync3(adaptersDir)) {
|
|
630
|
+
mkdirSync2(adaptersDir, { recursive: true });
|
|
631
|
+
}
|
|
632
|
+
writeFileSync2(join4(trellisHarnessDir, "pre-prompt-recall.sh"), renderPrePromptRecallScript(), "utf-8");
|
|
633
|
+
writeFileSync2(join4(trellisHarnessDir, "post-tool-oplog.sh"), renderPostToolOplogScript(), "utf-8");
|
|
634
|
+
writeFileSync2(join4(trellisHarnessDir, "post-tool-memory-capture.sh"), renderPostToolMemoryCaptureScript(), "utf-8");
|
|
635
|
+
writeFileSync2(join4(trellisHarnessDir, "stop-triage.sh"), renderStopTriageScript(), "utf-8");
|
|
636
|
+
writeFileSync2(join4(trellisHarnessDir, "bug-intake.sh"), renderBugIntakeScript(), "utf-8");
|
|
637
|
+
writeFileSync2(join4(trellisHarnessDir, "bug-investigate.sh"), renderBugInvestigateScript(), "utf-8");
|
|
638
|
+
writeFileSync2(join4(trellisHarnessDir, "milestone-triage.sh"), renderMilestoneTriageScript(), "utf-8");
|
|
639
|
+
writeFileSync2(join4(trellisHarnessDir, "cycle-planning.sh"), renderCyclePlanningScript(), "utf-8");
|
|
640
|
+
const adapterName = ide === "windsurf" ? "cascade-adapter.sh" : `${ide}-adapter.sh`;
|
|
641
|
+
writeFileSync2(join4(adaptersDir, adapterName), renderAdapterScript(ide), "utf-8");
|
|
642
|
+
switch (ide) {
|
|
643
|
+
case "cursor":
|
|
644
|
+
writeFileSync2(join4(rootPath, ".cursor", "hooks.json"), JSON.stringify(renderCursorHooksConfig(), null, 2), "utf-8");
|
|
645
|
+
break;
|
|
646
|
+
case "windsurf":
|
|
647
|
+
writeFileSync2(join4(rootPath, ".windsurf", "hooks.json"), JSON.stringify(renderWindsurfHooksConfig(), null, 2), "utf-8");
|
|
648
|
+
break;
|
|
649
|
+
case "claude":
|
|
650
|
+
writeFileSync2(join4(rootPath, ".claude", "settings.local.json"), JSON.stringify(renderClaudeHooksConfig(), null, 2), "utf-8");
|
|
651
|
+
break;
|
|
652
|
+
case "codex":
|
|
653
|
+
writeFileSync2(join4(rootPath, ".codex", "hooks.json"), JSON.stringify(renderCodexHooksConfig(), null, 2), "utf-8");
|
|
654
|
+
break;
|
|
655
|
+
case "gemini":
|
|
656
|
+
writeFileSync2(join4(rootPath, ".gemini", "settings.json"), JSON.stringify(renderGeminiHooksConfig(), null, 2), "utf-8");
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
622
660
|
function renderAgentsMd(profile, context) {
|
|
623
661
|
const userName = profile?.name ?? "the user";
|
|
624
662
|
const userBio = profile?.bio || "(No bio provided \u2014 run `trellis season` to set up your profile.)";
|
|
@@ -899,6 +937,800 @@ function renderGeminiConfig(input) {
|
|
|
899
937
|
features: input.plugins
|
|
900
938
|
};
|
|
901
939
|
}
|
|
940
|
+
function renderPrePromptRecallScript() {
|
|
941
|
+
return `#!/usr/bin/env bash
|
|
942
|
+
# Pre-prompt memory and context recall for Trellis integration
|
|
943
|
+
# Normalized contract: TRELLIS_ORIGIN, TRELLIS_DESK_ROOT, TRELLIS_HOOK_OUTPUT
|
|
944
|
+
set -euo pipefail
|
|
945
|
+
|
|
946
|
+
# Import desk root detection
|
|
947
|
+
source "$(dirname "$0")/../../desk-root.sh"
|
|
948
|
+
|
|
949
|
+
# Environment variables from contract
|
|
950
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
951
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
952
|
+
|
|
953
|
+
# Only run if we're in a Trellis workspace
|
|
954
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
955
|
+
exit 0
|
|
956
|
+
fi
|
|
957
|
+
|
|
958
|
+
# Try to get Trellis context (non-blocking)
|
|
959
|
+
if [ -f ".trellis/config.json" ]; then
|
|
960
|
+
# Query recent memories and entities for context
|
|
961
|
+
CONTEXT_OUTPUT=$(trellis query --limit 5 --format json 2>/dev/null || echo '{"entities":[],"relations":[]}')
|
|
962
|
+
|
|
963
|
+
# Query recent operations for context
|
|
964
|
+
OPS_OUTPUT=$(trellis log --limit 3 --format json 2>/dev/null || echo '{"operations":[]}')
|
|
965
|
+
|
|
966
|
+
# Query active issues
|
|
967
|
+
ISSUES_OUTPUT=$(trellis issue list --status active --format json 2>/dev/null || echo '{"issues":[]}')
|
|
968
|
+
|
|
969
|
+
# Format output based on hook type
|
|
970
|
+
case "$OUTPUT" in
|
|
971
|
+
"agent-stop")
|
|
972
|
+
# For Codex/Gemini blocking hooks
|
|
973
|
+
echo "{}"
|
|
974
|
+
;;
|
|
975
|
+
"gemini")
|
|
976
|
+
# For Gemini CLI format
|
|
977
|
+
cat << EOF
|
|
978
|
+
{
|
|
979
|
+
"decision": "allow",
|
|
980
|
+
"context": {
|
|
981
|
+
"memories": $CONTEXT_OUTPUT,
|
|
982
|
+
"operations": $OPS_OUTPUT,
|
|
983
|
+
"issues": $ISSUES_OUTPUT,
|
|
984
|
+
"origin": "$ORIGIN"
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
EOF
|
|
988
|
+
;;
|
|
989
|
+
*)
|
|
990
|
+
# Default stdout for Cursor/Windsurf/Claude
|
|
991
|
+
echo ""
|
|
992
|
+
echo "\uD83C\uDF3F Trellis Context ($ORIGIN):"
|
|
993
|
+
echo " Recent memories: $(echo "$CONTEXT_OUTPUT" | jq -r '.entities | length' 2>/dev/null || echo "0")"
|
|
994
|
+
echo " Recent ops: $(echo "$OPS_OUTPUT" | jq -r '.operations | length' 2>/dev/null || echo "0")"
|
|
995
|
+
echo " Active issues: $(echo "$ISSUES_OUTPUT" | jq -r '.issues | length' 2>/dev/null || echo "0")"
|
|
996
|
+
echo ""
|
|
997
|
+
;;
|
|
998
|
+
esac
|
|
999
|
+
fi
|
|
1000
|
+
|
|
1001
|
+
exit 0`;
|
|
1002
|
+
}
|
|
1003
|
+
function renderPostToolOplogScript() {
|
|
1004
|
+
return `#!/usr/bin/env bash
|
|
1005
|
+
# Post-tool operation logging for Trellis integration
|
|
1006
|
+
# Normalized contract: TRELLIS_ORIGIN, TRELLIS_DESK_ROOT, stdin with tool data
|
|
1007
|
+
set -euo pipefail
|
|
1008
|
+
|
|
1009
|
+
# Import desk root detection
|
|
1010
|
+
source "$(dirname "$0")/../../desk-root.sh"
|
|
1011
|
+
|
|
1012
|
+
# Environment variables from contract
|
|
1013
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
1014
|
+
|
|
1015
|
+
# Read tool data from stdin (normalized format)
|
|
1016
|
+
TOOL_DATA=$(cat)
|
|
1017
|
+
|
|
1018
|
+
# Extract relevant information from tool data
|
|
1019
|
+
# Expected format: JSON with tool, action, file_path, etc.
|
|
1020
|
+
TOOL_NAME=$(echo "$TOOL_DATA" | jq -r '.tool // "unknown"' 2>/dev/null || echo "unknown")
|
|
1021
|
+
ACTION=$(echo "$TOOL_DATA" | jq -r '.action // "unknown"' 2>/dev/null || echo "unknown")
|
|
1022
|
+
FILE_PATH=$(echo "$TOOL_DATA" | jq -r '.file_path // .filePath // .path // ""' 2>/dev/null || echo "")
|
|
1023
|
+
|
|
1024
|
+
# Only run if we're in a Trellis workspace
|
|
1025
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
1026
|
+
exit 0
|
|
1027
|
+
fi
|
|
1028
|
+
|
|
1029
|
+
if [ -f ".trellis/config.json" ]; then
|
|
1030
|
+
# Create operation log entry
|
|
1031
|
+
OP_ENTRY=$(cat << EOF
|
|
1032
|
+
{
|
|
1033
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)",
|
|
1034
|
+
"origin": "$ORIGIN",
|
|
1035
|
+
"tool": "$TOOL_NAME",
|
|
1036
|
+
"action": "$ACTION",
|
|
1037
|
+
"target": "$FILE_PATH",
|
|
1038
|
+
"type": "agent-operation"
|
|
1039
|
+
}
|
|
1040
|
+
EOF
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
# Try to append to Trellis op log (non-blocking)
|
|
1044
|
+
# Note: This would need a corresponding trellis operation command
|
|
1045
|
+
# For now, we'll create a local log file that can be imported
|
|
1046
|
+
LOG_DIR=".trellis/agent-ops"
|
|
1047
|
+
mkdir -p "$LOG_DIR"
|
|
1048
|
+
|
|
1049
|
+
LOG_FILE="$LOG_DIR/ops-$(date +%Y-%m-%d).jsonl"
|
|
1050
|
+
echo "$OP_ENTRY" >> "$LOG_FILE"
|
|
1051
|
+
|
|
1052
|
+
# Keep only last 7 days of logs
|
|
1053
|
+
find "$LOG_DIR" -name "ops-*.jsonl" -mtime +7 -delete 2>/dev/null || true
|
|
1054
|
+
fi
|
|
1055
|
+
|
|
1056
|
+
exit 0`;
|
|
1057
|
+
}
|
|
1058
|
+
function renderPostToolMemoryCaptureScript() {
|
|
1059
|
+
return `#!/usr/bin/env bash
|
|
1060
|
+
# Post-tool memory and entity capture for Trellis integration
|
|
1061
|
+
# Normalized contract: TRELLIS_ORIGIN, TRELLIS_DESK_ROOT, stdin with tool data
|
|
1062
|
+
set -euo pipefail
|
|
1063
|
+
|
|
1064
|
+
# Import desk root detection
|
|
1065
|
+
source "$(dirname "$0")/../../desk-root.sh"
|
|
1066
|
+
|
|
1067
|
+
# Environment variables from contract
|
|
1068
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
1069
|
+
|
|
1070
|
+
# Read tool data from stdin
|
|
1071
|
+
TOOL_DATA=$(cat)
|
|
1072
|
+
|
|
1073
|
+
# Extract relevant information
|
|
1074
|
+
TOOL_NAME=$(echo "$TOOL_DATA" | jq -r '.tool // "unknown"' 2>/dev/null || echo "unknown")
|
|
1075
|
+
ACTION=$(echo "$TOOL_DATA" | jq -r '.action // "unknown"' 2>/dev/null || echo "unknown")
|
|
1076
|
+
FILE_PATH=$(echo "$TOOL_DATA" | jq -r '.file_path // .filePath // .path // ""' 2>/dev/null || echo "")
|
|
1077
|
+
|
|
1078
|
+
# Only run if we're in a Trellis workspace
|
|
1079
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
1080
|
+
exit 0
|
|
1081
|
+
fi
|
|
1082
|
+
|
|
1083
|
+
if [ -f ".trellis/config.json" ]; then
|
|
1084
|
+
# Suggest memory creation for significant operations
|
|
1085
|
+
case "$TOOL_NAME-$ACTION" in
|
|
1086
|
+
"edit-create"|"write-create"|"Edit-create"|"Write-create")
|
|
1087
|
+
# File creation - suggest creating a memory
|
|
1088
|
+
if [ -n "$FILE_PATH" ]; then
|
|
1089
|
+
echo "\uD83E\uDDE0 Consider creating a memory for the new file: $FILE_PATH"
|
|
1090
|
+
echo " Run: trellis memory create -t "Created $FILE_PATH" -c "Created via $ORIGIN agent""
|
|
1091
|
+
fi
|
|
1092
|
+
;;
|
|
1093
|
+
"edit-update"|"Edit-update")
|
|
1094
|
+
# File update - suggest updating memory if significant
|
|
1095
|
+
if [ -n "$FILE_PATH" ]; then
|
|
1096
|
+
echo "\uD83D\uDD04 Consider updating relevant memories for: $FILE_PATH"
|
|
1097
|
+
echo " Run: trellis memory list -q "$FILE_PATH""
|
|
1098
|
+
fi
|
|
1099
|
+
;;
|
|
1100
|
+
"issue-create"|"issue-update")
|
|
1101
|
+
# Issue operations - always suggest memory
|
|
1102
|
+
echo "\uD83D\uDCDD Consider creating a memory for this issue operation"
|
|
1103
|
+
echo " Run: trellis memory create -t "Issue $ACTION via $ORIGIN""
|
|
1104
|
+
;;
|
|
1105
|
+
esac
|
|
1106
|
+
|
|
1107
|
+
# Store potential memory suggestions for later
|
|
1108
|
+
MEMORY_DIR=".trellis/agent-suggestions"
|
|
1109
|
+
mkdir -p "$MEMORY_DIR"
|
|
1110
|
+
|
|
1111
|
+
SUGGESTION=$(cat << EOF
|
|
1112
|
+
{
|
|
1113
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)",
|
|
1114
|
+
"origin": "$ORIGIN",
|
|
1115
|
+
"tool": "$TOOL_NAME",
|
|
1116
|
+
"action": "$ACTION",
|
|
1117
|
+
"target": "$FILE_PATH",
|
|
1118
|
+
"suggestion_type": "memory-creation"
|
|
1119
|
+
}
|
|
1120
|
+
EOF
|
|
1121
|
+
)
|
|
1122
|
+
|
|
1123
|
+
SUGGESTIONS_FILE="$MEMORY_DIR/suggestions-$(date +%Y-%m-%d).jsonl"
|
|
1124
|
+
echo "$SUGGESTION" >> "$SUGGESTIONS_FILE"
|
|
1125
|
+
|
|
1126
|
+
# Keep only last 3 days of suggestions
|
|
1127
|
+
find "$MEMORY_DIR" -name "suggestions-*.jsonl" -mtime +3 -delete 2>/dev/null || true
|
|
1128
|
+
fi
|
|
1129
|
+
|
|
1130
|
+
exit 0`;
|
|
1131
|
+
}
|
|
1132
|
+
function renderStopTriageScript() {
|
|
1133
|
+
return `#!/usr/bin/env bash
|
|
1134
|
+
# Session stop issue triage and workflow suggestions for Trellis integration
|
|
1135
|
+
# Normalized contract: TRELLIS_ORIGIN, TRELLIS_DESK_ROOT, TRELLIS_HOOK_OUTPUT
|
|
1136
|
+
set -euo pipefail
|
|
1137
|
+
|
|
1138
|
+
# Import desk root detection
|
|
1139
|
+
source "$(dirname "$0")/../../desk-root.sh"
|
|
1140
|
+
|
|
1141
|
+
# Environment variables from contract
|
|
1142
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
1143
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
1144
|
+
|
|
1145
|
+
# Only run if we're in a Trellis workspace
|
|
1146
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
1147
|
+
exit 0
|
|
1148
|
+
fi
|
|
1149
|
+
|
|
1150
|
+
if [ -f ".trellis/config.json" ]; then
|
|
1151
|
+
# Check for active issues that need attention
|
|
1152
|
+
ACTIVE_ISSUES=$(trellis issue list --status active --format json 2>/dev/null || echo '{"issues":[]}')
|
|
1153
|
+
ACTIVE_COUNT=$(echo "$ACTIVE_ISSUES" | jq -r '.issues | length' 2>/dev/null || echo "0")
|
|
1154
|
+
|
|
1155
|
+
# Check for pending memory suggestions
|
|
1156
|
+
MEMORY_DIR=".trellis/agent-suggestions"
|
|
1157
|
+
SUGGESTION_COUNT=0
|
|
1158
|
+
if [ -d "$MEMORY_DIR" ]; then
|
|
1159
|
+
SUGGESTION_COUNT=$(find "$MEMORY_DIR" -name "suggestions-*.jsonl" -exec wc -l {} ; 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
|
1160
|
+
fi
|
|
1161
|
+
|
|
1162
|
+
# Check for uncommitted changes
|
|
1163
|
+
UNCOMMITTED=0
|
|
1164
|
+
if git rev-parse --git-dir >/dev/null 2>&1; then
|
|
1165
|
+
UNCOMMITTED=$(git status --porcelain 2>/dev/null | wc -l || echo "0")
|
|
1166
|
+
fi
|
|
1167
|
+
|
|
1168
|
+
# Build recommendations
|
|
1169
|
+
RECOMMENDATIONS=()
|
|
1170
|
+
|
|
1171
|
+
if [ "$ACTIVE_COUNT" -gt 0 ]; then
|
|
1172
|
+
RECOMMENDATIONS+=("\uD83C\uDFAF $ACTIVE_COUNT active issues need attention - run 'trellis issue list'")
|
|
1173
|
+
fi
|
|
1174
|
+
|
|
1175
|
+
if [ "$SUGGESTION_COUNT" -gt 0 ]; then
|
|
1176
|
+
RECOMMENDATIONS+=("\uD83E\uDDE0 $SUGGESTION_COUNT memory suggestions pending - review .trellis/agent-suggestions/")
|
|
1177
|
+
fi
|
|
1178
|
+
|
|
1179
|
+
if [ "$UNCOMMITTED" -gt 0 ]; then
|
|
1180
|
+
RECOMMENDATIONS+=("\uD83D\uDCDD $UNCOMMITTED uncommitted changes - consider committing or creating a checkpoint")
|
|
1181
|
+
fi
|
|
1182
|
+
|
|
1183
|
+
# Format output based on hook type
|
|
1184
|
+
case "$OUTPUT" in
|
|
1185
|
+
"agent-stop")
|
|
1186
|
+
# For Codex/Gemini blocking hooks
|
|
1187
|
+
if [ \${#RECOMMENDATIONS[@]} -gt 0 ]; then
|
|
1188
|
+
MESSAGE=$(printf '%s
|
|
1189
|
+
' "\${RECOMMENDATIONS[@]}")
|
|
1190
|
+
cat << EOF
|
|
1191
|
+
{
|
|
1192
|
+
"decision": "block",
|
|
1193
|
+
"reason": "Trellis workflow items need attention: $MESSAGE"
|
|
1194
|
+
}
|
|
1195
|
+
EOF
|
|
1196
|
+
else
|
|
1197
|
+
echo "{}"
|
|
1198
|
+
fi
|
|
1199
|
+
;;
|
|
1200
|
+
"gemini")
|
|
1201
|
+
# For Gemini CLI format
|
|
1202
|
+
if [ \${#RECOMMENDATIONS[@]} -gt 0 ]; then
|
|
1203
|
+
MESSAGE=$(printf '%s\\n' "\${RECOMMENDATIONS[@]}")
|
|
1204
|
+
cat << EOF
|
|
1205
|
+
{
|
|
1206
|
+
"decision": "deny",
|
|
1207
|
+
"reason": "Trellis workflow items need attention: $MESSAGE"
|
|
1208
|
+
}
|
|
1209
|
+
EOF
|
|
1210
|
+
else
|
|
1211
|
+
echo '{"decision": "allow"}'
|
|
1212
|
+
fi
|
|
1213
|
+
;;
|
|
1214
|
+
*)
|
|
1215
|
+
# Default stdout for Cursor/Windsurf/Claude
|
|
1216
|
+
if [ \${#RECOMMENDATIONS[@]} -gt 0 ]; then
|
|
1217
|
+
echo ""
|
|
1218
|
+
echo "\uD83C\uDF3F Trellis Session Summary ($ORIGIN):"
|
|
1219
|
+
printf ' %s
|
|
1220
|
+
' "\${RECOMMENDATIONS[@]}"
|
|
1221
|
+
echo ""
|
|
1222
|
+
echo "Run 'trellis status' for full workspace state"
|
|
1223
|
+
else
|
|
1224
|
+
echo "\uD83C\uDF3F Trellis: All clear! No pending items."
|
|
1225
|
+
fi
|
|
1226
|
+
;;
|
|
1227
|
+
esac
|
|
1228
|
+
fi
|
|
1229
|
+
|
|
1230
|
+
exit 0`;
|
|
1231
|
+
}
|
|
1232
|
+
function renderAdapterScript(ide) {
|
|
1233
|
+
switch (ide) {
|
|
1234
|
+
case "cursor":
|
|
1235
|
+
return `#!/usr/bin/env bash
|
|
1236
|
+
# Cursor adapter for Trellis harness
|
|
1237
|
+
# Translates Cursor events to normalized contract
|
|
1238
|
+
set -euo pipefail
|
|
1239
|
+
|
|
1240
|
+
# Import desk root detection
|
|
1241
|
+
source "$(dirname "$0")/../desk-root.sh"
|
|
1242
|
+
|
|
1243
|
+
# Set origin
|
|
1244
|
+
export TRELLIS_ORIGIN="cursor"
|
|
1245
|
+
export TRELLIS_DESK_ROOT="$PWD"
|
|
1246
|
+
|
|
1247
|
+
# Route based on event type
|
|
1248
|
+
EVENT_TYPE="\${1:-unknown}"
|
|
1249
|
+
|
|
1250
|
+
case "$EVENT_TYPE" in
|
|
1251
|
+
"session-start")
|
|
1252
|
+
# Cursor sessionStart hook
|
|
1253
|
+
exec "$(dirname "$0")/../trellis-harness/pre-prompt-recall.sh"
|
|
1254
|
+
;;
|
|
1255
|
+
"post-tool")
|
|
1256
|
+
# Cursor afterFileEdit hook - read stdin for tool data
|
|
1257
|
+
TOOL_DATA=$(cat)
|
|
1258
|
+
|
|
1259
|
+
# Transform Cursor format to normalized format
|
|
1260
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1261
|
+
{
|
|
1262
|
+
"tool": "edit_file",
|
|
1263
|
+
"action": "update",
|
|
1264
|
+
"file_path": $(echo "$TOOL_DATA" | jq -r '.file_path // ""' 2>/dev/null || echo '""'),
|
|
1265
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1266
|
+
}
|
|
1267
|
+
EOF
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1270
|
+
# Call op logger
|
|
1271
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1272
|
+
|
|
1273
|
+
# Call memory capture
|
|
1274
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1275
|
+
;;
|
|
1276
|
+
"stop")
|
|
1277
|
+
# Cursor stop hook
|
|
1278
|
+
export TRELLIS_HOOK_OUTPUT="stdout"
|
|
1279
|
+
exec "$(dirname "$0")/../trellis-harness/stop-triage.sh"
|
|
1280
|
+
;;
|
|
1281
|
+
*)
|
|
1282
|
+
echo "Unknown Cursor event: $EVENT_TYPE" >&2
|
|
1283
|
+
exit 1
|
|
1284
|
+
;;
|
|
1285
|
+
esac`;
|
|
1286
|
+
case "windsurf":
|
|
1287
|
+
return `#!/usr/bin/env bash
|
|
1288
|
+
# Windsurf Cascade adapter for Trellis harness
|
|
1289
|
+
# Translates Cascade events to normalized contract
|
|
1290
|
+
set -euo pipefail
|
|
1291
|
+
|
|
1292
|
+
# Import desk root detection
|
|
1293
|
+
source "$(dirname "$0")/../desk-root.sh"
|
|
1294
|
+
|
|
1295
|
+
# Set origin
|
|
1296
|
+
export TRELLIS_ORIGIN="windsurf"
|
|
1297
|
+
export TRELLIS_DESK_ROOT="$PWD"
|
|
1298
|
+
|
|
1299
|
+
# Route based on event type
|
|
1300
|
+
EVENT_TYPE="\${1:-unknown}"
|
|
1301
|
+
|
|
1302
|
+
case "$EVENT_TYPE" in
|
|
1303
|
+
"pre-prompt")
|
|
1304
|
+
# Cascade pre_user_prompt hook
|
|
1305
|
+
exec "$(dirname "$0")/../trellis-harness/pre-prompt-recall.sh"
|
|
1306
|
+
;;
|
|
1307
|
+
"post-tool")
|
|
1308
|
+
# Cascade post_write_code hook - read stdin for tool data
|
|
1309
|
+
TOOL_DATA=$(cat)
|
|
1310
|
+
|
|
1311
|
+
# Transform Cascade format to normalized format
|
|
1312
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1313
|
+
{
|
|
1314
|
+
"tool": "write_file",
|
|
1315
|
+
"action": "create",
|
|
1316
|
+
"file_path": $(echo "$TOOL_DATA" | jq -r '.file_path // ""' 2>/dev/null || echo '""'),
|
|
1317
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1318
|
+
}
|
|
1319
|
+
EOF
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
# Call op logger
|
|
1323
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1324
|
+
|
|
1325
|
+
# Call memory capture
|
|
1326
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1327
|
+
;;
|
|
1328
|
+
"post-response")
|
|
1329
|
+
# Cascade post_cascade_response hook
|
|
1330
|
+
export TRELLIS_HOOK_OUTPUT="stdout"
|
|
1331
|
+
exec "$(dirname "$0")/../trellis-harness/stop-triage.sh"
|
|
1332
|
+
;;
|
|
1333
|
+
*)
|
|
1334
|
+
echo "Unknown Cascade event: $EVENT_TYPE" >&2
|
|
1335
|
+
exit 1
|
|
1336
|
+
;;
|
|
1337
|
+
esac`;
|
|
1338
|
+
case "claude":
|
|
1339
|
+
return `#!/usr/bin/env bash
|
|
1340
|
+
# Claude Code adapter for Trellis harness
|
|
1341
|
+
# Translates Claude Code events to normalized contract
|
|
1342
|
+
set -euo pipefail
|
|
1343
|
+
|
|
1344
|
+
# Import desk root detection
|
|
1345
|
+
source "$(dirname "$0")/../desk-root.sh"
|
|
1346
|
+
|
|
1347
|
+
# Set origin
|
|
1348
|
+
export TRELLIS_ORIGIN="claude"
|
|
1349
|
+
export TRELLIS_DESK_ROOT="$PWD"
|
|
1350
|
+
|
|
1351
|
+
# Route based on event type
|
|
1352
|
+
EVENT_TYPE="\${1:-unknown}"
|
|
1353
|
+
|
|
1354
|
+
case "$EVENT_TYPE" in
|
|
1355
|
+
"pre-tool-use")
|
|
1356
|
+
# Claude Code PreToolUse hook
|
|
1357
|
+
exec "$(dirname "$0")/../trellis-harness/pre-prompt-recall.sh"
|
|
1358
|
+
;;
|
|
1359
|
+
"post-tool-use")
|
|
1360
|
+
# Claude Code PostToolUse hook - read stdin for tool data
|
|
1361
|
+
TOOL_DATA=$(cat)
|
|
1362
|
+
|
|
1363
|
+
# Transform Claude Code format to normalized format
|
|
1364
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1365
|
+
{
|
|
1366
|
+
"tool": $(echo "$TOOL_DATA" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1367
|
+
"action": $(echo "$TOOL_DATA" | jq -r '.action // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1368
|
+
"file_path": $(echo "$TOOL_DATA" | jq -r '.file_path // .filePath // ""' 2>/dev/null || echo '""'),
|
|
1369
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1370
|
+
}
|
|
1371
|
+
EOF
|
|
1372
|
+
)
|
|
1373
|
+
|
|
1374
|
+
# Call op logger
|
|
1375
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1376
|
+
|
|
1377
|
+
# Call memory capture
|
|
1378
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1379
|
+
;;
|
|
1380
|
+
"post-tool-batch")
|
|
1381
|
+
# Claude Code PostToolBatch hook - process multiple tools
|
|
1382
|
+
TOOL_DATA=$(cat)
|
|
1383
|
+
|
|
1384
|
+
# Process each tool in the batch
|
|
1385
|
+
echo "$TOOL_DATA" | jq -c '.[]' 2>/dev/null | while read -r tool; do
|
|
1386
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1387
|
+
{
|
|
1388
|
+
"tool": $(echo "$tool" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1389
|
+
"action": $(echo "$tool" | jq -r '.action // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1390
|
+
"file_path": $(echo "$tool" | jq -r '.file_path // .filePath // ""' 2>/dev/null || echo '""'),
|
|
1391
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1392
|
+
}
|
|
1393
|
+
EOF
|
|
1394
|
+
)
|
|
1395
|
+
|
|
1396
|
+
# Call op logger
|
|
1397
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1398
|
+
|
|
1399
|
+
# Call memory capture
|
|
1400
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1401
|
+
done
|
|
1402
|
+
;;
|
|
1403
|
+
"permission-denied")
|
|
1404
|
+
# Claude Code PermissionDenied hook
|
|
1405
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1406
|
+
{
|
|
1407
|
+
"tool": "permission_denied",
|
|
1408
|
+
"action": "blocked",
|
|
1409
|
+
"file_path": "",
|
|
1410
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1411
|
+
}
|
|
1412
|
+
EOF
|
|
1413
|
+
)
|
|
1414
|
+
|
|
1415
|
+
# Call op logger
|
|
1416
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1417
|
+
;;
|
|
1418
|
+
*)
|
|
1419
|
+
echo "Unknown Claude Code event: $EVENT_TYPE" >&2
|
|
1420
|
+
exit 1
|
|
1421
|
+
;;
|
|
1422
|
+
esac`;
|
|
1423
|
+
case "codex":
|
|
1424
|
+
return `#!/usr/bin/env bash
|
|
1425
|
+
# Codex adapter for Trellis harness
|
|
1426
|
+
# Translates Codex events to normalized contract
|
|
1427
|
+
set -euo pipefail
|
|
1428
|
+
|
|
1429
|
+
# Import desk root detection
|
|
1430
|
+
source "$(dirname "$0")/../desk-root.sh"
|
|
1431
|
+
|
|
1432
|
+
# Set origin
|
|
1433
|
+
export TRELLIS_ORIGIN="codex"
|
|
1434
|
+
export TRELLIS_DESK_ROOT="$PWD"
|
|
1435
|
+
|
|
1436
|
+
# Route based on event type
|
|
1437
|
+
EVENT_TYPE="\${1:-unknown}"
|
|
1438
|
+
|
|
1439
|
+
case "$EVENT_TYPE" in
|
|
1440
|
+
"session-start")
|
|
1441
|
+
# Codex SessionStart hook
|
|
1442
|
+
exec "$(dirname "$0")/../trellis-harness/pre-prompt-recall.sh"
|
|
1443
|
+
;;
|
|
1444
|
+
"post-tool")
|
|
1445
|
+
# Codex PostToolUse hook - read stdin for tool data
|
|
1446
|
+
TOOL_DATA=$(cat)
|
|
1447
|
+
|
|
1448
|
+
# Transform Codex format to normalized format
|
|
1449
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1450
|
+
{
|
|
1451
|
+
"tool": $(echo "$TOOL_DATA" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1452
|
+
"action": $(echo "$TOOL_DATA" | jq -r '.action // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1453
|
+
"file_path": $(echo "$TOOL_DATA" | jq -r '.file_path // .filePath // ""' 2>/dev/null || echo '""'),
|
|
1454
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1455
|
+
}
|
|
1456
|
+
EOF
|
|
1457
|
+
)
|
|
1458
|
+
|
|
1459
|
+
# Call op logger
|
|
1460
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1461
|
+
|
|
1462
|
+
# Call memory capture
|
|
1463
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1464
|
+
;;
|
|
1465
|
+
"stop")
|
|
1466
|
+
# Codex Stop hook
|
|
1467
|
+
export TRELLIS_HOOK_OUTPUT="agent-stop"
|
|
1468
|
+
exec "$(dirname "$0")/../trellis-harness/stop-triage.sh"
|
|
1469
|
+
;;
|
|
1470
|
+
*)
|
|
1471
|
+
echo "Unknown Codex event: $EVENT_TYPE" >&2
|
|
1472
|
+
exit 1
|
|
1473
|
+
;;
|
|
1474
|
+
esac`;
|
|
1475
|
+
case "gemini":
|
|
1476
|
+
return `#!/usr/bin/env bash
|
|
1477
|
+
# Gemini CLI adapter for Trellis harness
|
|
1478
|
+
# Translates Gemini events to normalized contract
|
|
1479
|
+
set -euo pipefail
|
|
1480
|
+
|
|
1481
|
+
# Import desk root detection
|
|
1482
|
+
source "$(dirname "$0")/../desk-root.sh"
|
|
1483
|
+
|
|
1484
|
+
# Set origin
|
|
1485
|
+
export TRELLIS_ORIGIN="gemini"
|
|
1486
|
+
export TRELLIS_DESK_ROOT="$PWD"
|
|
1487
|
+
|
|
1488
|
+
# Route based on event type
|
|
1489
|
+
EVENT_TYPE="\${1:-unknown}"
|
|
1490
|
+
|
|
1491
|
+
case "$EVENT_TYPE" in
|
|
1492
|
+
"session-start"|"before-agent")
|
|
1493
|
+
# Gemini SessionStart or BeforeAgent hook
|
|
1494
|
+
exec "$(dirname "$0")/../trellis-harness/pre-prompt-recall.sh"
|
|
1495
|
+
;;
|
|
1496
|
+
"post-tool")
|
|
1497
|
+
# Gemini AfterTool hook - read stdin for tool data
|
|
1498
|
+
TOOL_DATA=$(cat)
|
|
1499
|
+
|
|
1500
|
+
# Transform Gemini format to normalized format
|
|
1501
|
+
NORMALIZED_DATA=$(cat << EOF
|
|
1502
|
+
{
|
|
1503
|
+
"tool": $(echo "$TOOL_DATA" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1504
|
+
"action": $(echo "$TOOL_DATA" | jq -r '.action // "unknown"' 2>/dev/null || echo '"unknown"'),
|
|
1505
|
+
"file_path": $(echo "$TOOL_DATA" | jq -r '.file_path // .filePath // ""' 2>/dev/null || echo '""'),
|
|
1506
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
|
1507
|
+
}
|
|
1508
|
+
EOF
|
|
1509
|
+
)
|
|
1510
|
+
|
|
1511
|
+
# Call op logger
|
|
1512
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-oplog.sh"
|
|
1513
|
+
|
|
1514
|
+
# Call memory capture
|
|
1515
|
+
echo "$NORMALIZED_DATA" | "$(dirname "$0")/../trellis-harness/post-tool-memory-capture.sh"
|
|
1516
|
+
;;
|
|
1517
|
+
"after-agent")
|
|
1518
|
+
# Gemini AfterAgent hook
|
|
1519
|
+
export TRELLIS_HOOK_OUTPUT="gemini"
|
|
1520
|
+
exec "$(dirname "$0")/../trellis-harness/stop-triage.sh"
|
|
1521
|
+
;;
|
|
1522
|
+
*)
|
|
1523
|
+
echo "Unknown Gemini event: $EVENT_TYPE" >&2
|
|
1524
|
+
exit 1
|
|
1525
|
+
;;
|
|
1526
|
+
esac`;
|
|
1527
|
+
default:
|
|
1528
|
+
return `#!/usr/bin/env bash
|
|
1529
|
+
# Default adapter for Trellis harness
|
|
1530
|
+
echo "Unsupported IDE: ${ide}" >&2
|
|
1531
|
+
exit 1`;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
function renderCursorHooksConfig() {
|
|
1535
|
+
return {
|
|
1536
|
+
version: 1,
|
|
1537
|
+
hooks: {
|
|
1538
|
+
sessionStart: [
|
|
1539
|
+
{
|
|
1540
|
+
command: "bash .cursor/hooks/adapters/cursor-adapter.sh session-start",
|
|
1541
|
+
timeout: 15
|
|
1542
|
+
}
|
|
1543
|
+
],
|
|
1544
|
+
afterFileEdit: [
|
|
1545
|
+
{
|
|
1546
|
+
command: "bash .cursor/hooks/adapters/cursor-adapter.sh post-tool",
|
|
1547
|
+
timeout: 10
|
|
1548
|
+
}
|
|
1549
|
+
],
|
|
1550
|
+
stop: [
|
|
1551
|
+
{
|
|
1552
|
+
command: "bash .cursor/hooks/adapters/cursor-adapter.sh stop",
|
|
1553
|
+
timeout: 10
|
|
1554
|
+
}
|
|
1555
|
+
]
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
function renderWindsurfHooksConfig() {
|
|
1560
|
+
return {
|
|
1561
|
+
hooks: {
|
|
1562
|
+
pre_user_prompt: [
|
|
1563
|
+
{
|
|
1564
|
+
command: "bash .cursor/hooks/adapters/cascade-adapter.sh pre-prompt",
|
|
1565
|
+
show_output: true
|
|
1566
|
+
}
|
|
1567
|
+
],
|
|
1568
|
+
post_write_code: [
|
|
1569
|
+
{
|
|
1570
|
+
command: "bash .cursor/hooks/adapters/cascade-adapter.sh post-tool",
|
|
1571
|
+
show_output: false
|
|
1572
|
+
}
|
|
1573
|
+
],
|
|
1574
|
+
post_cascade_response: [
|
|
1575
|
+
{
|
|
1576
|
+
command: "bash .cursor/hooks/adapters/cascade-adapter.sh post-response",
|
|
1577
|
+
show_output: true
|
|
1578
|
+
}
|
|
1579
|
+
]
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
function renderClaudeHooksConfig() {
|
|
1584
|
+
return {
|
|
1585
|
+
hooks: {
|
|
1586
|
+
PreToolUse: [
|
|
1587
|
+
{
|
|
1588
|
+
command: "bash .cursor/hooks/adapters/claude-adapter.sh pre-tool-use",
|
|
1589
|
+
timeout: 15
|
|
1590
|
+
}
|
|
1591
|
+
],
|
|
1592
|
+
PostToolUse: [
|
|
1593
|
+
{
|
|
1594
|
+
command: "bash .cursor/hooks/adapters/claude-adapter.sh post-tool-use",
|
|
1595
|
+
timeout: 10
|
|
1596
|
+
}
|
|
1597
|
+
],
|
|
1598
|
+
PostToolBatch: [
|
|
1599
|
+
{
|
|
1600
|
+
command: "bash .cursor/hooks/adapters/claude-adapter.sh post-tool-batch",
|
|
1601
|
+
timeout: 15
|
|
1602
|
+
}
|
|
1603
|
+
],
|
|
1604
|
+
PermissionDenied: [
|
|
1605
|
+
{
|
|
1606
|
+
command: "bash .cursor/hooks/adapters/claude-adapter.sh permission-denied",
|
|
1607
|
+
timeout: 5
|
|
1608
|
+
}
|
|
1609
|
+
]
|
|
1610
|
+
},
|
|
1611
|
+
permissions: {
|
|
1612
|
+
allow: [
|
|
1613
|
+
"Bash(trellis --version)",
|
|
1614
|
+
"Bash(trellis issue *)",
|
|
1615
|
+
"Bash(trellis --help)",
|
|
1616
|
+
"Bash(trellis search *)",
|
|
1617
|
+
"Bash(trellis entity *)",
|
|
1618
|
+
"Bash(trellis ontology *)",
|
|
1619
|
+
"Bash(trellis query *)",
|
|
1620
|
+
"Bash(lsof -nP -iTCP -sTCP:LISTEN)",
|
|
1621
|
+
"Bash(awk '{print $9, $1, $2}')",
|
|
1622
|
+
"Bash(curl -s --max-time 1 http://localhost:__TRACKED_VAR__/api/graph/health)",
|
|
1623
|
+
"Bash(curl -s --max-time 1 http://localhost:__TRACKED_VAR__/api/graph/health -H 'Accept: application/json')",
|
|
1624
|
+
'Bash(grep -ivE "node_modules|dist|.vercel|.git$|.git/|.logs")'
|
|
1625
|
+
]
|
|
1626
|
+
},
|
|
1627
|
+
spinnerTipsEnabled: true
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
function renderCodexHooksConfig() {
|
|
1631
|
+
return {
|
|
1632
|
+
hooks: {
|
|
1633
|
+
SessionStart: [
|
|
1634
|
+
{
|
|
1635
|
+
matcher: "startup|resume|clear",
|
|
1636
|
+
hooks: [
|
|
1637
|
+
{
|
|
1638
|
+
type: "command",
|
|
1639
|
+
command: "bash .cursor/hooks/adapters/codex-adapter.sh session-start",
|
|
1640
|
+
timeout: 15,
|
|
1641
|
+
statusMessage: "Loading Trellis desk context"
|
|
1642
|
+
}
|
|
1643
|
+
]
|
|
1644
|
+
}
|
|
1645
|
+
],
|
|
1646
|
+
PostToolUse: [
|
|
1647
|
+
{
|
|
1648
|
+
matcher: "apply_patch|Edit|Write",
|
|
1649
|
+
hooks: [
|
|
1650
|
+
{
|
|
1651
|
+
type: "command",
|
|
1652
|
+
command: "bash .cursor/hooks/adapters/codex-adapter.sh post-tool",
|
|
1653
|
+
timeout: 10,
|
|
1654
|
+
statusMessage: "Recording Trellis operation"
|
|
1655
|
+
}
|
|
1656
|
+
]
|
|
1657
|
+
}
|
|
1658
|
+
],
|
|
1659
|
+
Stop: [
|
|
1660
|
+
{
|
|
1661
|
+
hooks: [
|
|
1662
|
+
{
|
|
1663
|
+
type: "command",
|
|
1664
|
+
command: "bash .cursor/hooks/adapters/codex-adapter.sh stop",
|
|
1665
|
+
timeout: 10,
|
|
1666
|
+
statusMessage: "Checking Trellis workflow status"
|
|
1667
|
+
}
|
|
1668
|
+
]
|
|
1669
|
+
}
|
|
1670
|
+
]
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
function renderGeminiHooksConfig() {
|
|
1675
|
+
return {
|
|
1676
|
+
hooks: {
|
|
1677
|
+
SessionStart: [
|
|
1678
|
+
{
|
|
1679
|
+
matcher: "startup|resume|clear",
|
|
1680
|
+
hooks: [
|
|
1681
|
+
{
|
|
1682
|
+
name: "trellis-desk-context",
|
|
1683
|
+
type: "command",
|
|
1684
|
+
command: "bash .cursor/hooks/adapters/gemini-adapter.sh session-start",
|
|
1685
|
+
timeout: 15000,
|
|
1686
|
+
description: "Refresh pending Trellis context at session start"
|
|
1687
|
+
}
|
|
1688
|
+
]
|
|
1689
|
+
}
|
|
1690
|
+
],
|
|
1691
|
+
BeforeAgent: [
|
|
1692
|
+
{
|
|
1693
|
+
hooks: [
|
|
1694
|
+
{
|
|
1695
|
+
name: "trellis-desk-prompt-context",
|
|
1696
|
+
type: "command",
|
|
1697
|
+
command: "bash .cursor/hooks/adapters/gemini-adapter.sh before-agent",
|
|
1698
|
+
timeout: 15000,
|
|
1699
|
+
description: "Mirror Windsurf pre_user_prompt desk context refresh"
|
|
1700
|
+
}
|
|
1701
|
+
]
|
|
1702
|
+
}
|
|
1703
|
+
],
|
|
1704
|
+
AfterTool: [
|
|
1705
|
+
{
|
|
1706
|
+
matcher: "write_file|replace|apply_patch",
|
|
1707
|
+
hooks: [
|
|
1708
|
+
{
|
|
1709
|
+
name: "trellis-op-logging",
|
|
1710
|
+
type: "command",
|
|
1711
|
+
command: "bash .cursor/hooks/adapters/gemini-adapter.sh post-tool",
|
|
1712
|
+
timeout: 1e4,
|
|
1713
|
+
description: "Record Trellis operations and suggest memory creation"
|
|
1714
|
+
}
|
|
1715
|
+
]
|
|
1716
|
+
}
|
|
1717
|
+
],
|
|
1718
|
+
AfterAgent: [
|
|
1719
|
+
{
|
|
1720
|
+
hooks: [
|
|
1721
|
+
{
|
|
1722
|
+
name: "trellis-workflow-triage",
|
|
1723
|
+
type: "command",
|
|
1724
|
+
command: "bash .cursor/hooks/adapters/gemini-adapter.sh after-agent",
|
|
1725
|
+
timeout: 1e4,
|
|
1726
|
+
description: "Suggest Trellis workflow actions when items need attention"
|
|
1727
|
+
}
|
|
1728
|
+
]
|
|
1729
|
+
}
|
|
1730
|
+
]
|
|
1731
|
+
}
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
902
1734
|
function writeIdeScaffold(rootPath, input) {
|
|
903
1735
|
const { ide, footprint, framework, plugins, context, profile } = input;
|
|
904
1736
|
const fullInput = {
|
|
@@ -917,6 +1749,9 @@ function writeIdeScaffold(rootPath, input) {
|
|
|
917
1749
|
mkdirSync2(cursorDir, { recursive: true });
|
|
918
1750
|
}
|
|
919
1751
|
writeFileSync2(join4(cursorDir, "rules.md"), renderCursorRules(fullInput), "utf-8");
|
|
1752
|
+
if (footprint === "full") {
|
|
1753
|
+
writeTrellisHooks(rootPath, "cursor");
|
|
1754
|
+
}
|
|
920
1755
|
break;
|
|
921
1756
|
}
|
|
922
1757
|
case "windsurf": {
|
|
@@ -925,6 +1760,9 @@ function writeIdeScaffold(rootPath, input) {
|
|
|
925
1760
|
mkdirSync2(windsurfDir, { recursive: true });
|
|
926
1761
|
}
|
|
927
1762
|
writeFileSync2(join4(windsurfDir, "rules.md"), renderWindsurfRules(fullInput), "utf-8");
|
|
1763
|
+
if (footprint === "full") {
|
|
1764
|
+
writeTrellisHooks(rootPath, "windsurf");
|
|
1765
|
+
}
|
|
928
1766
|
break;
|
|
929
1767
|
}
|
|
930
1768
|
case "claude": {
|
|
@@ -933,6 +1771,9 @@ function writeIdeScaffold(rootPath, input) {
|
|
|
933
1771
|
mkdirSync2(claudeDir, { recursive: true });
|
|
934
1772
|
}
|
|
935
1773
|
writeFileSync2(join4(claudeDir, "settings.md"), renderClaudeMd(fullInput), "utf-8");
|
|
1774
|
+
if (footprint === "full") {
|
|
1775
|
+
writeTrellisHooks(rootPath, "claude");
|
|
1776
|
+
}
|
|
936
1777
|
break;
|
|
937
1778
|
}
|
|
938
1779
|
case "copilot": {
|
|
@@ -950,6 +1791,9 @@ function writeIdeScaffold(rootPath, input) {
|
|
|
950
1791
|
mkdirSync2(codexDir, { recursive: true });
|
|
951
1792
|
}
|
|
952
1793
|
writeFileSync2(join4(codexDir, "config.json"), JSON.stringify(renderCodexConfig(fullInput), null, 2), "utf-8");
|
|
1794
|
+
if (footprint === "full") {
|
|
1795
|
+
writeTrellisHooks(rootPath, "codex");
|
|
1796
|
+
}
|
|
953
1797
|
break;
|
|
954
1798
|
}
|
|
955
1799
|
case "gemini": {
|
|
@@ -958,6 +1802,9 @@ function writeIdeScaffold(rootPath, input) {
|
|
|
958
1802
|
mkdirSync2(geminiDir, { recursive: true });
|
|
959
1803
|
}
|
|
960
1804
|
writeFileSync2(join4(geminiDir, "config.json"), JSON.stringify(renderGeminiConfig(fullInput), null, 2), "utf-8");
|
|
1805
|
+
if (footprint === "full") {
|
|
1806
|
+
writeTrellisHooks(rootPath, "gemini");
|
|
1807
|
+
}
|
|
961
1808
|
break;
|
|
962
1809
|
}
|
|
963
1810
|
case "none":
|
|
@@ -980,6 +1827,356 @@ trellis milestone # Create narrative checkpoints
|
|
|
980
1827
|
}
|
|
981
1828
|
}
|
|
982
1829
|
}
|
|
1830
|
+
function renderBugIntakeScript() {
|
|
1831
|
+
return `#!/usr/bin/env bash
|
|
1832
|
+
# Bug intake and TDD enforcement for Trellis integration
|
|
1833
|
+
# Creates structured issues with acceptance criteria and test requirements
|
|
1834
|
+
set -euo pipefail
|
|
1835
|
+
|
|
1836
|
+
# Import desk root detection
|
|
1837
|
+
source "\\$(dirname "\\$0")/../desk-root.sh"
|
|
1838
|
+
|
|
1839
|
+
# Environment variables from contract
|
|
1840
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
1841
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
1842
|
+
|
|
1843
|
+
# Only run if we're in a Trellis workspace
|
|
1844
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
1845
|
+
exit 0
|
|
1846
|
+
fi
|
|
1847
|
+
|
|
1848
|
+
# Read bug description from stdin or environment
|
|
1849
|
+
BUG_DATA="\${TRELLIS_BUG_DATA:-}"
|
|
1850
|
+
if [ -z "\\$BUG_DATA" ]; then
|
|
1851
|
+
BUG_DATA=$(cat)
|
|
1852
|
+
fi
|
|
1853
|
+
|
|
1854
|
+
# Extract bug information
|
|
1855
|
+
TITLE=$(echo "\\$BUG_DATA" | jq -r '.title // "Untitled Bug"' 2>/dev/null || echo "Untitled Bug")
|
|
1856
|
+
DESCRIPTION=$(echo "\\$BUG_DATA" | jq -r '.description // ""' 2>/dev/null || echo "")
|
|
1857
|
+
SEVERITY=$(echo "\\$BUG_DATA" | jq -r '.severity // "medium"' 2>/dev/null || echo "medium")
|
|
1858
|
+
COMPONENT=$(echo "\\$BUG_DATA" | jq -r '.component // "unknown"' 2>/dev/null || echo "unknown")
|
|
1859
|
+
|
|
1860
|
+
# Validate required fields
|
|
1861
|
+
if [ -z "\\$DESCRIPTION" ]; then
|
|
1862
|
+
echo "\u274C Bug description is required" >&2
|
|
1863
|
+
exit 1
|
|
1864
|
+
fi
|
|
1865
|
+
|
|
1866
|
+
# Create the Trellis issue with structured content
|
|
1867
|
+
ISSUE_CONTENT="# Bug: \\$TITLE
|
|
1868
|
+
|
|
1869
|
+
**Severity:** \\$SEVERITY
|
|
1870
|
+
**Component:** \\$COMPONENT
|
|
1871
|
+
**Reported by:** \\$ORIGIN
|
|
1872
|
+
**Reported at:** $(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
|
|
1873
|
+
|
|
1874
|
+
## Description
|
|
1875
|
+
\\$DESCRIPTION
|
|
1876
|
+
|
|
1877
|
+
## Acceptance Criteria
|
|
1878
|
+
|
|
1879
|
+
### Functional Requirements
|
|
1880
|
+
- [ ] **AC-1:** Bug reproduction confirmed in test environment
|
|
1881
|
+
- [ ] **AC-2:** Root cause identified and documented
|
|
1882
|
+
- [ ] **AC-3:** Fix implemented without breaking existing functionality
|
|
1883
|
+
- [ ] **AC-4:** Bug no longer reproducible after fix
|
|
1884
|
+
- [ ] **AC-5:** Edge cases covered and tested
|
|
1885
|
+
|
|
1886
|
+
### Test Requirements (TDD)
|
|
1887
|
+
- [ ] **TEST-1:** Unit tests written for the failing behavior
|
|
1888
|
+
- [ ] **TEST-2:** Integration tests cover the bug scenario
|
|
1889
|
+
- [ ] **TEST-3:** Regression tests prevent future occurrences
|
|
1890
|
+
- [ ] **TEST-4:** Performance tests if applicable
|
|
1891
|
+
- [ ] **TEST-5:** Manual testing checklist completed
|
|
1892
|
+
|
|
1893
|
+
### Documentation Requirements
|
|
1894
|
+
- [ ] **DOC-1:** API documentation updated if behavior changed
|
|
1895
|
+
- [ ] **DOC-2:** README updated if user-facing change
|
|
1896
|
+
- [ ] **DOC-3:** Changelog entry prepared
|
|
1897
|
+
- [ ] **DOC-4:** Technical notes added for future reference
|
|
1898
|
+
|
|
1899
|
+
### Code Quality Requirements
|
|
1900
|
+
- [ ] **QUALITY-1:** Code follows project style guidelines
|
|
1901
|
+
- [ ] **QUALITY-2:** No new linting errors introduced
|
|
1902
|
+
- [ ] **QUALITY-3:** Code coverage maintained or improved
|
|
1903
|
+
- [ ] **QUALITY-4:** Security review completed if applicable
|
|
1904
|
+
- [ ] **QUALITY-5:** Performance impact assessed
|
|
1905
|
+
|
|
1906
|
+
## Definition of Done
|
|
1907
|
+
|
|
1908
|
+
This bug is considered **DONE** when:
|
|
1909
|
+
1. \u2705 All acceptance criteria are met
|
|
1910
|
+
2. \u2705 All tests pass (unit, integration, regression)
|
|
1911
|
+
3. \u2705 Code review approved
|
|
1912
|
+
4. \u2705 Documentation updated
|
|
1913
|
+
5. \u2705 No performance regressions
|
|
1914
|
+
6. \u2705 Security implications addressed
|
|
1915
|
+
7. \u2705 Changelog entry created
|
|
1916
|
+
8. \u2705 Release notes prepared
|
|
1917
|
+
|
|
1918
|
+
## Labels
|
|
1919
|
+
\`bug\`, \`severity-\\$SEVERITY\`, \`component-\\$COMPONENT\`, \`tdd-required\`, \`needs-investigation\`
|
|
1920
|
+
|
|
1921
|
+
---
|
|
1922
|
+
|
|
1923
|
+
**Generated by:** Trellis Enhanced Hooks
|
|
1924
|
+
**Origin:** \\$ORIGIN
|
|
1925
|
+
**Template:** bug-intake-v1.0
|
|
1926
|
+
"
|
|
1927
|
+
|
|
1928
|
+
# Create the Trellis issue
|
|
1929
|
+
ISSUE_ID=$(echo "\\$ISSUE_CONTENT" | trellis issue create --title "\\$TITLE" --content-from-stdin --format json 2>/dev/null | jq -r '.id // empty' || echo "")
|
|
1930
|
+
|
|
1931
|
+
if [ -n "\\$ISSUE_ID" ]; then
|
|
1932
|
+
# Add labels to the issue
|
|
1933
|
+
trellis issue label "\\$ISSUE_ID" add "bug" "severity-\\$SEVERITY" "component-\\$COMPONENT" "tdd-required" "needs-investigation" 2>/dev/null || true
|
|
1934
|
+
|
|
1935
|
+
echo ""
|
|
1936
|
+
echo "\uD83D\uDC1B Bug Intake Completed (\\$ORIGIN):"
|
|
1937
|
+
echo " \uD83D\uDCDD Issue: #\\$ISSUE_ID - \\$TITLE"
|
|
1938
|
+
echo " \uD83D\uDD27 Severity: \\$SEVERITY"
|
|
1939
|
+
echo " \uD83D\uDCE6 Component: \\$COMPONENT"
|
|
1940
|
+
echo " \u2705 TDD requirements enforced"
|
|
1941
|
+
echo ""
|
|
1942
|
+
echo "\uD83D\uDCCB Next Steps:"
|
|
1943
|
+
echo " 1. Investigate the bug: trellis issue view \\$ISSUE_ID"
|
|
1944
|
+
echo " 2. Develop tests with TDD approach"
|
|
1945
|
+
echo " 3. Implement fix"
|
|
1946
|
+
echo ""
|
|
1947
|
+
else
|
|
1948
|
+
echo "\u274C Failed to create bug issue" >&2
|
|
1949
|
+
exit 1
|
|
1950
|
+
fi
|
|
1951
|
+
`;
|
|
1952
|
+
}
|
|
1953
|
+
function renderBugInvestigateScript() {
|
|
1954
|
+
return `#!/usr/bin/env bash
|
|
1955
|
+
# Bug investigation and TDD enforcement for Trellis integration
|
|
1956
|
+
# Ensures thorough investigation before fix implementation
|
|
1957
|
+
set -euo pipefail
|
|
1958
|
+
|
|
1959
|
+
# Import desk root detection
|
|
1960
|
+
source "\\$(dirname "\\$0")/../desk-root.sh"
|
|
1961
|
+
|
|
1962
|
+
# Environment variables from contract
|
|
1963
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
1964
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
1965
|
+
ISSUE_ID="\${TRELLIS_ISSUE_ID:-}"
|
|
1966
|
+
|
|
1967
|
+
# Only run if we're in a Trellis workspace
|
|
1968
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
1969
|
+
exit 0
|
|
1970
|
+
fi
|
|
1971
|
+
|
|
1972
|
+
# Validate issue ID
|
|
1973
|
+
if [ -z "\\$ISSUE_ID" ]; then
|
|
1974
|
+
echo "\u274C Issue ID is required for bug investigation" >&2
|
|
1975
|
+
exit 1
|
|
1976
|
+
fi
|
|
1977
|
+
|
|
1978
|
+
# Get issue details
|
|
1979
|
+
ISSUE_DETAILS=$(trellis issue view "\\$ISSUE_ID" --format json 2>/dev/null || echo "{}")
|
|
1980
|
+
TITLE=$(echo "\\$ISSUE_DETAILS" | jq -r '.title // "Unknown Issue"' 2>/dev/null || echo "Unknown Issue")
|
|
1981
|
+
|
|
1982
|
+
# Create test directory structure
|
|
1983
|
+
TEST_DIR="tests/bugs/\\$ISSUE_ID"
|
|
1984
|
+
mkdir -p "\\$TEST_DIR"
|
|
1985
|
+
|
|
1986
|
+
# Create test template files
|
|
1987
|
+
cat > "\\$TEST_DIR/reproduction.test.ts" << 'EOF'
|
|
1988
|
+
/**
|
|
1989
|
+
* Bug #\\$ISSUE_ID: \\$TITLE
|
|
1990
|
+
* Reproduction test - This test should fail initially
|
|
1991
|
+
*/
|
|
1992
|
+
|
|
1993
|
+
import { describe, test, expect } from 'bun:test'
|
|
1994
|
+
|
|
1995
|
+
describe('Bug #\\$ISSUE_ID: \\$TITLE', () => {
|
|
1996
|
+
test('should reproduce the reported issue', async () => {
|
|
1997
|
+
// TODO: Implement reproduction steps based on bug description
|
|
1998
|
+
// This test should fail initially
|
|
1999
|
+
expect(true).toBe(false)
|
|
2000
|
+
})
|
|
2001
|
+
})
|
|
2002
|
+
EOF
|
|
2003
|
+
|
|
2004
|
+
cat > "\\$TEST_DIR/fix.test.ts" << 'EOF'
|
|
2005
|
+
/**
|
|
2006
|
+
* Bug #\\$ISSUE_ID: \\$TITLE
|
|
2007
|
+
* Fix verification test - This test should pass after implementing the fix
|
|
2008
|
+
*/
|
|
2009
|
+
|
|
2010
|
+
import { describe, test, expect } from 'bun:test'
|
|
2011
|
+
|
|
2012
|
+
describe('Bug #\\$ISSUE_ID: \\$TITLE - Fix Verification', () => {
|
|
2013
|
+
test('should resolve the issue after fix implementation', async () => {
|
|
2014
|
+
// TODO: Implement test that verifies the fix
|
|
2015
|
+
// This test should pass after fix
|
|
2016
|
+
expect(true).toBe(true)
|
|
2017
|
+
})
|
|
2018
|
+
})
|
|
2019
|
+
EOF
|
|
2020
|
+
|
|
2021
|
+
# Create test runner script
|
|
2022
|
+
cat > "\\$TEST_DIR/run-tests.sh" << 'EOF'
|
|
2023
|
+
#!/usr/bin/env bash
|
|
2024
|
+
# Test runner for bug investigation
|
|
2025
|
+
|
|
2026
|
+
set -euo pipefail
|
|
2027
|
+
|
|
2028
|
+
ISSUE_ID=$(basename "$(pwd)")
|
|
2029
|
+
echo "\uD83E\uDDEA Running tests for Bug #\\$ISSUE_ID"
|
|
2030
|
+
|
|
2031
|
+
# Run reproduction test (should fail initially)
|
|
2032
|
+
echo "\uD83D\uDCCB Running reproduction test..."
|
|
2033
|
+
bun run reproduction.test.ts || echo "\u274C Reproduction test failed (expected)"
|
|
2034
|
+
|
|
2035
|
+
# Run fix test (should pass after fix)
|
|
2036
|
+
echo "\uD83D\uDD27 Running fix verification test..."
|
|
2037
|
+
bun run fix.test.ts
|
|
2038
|
+
|
|
2039
|
+
echo "\u2705 All tests completed"
|
|
2040
|
+
EOF
|
|
2041
|
+
|
|
2042
|
+
chmod +x "\\$TEST_DIR/run-tests.sh"
|
|
2043
|
+
|
|
2044
|
+
# Update issue labels
|
|
2045
|
+
trellis issue label "\\$ISSUE_ID" add "investigating" 2>/dev/null || true
|
|
2046
|
+
|
|
2047
|
+
echo ""
|
|
2048
|
+
echo "\uD83D\uDD0D Bug Investigation Started (\\$ORIGIN):"
|
|
2049
|
+
echo " \uD83D\uDCDD Issue: #\\$ISSUE_ID - \\$TITLE"
|
|
2050
|
+
echo " \uD83D\uDCC1 Test directory: \\$TEST_DIR"
|
|
2051
|
+
echo " \uD83E\uDDEA Test files created"
|
|
2052
|
+
echo ""
|
|
2053
|
+
echo "\uD83D\uDCCB Next Steps:"
|
|
2054
|
+
echo " 1. Complete investigation: trellis issue view \\$ISSUE_ID"
|
|
2055
|
+
echo " 2. Run reproduction test: cd \\$TEST_DIR && ./run-tests.sh"
|
|
2056
|
+
echo " 3. Implement fix with TDD approach"
|
|
2057
|
+
echo ""
|
|
2058
|
+
`;
|
|
2059
|
+
}
|
|
2060
|
+
function renderMilestoneTriageScript() {
|
|
2061
|
+
return `#!/usr/bin/env bash
|
|
2062
|
+
# Milestone and cycle triage for Trellis integration
|
|
2063
|
+
# Integrates bugs with project milestones and development cycles
|
|
2064
|
+
set -euo pipefail
|
|
2065
|
+
|
|
2066
|
+
# Import desk root detection
|
|
2067
|
+
source "\\$(dirname "\\$0")/../desk-root.sh"
|
|
2068
|
+
|
|
2069
|
+
# Environment variables from contract
|
|
2070
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
2071
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
2072
|
+
ISSUE_ID="\${TRELLIS_ISSUE_ID:-}"
|
|
2073
|
+
|
|
2074
|
+
# Only run if we're in a Trellis workspace
|
|
2075
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
2076
|
+
exit 0
|
|
2077
|
+
fi
|
|
2078
|
+
|
|
2079
|
+
# Validate issue ID
|
|
2080
|
+
if [ -z "\\$ISSUE_ID" ]; then
|
|
2081
|
+
echo "\u274C Issue ID is required for milestone triage" >&2
|
|
2082
|
+
exit 1
|
|
2083
|
+
fi
|
|
2084
|
+
|
|
2085
|
+
# Get issue details and calculate priority
|
|
2086
|
+
ISSUE_DETAILS=$(trellis issue view "\\$ISSUE_ID" --format json 2>/dev/null || echo "{}")
|
|
2087
|
+
TITLE=$(echo "\\$ISSUE_DETAILS" | jq -r '.title // "Unknown Issue"' 2>/dev/null || echo "Unknown Issue")
|
|
2088
|
+
LABELS=$(echo "\\$ISSUE_DETAILS" | jq -r '.labels // []' 2>/dev/null || echo "[]")
|
|
2089
|
+
SEVERITY=$(echo "\\$LABELS" | jq -r '.[] | select(startswith("severity-")) | split("-")[1]' 2>/dev/null || echo "medium")
|
|
2090
|
+
|
|
2091
|
+
# Get current milestone and cycle info
|
|
2092
|
+
CURRENT_MILESTONE=$(trellis milestone current --format json 2>/dev/null || echo "{}")
|
|
2093
|
+
MILESTONE_NAME=$(echo "\\$CURRENT_MILESTONE" | jq -r '.name // "current"' 2>/dev/null || echo "current")
|
|
2094
|
+
|
|
2095
|
+
CURRENT_CYCLE=$(trellis cycle current --format json 2>/dev/null || echo "{}")
|
|
2096
|
+
CYCLE_NAME=$(echo "\\$CURRENT_CYCLE" | jq -r '.name // "current"' 2>/dev/null || echo "current")
|
|
2097
|
+
|
|
2098
|
+
# Calculate priority based on severity
|
|
2099
|
+
calculate_priority() {
|
|
2100
|
+
local severity="\\$1"
|
|
2101
|
+
case "\\$severity" in
|
|
2102
|
+
"critical") echo "urgent" ;;
|
|
2103
|
+
"high") echo "high" ;;
|
|
2104
|
+
"medium") echo "medium" ;;
|
|
2105
|
+
"low") echo "low" ;;
|
|
2106
|
+
*) echo "medium" ;;
|
|
2107
|
+
esac
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
PRIORITY=$(calculate_priority "\\$SEVERITY")
|
|
2111
|
+
|
|
2112
|
+
# Update issue labels and assign to milestone/cycle
|
|
2113
|
+
trellis issue label "\\$ISSUE_ID" add "triaged" "priority-\\$PRIORITY" "milestone-\\$MILESTONE_NAME" "cycle-\\$CYCLE_NAME" 2>/dev/null || true
|
|
2114
|
+
|
|
2115
|
+
# Update issue priority
|
|
2116
|
+
trellis issue priority "\\$ISSUE_ID" set "\\$PRIORITY" 2>/dev/null || true
|
|
2117
|
+
|
|
2118
|
+
echo ""
|
|
2119
|
+
echo "\uD83C\uDFAF Milestone & Cycle Triage Completed (\\$ORIGIN):"
|
|
2120
|
+
echo " \uD83D\uDCDD Issue: #\\$ISSUE_ID - \\$TITLE"
|
|
2121
|
+
echo " \uD83D\uDEA6 Priority: \\$PRIORITY"
|
|
2122
|
+
echo " \uD83C\uDFAF Milestone: \\$MILESTONE_NAME"
|
|
2123
|
+
echo " \uD83D\uDD04 Cycle: \\$CYCLE_NAME"
|
|
2124
|
+
echo ""
|
|
2125
|
+
`;
|
|
2126
|
+
}
|
|
2127
|
+
function renderCyclePlanningScript() {
|
|
2128
|
+
return `#!/usr/bin/env bash
|
|
2129
|
+
# Cycle planning and workload management for Trellis integration
|
|
2130
|
+
# Manages development cycles, sprint planning, and resource allocation
|
|
2131
|
+
set -euo pipefail
|
|
2132
|
+
|
|
2133
|
+
# Import desk root detection
|
|
2134
|
+
source "\\$(dirname "\\$0")/../desk-root.sh"
|
|
2135
|
+
|
|
2136
|
+
# Environment variables from contract
|
|
2137
|
+
ORIGIN="\${TRELLIS_ORIGIN:-unknown}"
|
|
2138
|
+
OUTPUT="\${TRELLIS_HOOK_OUTPUT:-stdout}"
|
|
2139
|
+
|
|
2140
|
+
# Only run if we're in a Trellis workspace
|
|
2141
|
+
if ! command -v trellis >/dev/null 2>&1; then
|
|
2142
|
+
exit 0
|
|
2143
|
+
fi
|
|
2144
|
+
|
|
2145
|
+
# Get current cycle information
|
|
2146
|
+
CURRENT_CYCLE=$(trellis cycle current --format json 2>/dev/null || echo "{}")
|
|
2147
|
+
CYCLE_NAME=$(echo "\\$CURRENT_CYCLE" | jq -r '.name // "current"' 2>/dev/null || echo "current")
|
|
2148
|
+
|
|
2149
|
+
# Get all issues in current cycle
|
|
2150
|
+
CYCLE_ISSUES=$(trellis cycle issues --format json 2>/dev/null || echo "[]")
|
|
2151
|
+
|
|
2152
|
+
# Analyze cycle workload
|
|
2153
|
+
total_issues=$(echo "\\$CYCLE_ISSUES" | jq 'length' 2>/dev/null || echo "0")
|
|
2154
|
+
urgent_issues=$(echo "\\$CYCLE_ISSUES" | jq '[.[] | select(.labels[] | contains("priority-urgent"))] | length' 2>/dev/null || echo "0")
|
|
2155
|
+
high_issues=$(echo "\\$CYCLE_ISSUES" | jq '[.[] | select(.labels[] | contains("priority-high"))] | length' 2>/dev/null || echo "0")
|
|
2156
|
+
|
|
2157
|
+
# Calculate health score
|
|
2158
|
+
health_score=100
|
|
2159
|
+
health_score=$((health_score - (urgent_issues * 20)))
|
|
2160
|
+
health_score=$((health_score - (high_issues * 10)))
|
|
2161
|
+
|
|
2162
|
+
if [ "\\$health_score" -lt 0 ]; then
|
|
2163
|
+
health_score=0
|
|
2164
|
+
fi
|
|
2165
|
+
|
|
2166
|
+
echo ""
|
|
2167
|
+
echo "\uD83D\uDD04 Cycle Planning Completed (\\$ORIGIN):"
|
|
2168
|
+
echo " \uD83D\uDCCA Cycle: \\$CYCLE_NAME"
|
|
2169
|
+
echo " \uD83D\uDCC8 Health Score: \\$health_score/100"
|
|
2170
|
+
echo " \uD83D\uDCDD Total Issues: \\$total_issues"
|
|
2171
|
+
echo " \uD83D\uDEA8 Urgent Issues: \\$urgent_issues"
|
|
2172
|
+
echo " \u26A1 High Priority Issues: \\$high_issues"
|
|
2173
|
+
echo ""
|
|
2174
|
+
echo "\uD83D\uDCCB Recommendations:"
|
|
2175
|
+
echo " \\$([ "\\$health_score" -lt 60 ] && echo "\uD83D\uDEA8 High workload detected - consider rebalancing" || echo "\u2705 Healthy workload - maintain current pace")"
|
|
2176
|
+
echo " \\$([ "\\$urgent_issues" -gt 0 ] && echo "\u26A0\uFE0F Address urgent issues immediately" || echo "\u2705 No urgent issues")"
|
|
2177
|
+
echo ""
|
|
2178
|
+
`;
|
|
2179
|
+
}
|
|
983
2180
|
var init_write = () => {};
|
|
984
2181
|
|
|
985
2182
|
// src/garden/cluster.ts
|
|
@@ -4868,160 +6065,4 @@ var init_engine = __esm(() => {
|
|
|
4868
6065
|
init_write();
|
|
4869
6066
|
});
|
|
4870
6067
|
|
|
4871
|
-
|
|
4872
|
-
init_profile();
|
|
4873
|
-
init_infer();
|
|
4874
|
-
import { existsSync as existsSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
4875
|
-
import { join as join6 } from "path";
|
|
4876
|
-
async function seedContext(opts) {
|
|
4877
|
-
const { rootPath, ide = "none", force = false } = opts;
|
|
4878
|
-
const filesUpdated = [];
|
|
4879
|
-
const timestamp = new Date().toISOString();
|
|
4880
|
-
const profile = loadProfile();
|
|
4881
|
-
const context = await inferProjectContext(rootPath);
|
|
4882
|
-
const agentsDir = join6(rootPath, ".trellis", "agents");
|
|
4883
|
-
if (existsSync5(agentsDir)) {
|
|
4884
|
-
const agentsMdPath = join6(agentsDir, "AGENTS.md");
|
|
4885
|
-
if (existsSync5(agentsMdPath) || force) {
|
|
4886
|
-
const content = renderSeedAgentsMd(profile, context, timestamp);
|
|
4887
|
-
writeFileSync4(agentsMdPath, content, "utf-8");
|
|
4888
|
-
filesUpdated.push(".trellis/agents/AGENTS.md");
|
|
4889
|
-
}
|
|
4890
|
-
const agentContextPath = join6(agentsDir, "agent-context.json");
|
|
4891
|
-
if (existsSync5(agentContextPath) || force) {
|
|
4892
|
-
const config = {
|
|
4893
|
-
domain: context.domain,
|
|
4894
|
-
ecosystem: context.ecosystem,
|
|
4895
|
-
tools: [],
|
|
4896
|
-
ontologies: [],
|
|
4897
|
-
generatedAt: timestamp,
|
|
4898
|
-
confidence: context.confidence,
|
|
4899
|
-
lastSeed: timestamp
|
|
4900
|
-
};
|
|
4901
|
-
writeFileSync4(agentContextPath, JSON.stringify(config, null, 2), "utf-8");
|
|
4902
|
-
filesUpdated.push(".trellis/agents/agent-context.json");
|
|
4903
|
-
}
|
|
4904
|
-
}
|
|
4905
|
-
switch (ide) {
|
|
4906
|
-
case "cursor": {
|
|
4907
|
-
const cursorRulesPath = join6(rootPath, ".cursor", "rules.md");
|
|
4908
|
-
if (existsSync5(cursorRulesPath) || force) {
|
|
4909
|
-
const content = renderSeedIdeRules(profile, context, "cursor", timestamp);
|
|
4910
|
-
writeFileSync4(cursorRulesPath, content, "utf-8");
|
|
4911
|
-
filesUpdated.push(".cursor/rules.md");
|
|
4912
|
-
}
|
|
4913
|
-
break;
|
|
4914
|
-
}
|
|
4915
|
-
case "windsurf": {
|
|
4916
|
-
const windsurfRulesPath = join6(rootPath, ".windsurf", "rules.md");
|
|
4917
|
-
if (existsSync5(windsurfRulesPath) || force) {
|
|
4918
|
-
const content = renderSeedIdeRules(profile, context, "windsurf", timestamp);
|
|
4919
|
-
writeFileSync4(windsurfRulesPath, content, "utf-8");
|
|
4920
|
-
filesUpdated.push(".windsurf/rules.md");
|
|
4921
|
-
}
|
|
4922
|
-
break;
|
|
4923
|
-
}
|
|
4924
|
-
case "claude": {
|
|
4925
|
-
const claudeSettingsPath = join6(rootPath, ".claude", "settings.md");
|
|
4926
|
-
if (existsSync5(claudeSettingsPath) || force) {
|
|
4927
|
-
const content = renderSeedIdeRules(profile, context, "claude", timestamp);
|
|
4928
|
-
writeFileSync4(claudeSettingsPath, content, "utf-8");
|
|
4929
|
-
filesUpdated.push(".claude/settings.md");
|
|
4930
|
-
}
|
|
4931
|
-
break;
|
|
4932
|
-
}
|
|
4933
|
-
case "none":
|
|
4934
|
-
break;
|
|
4935
|
-
}
|
|
4936
|
-
return {
|
|
4937
|
-
success: true,
|
|
4938
|
-
filesUpdated,
|
|
4939
|
-
timestamp
|
|
4940
|
-
};
|
|
4941
|
-
}
|
|
4942
|
-
function renderSeedAgentsMd(profile, context, timestamp) {
|
|
4943
|
-
const userName = profile?.name ?? "the user";
|
|
4944
|
-
const userBio = profile?.bio ?? "(not provided)";
|
|
4945
|
-
const userSkills = profile?.skills?.length ? profile.skills.join(", ") : "(not specified)";
|
|
4946
|
-
return `# Trellis Agent Context
|
|
4947
|
-
|
|
4948
|
-
> This file was seeded by \`trellis seed\` on ${timestamp}
|
|
4949
|
-
> Inference confidence: **${context.confidence}**
|
|
4950
|
-
|
|
4951
|
-
---
|
|
4952
|
-
|
|
4953
|
-
## About the User
|
|
4954
|
-
|
|
4955
|
-
| Field | Value |
|
|
4956
|
-
|-------|-------|
|
|
4957
|
-
| **Name** | ${userName} |
|
|
4958
|
-
| **Bio** | ${userBio} |
|
|
4959
|
-
| **Skills** | ${userSkills} |
|
|
4960
|
-
|
|
4961
|
-
---
|
|
4962
|
-
|
|
4963
|
-
## About This Project
|
|
4964
|
-
|
|
4965
|
-
| Field | Value |
|
|
4966
|
-
|-------|-------|
|
|
4967
|
-
| **Name** | ${context.name ?? "(unnamed)"} |
|
|
4968
|
-
| **Domain** | ${context.domain ?? "(not determined)"} |
|
|
4969
|
-
| **Description** | ${context.description ?? "(no description found)"} |
|
|
4970
|
-
| **Ecosystem** | ${context.ecosystem ?? "unknown"} |
|
|
4971
|
-
| **File count** | ~${context.fileCount} |
|
|
4972
|
-
|
|
4973
|
-
---
|
|
4974
|
-
|
|
4975
|
-
## Agent Instructions
|
|
4976
|
-
|
|
4977
|
-
You are operating in a Trellis-tracked repository. Follow these guidelines:
|
|
4978
|
-
|
|
4979
|
-
1. **Read \`agent-context.json\`** in this directory for registered tools, ontologies, and domain settings.
|
|
4980
|
-
2. **Check \`skills/\`** for domain-specific operating instructions relevant to this project.
|
|
4981
|
-
3. **Check \`workflows/\`** for repeatable task procedures.
|
|
4982
|
-
4. **Run \`trellis seed\`** to refresh this context file when the project evolves.
|
|
4983
|
-
|
|
4984
|
-
---
|
|
4985
|
-
|
|
4986
|
-
## Quick Reference
|
|
4987
|
-
|
|
4988
|
-
\`\`\`bash
|
|
4989
|
-
trellis status # Current repo state
|
|
4990
|
-
trellis log # Causal operation history
|
|
4991
|
-
trellis seed # Refresh this context
|
|
4992
|
-
trellis milestone # Create narrative checkpoints
|
|
4993
|
-
\`\`\`
|
|
4994
|
-
`;
|
|
4995
|
-
}
|
|
4996
|
-
function renderSeedIdeRules(profile, context, ide, timestamp) {
|
|
4997
|
-
const ideName = ide.charAt(0).toUpperCase() + ide.slice(1);
|
|
4998
|
-
const projectName = context.name ?? "this project";
|
|
4999
|
-
return `# ${ideName} Rules for ${projectName}
|
|
5000
|
-
|
|
5001
|
-
> Generated by \`trellis seed\` on ${timestamp}
|
|
5002
|
-
|
|
5003
|
-
## Project Context
|
|
5004
|
-
- **Domain**: ${context.domain ?? "(not determined)"}
|
|
5005
|
-
- **Ecosystem**: ${context.ecosystem ?? "unknown"}
|
|
5006
|
-
- **File count**: ~${context.fileCount}
|
|
5007
|
-
- **Confidence**: ${context.confidence}
|
|
5008
|
-
|
|
5009
|
-
## Agent Instructions
|
|
5010
|
-
You are working in a Trellis-tracked repository. See \`.trellis/agents/AGENTS.md\` for full context.
|
|
5011
|
-
|
|
5012
|
-
## Commands
|
|
5013
|
-
- \`trellis status\` \u2014 Check repo state
|
|
5014
|
-
- \`trellis seed\` \u2014 Refresh this context file
|
|
5015
|
-
- \`trellis log\` \u2014 View causal history
|
|
5016
|
-
|
|
5017
|
-
---
|
|
5018
|
-
*Auto-generated by Trellis. Run \`trellis seed\` to refresh context.*
|
|
5019
|
-
`;
|
|
5020
|
-
}
|
|
5021
|
-
|
|
5022
|
-
// src/scaffold/index.ts
|
|
5023
|
-
init_infer();
|
|
5024
|
-
init_profile();
|
|
5025
|
-
init_write();
|
|
5026
|
-
|
|
5027
|
-
export { FileWatcher, init_fs_watcher, Ingestion, init_ingestion, inferProjectContext, loadProfile, saveProfile, hasProfile, promptForProfile, updateProfile, writeAgentScaffold, writeIdeScaffold, TrellisVcsEngine, init_engine, seedContext };
|
|
6068
|
+
export { FileWatcher, init_fs_watcher, Ingestion, init_ingestion, inferProjectContext, init_infer, loadProfile, saveProfile, hasProfile, promptForProfile, updateProfile, init_profile, writeAgentScaffold, writeIdeScaffold, init_write, TrellisVcsEngine, init_engine };
|