orbital-command 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +396 -0
- package/bin/orbital.js +362 -0
- package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +84 -0
- package/dist/assets/WorkflowVisualizer-BZV40eAE.css +1 -0
- package/dist/assets/charts-D__PA1zp.js +72 -0
- package/dist/assets/index-D1G6i0nS.css +1 -0
- package/dist/assets/index-DpItvKpf.js +419 -0
- package/dist/assets/ui-BvF022GT.js +53 -0
- package/dist/assets/vendor-Dzv9lrRc.js +59 -0
- package/dist/index.html +19 -0
- package/dist/scanner-sweep.png +0 -0
- package/dist/server/server/adapters/index.js +34 -0
- package/dist/server/server/adapters/iterm2-adapter.js +29 -0
- package/dist/server/server/adapters/subprocess-adapter.js +21 -0
- package/dist/server/server/adapters/terminal-adapter.js +1 -0
- package/dist/server/server/config.js +156 -0
- package/dist/server/server/database.js +90 -0
- package/dist/server/server/index.js +372 -0
- package/dist/server/server/init.js +811 -0
- package/dist/server/server/parsers/event-parser.js +64 -0
- package/dist/server/server/parsers/scope-parser.js +188 -0
- package/dist/server/server/routes/config-routes.js +163 -0
- package/dist/server/server/routes/data-routes.js +461 -0
- package/dist/server/server/routes/dispatch-routes.js +215 -0
- package/dist/server/server/routes/git-routes.js +92 -0
- package/dist/server/server/routes/scope-routes.js +215 -0
- package/dist/server/server/routes/sprint-routes.js +116 -0
- package/dist/server/server/routes/version-routes.js +130 -0
- package/dist/server/server/routes/workflow-routes.js +185 -0
- package/dist/server/server/schema.js +90 -0
- package/dist/server/server/services/batch-orchestrator.js +253 -0
- package/dist/server/server/services/claude-session-service.js +352 -0
- package/dist/server/server/services/config-service.js +132 -0
- package/dist/server/server/services/deploy-service.js +51 -0
- package/dist/server/server/services/event-service.js +63 -0
- package/dist/server/server/services/gate-service.js +83 -0
- package/dist/server/server/services/git-service.js +309 -0
- package/dist/server/server/services/github-service.js +145 -0
- package/dist/server/server/services/readiness-service.js +184 -0
- package/dist/server/server/services/scope-cache.js +72 -0
- package/dist/server/server/services/scope-service.js +424 -0
- package/dist/server/server/services/sprint-orchestrator.js +312 -0
- package/dist/server/server/services/sprint-service.js +293 -0
- package/dist/server/server/services/workflow-service.js +397 -0
- package/dist/server/server/utils/cc-hooks-parser.js +49 -0
- package/dist/server/server/utils/dispatch-utils.js +305 -0
- package/dist/server/server/utils/logger.js +86 -0
- package/dist/server/server/utils/terminal-launcher.js +388 -0
- package/dist/server/server/utils/worktree-manager.js +98 -0
- package/dist/server/server/watchers/event-watcher.js +81 -0
- package/dist/server/server/watchers/scope-watcher.js +33 -0
- package/dist/server/shared/api-types.js +5 -0
- package/dist/server/shared/default-workflow.json +616 -0
- package/dist/server/shared/workflow-config.js +44 -0
- package/dist/server/shared/workflow-engine.js +353 -0
- package/index.html +15 -0
- package/package.json +110 -0
- package/postcss.config.js +6 -0
- package/schemas/orbital.config.schema.json +83 -0
- package/scripts/postinstall.js +24 -0
- package/scripts/start.sh +20 -0
- package/server/adapters/index.ts +41 -0
- package/server/adapters/iterm2-adapter.ts +37 -0
- package/server/adapters/subprocess-adapter.ts +25 -0
- package/server/adapters/terminal-adapter.ts +24 -0
- package/server/config.ts +234 -0
- package/server/database.ts +107 -0
- package/server/index.ts +452 -0
- package/server/init.ts +891 -0
- package/server/parsers/event-parser.ts +74 -0
- package/server/parsers/scope-parser.ts +240 -0
- package/server/routes/config-routes.ts +182 -0
- package/server/routes/data-routes.ts +548 -0
- package/server/routes/dispatch-routes.ts +275 -0
- package/server/routes/git-routes.ts +112 -0
- package/server/routes/scope-routes.ts +262 -0
- package/server/routes/sprint-routes.ts +142 -0
- package/server/routes/version-routes.ts +156 -0
- package/server/routes/workflow-routes.ts +198 -0
- package/server/schema.ts +90 -0
- package/server/services/batch-orchestrator.ts +286 -0
- package/server/services/claude-session-service.ts +441 -0
- package/server/services/config-service.ts +151 -0
- package/server/services/deploy-service.ts +98 -0
- package/server/services/event-service.ts +98 -0
- package/server/services/gate-service.ts +126 -0
- package/server/services/git-service.ts +391 -0
- package/server/services/github-service.ts +183 -0
- package/server/services/readiness-service.ts +250 -0
- package/server/services/scope-cache.ts +81 -0
- package/server/services/scope-service.ts +476 -0
- package/server/services/sprint-orchestrator.ts +361 -0
- package/server/services/sprint-service.ts +415 -0
- package/server/services/workflow-service.ts +461 -0
- package/server/utils/cc-hooks-parser.ts +70 -0
- package/server/utils/dispatch-utils.ts +395 -0
- package/server/utils/logger.ts +109 -0
- package/server/utils/terminal-launcher.ts +462 -0
- package/server/utils/worktree-manager.ts +104 -0
- package/server/watchers/event-watcher.ts +100 -0
- package/server/watchers/scope-watcher.ts +38 -0
- package/shared/api-types.ts +20 -0
- package/shared/default-workflow.json +616 -0
- package/shared/workflow-config.ts +170 -0
- package/shared/workflow-engine.ts +427 -0
- package/src/App.tsx +33 -0
- package/src/components/AgentBadge.tsx +40 -0
- package/src/components/BatchPreflightModal.tsx +115 -0
- package/src/components/CardDisplayToggle.tsx +74 -0
- package/src/components/ColumnHeaderActions.tsx +55 -0
- package/src/components/ColumnMenu.tsx +99 -0
- package/src/components/DeployHistory.tsx +141 -0
- package/src/components/DispatchModal.tsx +164 -0
- package/src/components/DispatchPopover.tsx +139 -0
- package/src/components/DragOverlay.tsx +25 -0
- package/src/components/DriftSidebar.tsx +140 -0
- package/src/components/EnvironmentStrip.tsx +88 -0
- package/src/components/ErrorBoundary.tsx +62 -0
- package/src/components/FilterChip.tsx +105 -0
- package/src/components/GateIndicator.tsx +33 -0
- package/src/components/IdeaDetailModal.tsx +190 -0
- package/src/components/IdeaFormDialog.tsx +113 -0
- package/src/components/KanbanColumn.tsx +201 -0
- package/src/components/MarkdownRenderer.tsx +114 -0
- package/src/components/NeonGrid.tsx +128 -0
- package/src/components/PromotionQueue.tsx +89 -0
- package/src/components/ScopeCard.tsx +234 -0
- package/src/components/ScopeDetailModal.tsx +255 -0
- package/src/components/ScopeFilterBar.tsx +152 -0
- package/src/components/SearchInput.tsx +102 -0
- package/src/components/SessionPanel.tsx +335 -0
- package/src/components/SprintContainer.tsx +303 -0
- package/src/components/SprintDependencyDialog.tsx +78 -0
- package/src/components/SprintPreflightModal.tsx +138 -0
- package/src/components/StatusBar.tsx +168 -0
- package/src/components/SwimCell.tsx +67 -0
- package/src/components/SwimLaneRow.tsx +94 -0
- package/src/components/SwimlaneBoardView.tsx +108 -0
- package/src/components/VersionBadge.tsx +139 -0
- package/src/components/ViewModeSelector.tsx +114 -0
- package/src/components/config/AgentChip.tsx +53 -0
- package/src/components/config/AgentCreateDialog.tsx +321 -0
- package/src/components/config/AgentEditor.tsx +175 -0
- package/src/components/config/DirectoryTree.tsx +582 -0
- package/src/components/config/FileEditor.tsx +550 -0
- package/src/components/config/HookChip.tsx +50 -0
- package/src/components/config/StageCard.tsx +198 -0
- package/src/components/config/TransitionZone.tsx +173 -0
- package/src/components/config/UnifiedWorkflowPipeline.tsx +216 -0
- package/src/components/config/WorkflowPipeline.tsx +161 -0
- package/src/components/source-control/BranchList.tsx +93 -0
- package/src/components/source-control/BranchPanel.tsx +105 -0
- package/src/components/source-control/CommitLog.tsx +100 -0
- package/src/components/source-control/CommitRow.tsx +47 -0
- package/src/components/source-control/GitHubPanel.tsx +110 -0
- package/src/components/source-control/GitHubSetupGuide.tsx +52 -0
- package/src/components/source-control/GitOverviewBar.tsx +101 -0
- package/src/components/source-control/PullRequestList.tsx +69 -0
- package/src/components/source-control/WorktreeList.tsx +80 -0
- package/src/components/ui/badge.tsx +41 -0
- package/src/components/ui/button.tsx +55 -0
- package/src/components/ui/card.tsx +78 -0
- package/src/components/ui/dialog.tsx +94 -0
- package/src/components/ui/popover.tsx +33 -0
- package/src/components/ui/scroll-area.tsx +54 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/tabs.tsx +52 -0
- package/src/components/ui/toggle-switch.tsx +35 -0
- package/src/components/ui/tooltip.tsx +27 -0
- package/src/components/workflow/AddEdgeDialog.tsx +217 -0
- package/src/components/workflow/AddListDialog.tsx +201 -0
- package/src/components/workflow/ChecklistEditor.tsx +239 -0
- package/src/components/workflow/CommandPrefixManager.tsx +118 -0
- package/src/components/workflow/ConfigSettingsPanel.tsx +189 -0
- package/src/components/workflow/DirectionSelector.tsx +133 -0
- package/src/components/workflow/DispatchConfigPanel.tsx +180 -0
- package/src/components/workflow/EdgeDetailPanel.tsx +236 -0
- package/src/components/workflow/EdgePropertyEditor.tsx +251 -0
- package/src/components/workflow/EditToolbar.tsx +138 -0
- package/src/components/workflow/HookDetailPanel.tsx +250 -0
- package/src/components/workflow/HookExecutionLog.tsx +24 -0
- package/src/components/workflow/HookSourceModal.tsx +129 -0
- package/src/components/workflow/HooksDashboard.tsx +363 -0
- package/src/components/workflow/ListPropertyEditor.tsx +251 -0
- package/src/components/workflow/MigrationPreviewDialog.tsx +237 -0
- package/src/components/workflow/MovementRulesPanel.tsx +188 -0
- package/src/components/workflow/NodeDetailPanel.tsx +245 -0
- package/src/components/workflow/PresetSelector.tsx +414 -0
- package/src/components/workflow/SkillCommandBuilder.tsx +174 -0
- package/src/components/workflow/WorkflowEdgeComponent.tsx +145 -0
- package/src/components/workflow/WorkflowNode.tsx +147 -0
- package/src/components/workflow/graphLayout.ts +186 -0
- package/src/components/workflow/mergeHooks.ts +85 -0
- package/src/components/workflow/useEditHistory.ts +88 -0
- package/src/components/workflow/useWorkflowEditor.ts +262 -0
- package/src/components/workflow/validateConfig.ts +70 -0
- package/src/hooks/useActiveDispatches.ts +198 -0
- package/src/hooks/useBoardSettings.ts +170 -0
- package/src/hooks/useCardDisplay.ts +57 -0
- package/src/hooks/useCcHooks.ts +24 -0
- package/src/hooks/useConfigTree.ts +51 -0
- package/src/hooks/useEnforcementRules.ts +46 -0
- package/src/hooks/useEvents.ts +59 -0
- package/src/hooks/useFileEditor.ts +165 -0
- package/src/hooks/useGates.ts +57 -0
- package/src/hooks/useIdeaActions.ts +53 -0
- package/src/hooks/useKanbanDnd.ts +410 -0
- package/src/hooks/useOrbitalConfig.ts +54 -0
- package/src/hooks/usePipeline.ts +47 -0
- package/src/hooks/usePipelineData.ts +338 -0
- package/src/hooks/useReconnect.ts +25 -0
- package/src/hooks/useScopeFilters.ts +125 -0
- package/src/hooks/useScopeSessions.ts +44 -0
- package/src/hooks/useScopes.ts +67 -0
- package/src/hooks/useSearch.ts +67 -0
- package/src/hooks/useSettings.tsx +187 -0
- package/src/hooks/useSocket.ts +25 -0
- package/src/hooks/useSourceControl.ts +105 -0
- package/src/hooks/useSprintPreflight.ts +55 -0
- package/src/hooks/useSprints.ts +154 -0
- package/src/hooks/useStatusBarHighlight.ts +18 -0
- package/src/hooks/useSwimlaneBoardSettings.ts +104 -0
- package/src/hooks/useTheme.ts +9 -0
- package/src/hooks/useTransitionReadiness.ts +53 -0
- package/src/hooks/useVersion.ts +155 -0
- package/src/hooks/useViolations.ts +65 -0
- package/src/hooks/useWorkflow.tsx +125 -0
- package/src/hooks/useZoomModifier.ts +19 -0
- package/src/index.css +797 -0
- package/src/layouts/DashboardLayout.tsx +113 -0
- package/src/lib/collisionDetection.ts +20 -0
- package/src/lib/scope-fields.ts +61 -0
- package/src/lib/swimlane.ts +146 -0
- package/src/lib/utils.ts +15 -0
- package/src/main.tsx +19 -0
- package/src/socket.ts +11 -0
- package/src/types/index.ts +497 -0
- package/src/views/AgentFeed.tsx +339 -0
- package/src/views/DeployPipeline.tsx +59 -0
- package/src/views/EnforcementView.tsx +378 -0
- package/src/views/PrimitivesConfig.tsx +500 -0
- package/src/views/QualityGates.tsx +1012 -0
- package/src/views/ScopeBoard.tsx +454 -0
- package/src/views/SessionTimeline.tsx +516 -0
- package/src/views/Settings.tsx +183 -0
- package/src/views/SourceControl.tsx +95 -0
- package/src/views/WorkflowVisualizer.tsx +382 -0
- package/tailwind.config.js +161 -0
- package/templates/agents/AUTO-INVOKE.md +180 -0
- package/templates/agents/CONFLICT-RESOLUTION.md +128 -0
- package/templates/agents/QUICK-REFERENCE.md +122 -0
- package/templates/agents/README.md +188 -0
- package/templates/agents/SKILL-TRIGGERS.md +100 -0
- package/templates/agents/blue-team/frontend-designer.md +424 -0
- package/templates/agents/green-team/architect.md +526 -0
- package/templates/agents/green-team/rules-enforcer.md +131 -0
- package/templates/agents/red-team/attacker-learned.md +24 -0
- package/templates/agents/red-team/attacker.md +486 -0
- package/templates/agents/red-team/chaos.md +548 -0
- package/templates/agents/reference/component-registry.md +82 -0
- package/templates/agents/workflows/full-mode.md +218 -0
- package/templates/agents/workflows/quick-mode.md +118 -0
- package/templates/agents/workflows/security-mode.md +283 -0
- package/templates/anti-patterns/dangerous-shortcuts.md +427 -0
- package/templates/config/agent-triggers.json +92 -0
- package/templates/hooks/agent-team-gate.sh +31 -0
- package/templates/hooks/agent-trigger.sh +97 -0
- package/templates/hooks/block-push.sh +66 -0
- package/templates/hooks/block-workarounds.sh +61 -0
- package/templates/hooks/blocker-check.sh +28 -0
- package/templates/hooks/completion-checklist.sh +28 -0
- package/templates/hooks/decision-capture.sh +15 -0
- package/templates/hooks/dependency-check.sh +27 -0
- package/templates/hooks/end-session.sh +31 -0
- package/templates/hooks/exploration-logger.sh +37 -0
- package/templates/hooks/files-changed-summary.sh +37 -0
- package/templates/hooks/get-session-id.sh +49 -0
- package/templates/hooks/git-commit-guard.sh +34 -0
- package/templates/hooks/init-session.sh +93 -0
- package/templates/hooks/orbital-emit.sh +79 -0
- package/templates/hooks/orbital-report-deploy.sh +78 -0
- package/templates/hooks/orbital-report-gates.sh +40 -0
- package/templates/hooks/orbital-report-violation.sh +36 -0
- package/templates/hooks/orbital-scope-update.sh +53 -0
- package/templates/hooks/phase-verify-reminder.sh +26 -0
- package/templates/hooks/review-gate-check.sh +82 -0
- package/templates/hooks/scope-commit-logger.sh +37 -0
- package/templates/hooks/scope-create-cleanup.sh +36 -0
- package/templates/hooks/scope-create-gate.sh +80 -0
- package/templates/hooks/scope-create-tracker.sh +17 -0
- package/templates/hooks/scope-file-sync.sh +53 -0
- package/templates/hooks/scope-gate.sh +35 -0
- package/templates/hooks/scope-helpers.sh +188 -0
- package/templates/hooks/scope-lifecycle-gate.sh +139 -0
- package/templates/hooks/scope-prepare.sh +244 -0
- package/templates/hooks/scope-transition.sh +172 -0
- package/templates/hooks/session-enforcer.sh +143 -0
- package/templates/hooks/time-tracker.sh +33 -0
- package/templates/lessons-learned.md +15 -0
- package/templates/orbital.config.json +35 -0
- package/templates/presets/development.json +42 -0
- package/templates/presets/gitflow.json +712 -0
- package/templates/presets/minimal.json +23 -0
- package/templates/quick/rules.md +218 -0
- package/templates/scopes/_template.md +255 -0
- package/templates/settings-hooks.json +98 -0
- package/templates/skills/git-commit/SKILL.md +85 -0
- package/templates/skills/git-dev/SKILL.md +99 -0
- package/templates/skills/git-hotfix/SKILL.md +223 -0
- package/templates/skills/git-main/SKILL.md +84 -0
- package/templates/skills/git-production/SKILL.md +165 -0
- package/templates/skills/git-staging/SKILL.md +112 -0
- package/templates/skills/scope-create/SKILL.md +81 -0
- package/templates/skills/scope-fix-review/SKILL.md +168 -0
- package/templates/skills/scope-implement/SKILL.md +110 -0
- package/templates/skills/scope-post-review/SKILL.md +144 -0
- package/templates/skills/scope-pre-review/SKILL.md +211 -0
- package/templates/skills/scope-verify/SKILL.md +201 -0
- package/templates/skills/session-init/SKILL.md +62 -0
- package/templates/skills/session-resume/SKILL.md +201 -0
- package/templates/skills/test-checks/SKILL.md +171 -0
- package/templates/skills/test-code-review/SKILL.md +252 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +38 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# block-push.sh — PreToolUse:Bash hook
|
|
3
|
+
#
|
|
4
|
+
# Enforces stage-specific git restrictions using flag files
|
|
5
|
+
# managed by git-commit-guard.sh (PreToolUse:Skill):
|
|
6
|
+
# .block-push-active → blocks git push (during /git-commit)
|
|
7
|
+
# .implementing-session → blocks git commit/add (during /scope-implement)
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
INPUT=$(cat)
|
|
11
|
+
|
|
12
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
13
|
+
|
|
14
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
15
|
+
[ -z "$TOOL_NAME" ] && TOOL_NAME="$CLAUDE_TOOL_NAME"
|
|
16
|
+
[ "$TOOL_NAME" != "Bash" ] && exit 0
|
|
17
|
+
|
|
18
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
|
|
19
|
+
PUSH_FLAG="$PROJECT_DIR/.claude/.block-push-active"
|
|
20
|
+
IMPL_FLAG="$PROJECT_DIR/.claude/.implementing-session"
|
|
21
|
+
|
|
22
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
23
|
+
[ -z "$COMMAND" ] && COMMAND="$INPUT"
|
|
24
|
+
|
|
25
|
+
HOOK_DIR="$(dirname "$0")"
|
|
26
|
+
|
|
27
|
+
# Build workflow-specific pipeline hint from manifest (only on block path)
|
|
28
|
+
_pipeline_after() {
|
|
29
|
+
local start="$1" found=false result=""
|
|
30
|
+
source "$HOOK_DIR/scope-helpers.sh" 2>/dev/null || return
|
|
31
|
+
for s in $WORKFLOW_STATUSES; do
|
|
32
|
+
if [ "$found" = true ]; then
|
|
33
|
+
result="${result:+$result → }$s"
|
|
34
|
+
fi
|
|
35
|
+
[ "$s" = "$start" ] && found=true
|
|
36
|
+
done
|
|
37
|
+
echo "$result"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Block git push during /git-commit
|
|
41
|
+
if [ -f "$PUSH_FLAG" ]; then
|
|
42
|
+
if echo "$COMMAND" | grep -qE '(^|[;&|]\s*)git\s+push'; then
|
|
43
|
+
"$HOOK_DIR/orbital-emit.sh" VIOLATION '{"rule":"block-push","outcome":"blocked"}' 2>/dev/null || true
|
|
44
|
+
REMAINING=$(_pipeline_after "completed")
|
|
45
|
+
echo "BLOCKED: /git-commit only commits locally — it does not push to remote."
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Your job is done once the commit is created. Do not push."
|
|
48
|
+
echo "The next workflow step pushes to: ${REMAINING:-the next stage}."
|
|
49
|
+
exit 2
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Block git commit/add during /scope-implement
|
|
54
|
+
if [ -f "$IMPL_FLAG" ]; then
|
|
55
|
+
if echo "$COMMAND" | grep -qE '(^|[;&|]\s*)git\s+(commit|add)'; then
|
|
56
|
+
"$HOOK_DIR/orbital-emit.sh" VIOLATION '{"rule":"block-commit-implementing","outcome":"blocked"}' 2>/dev/null || true
|
|
57
|
+
REMAINING=$(_pipeline_after "implementing")
|
|
58
|
+
echo "BLOCKED: Implementing sessions must not commit."
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Code changes stay uncommitted until the review pipeline handles them."
|
|
61
|
+
echo "Remaining pipeline: ${REMAINING:-review → completed}."
|
|
62
|
+
exit 2
|
|
63
|
+
fi
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
exit 0
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Claude Code PreToolUse Hook: Block Dangerous Workarounds
|
|
4
|
+
#
|
|
5
|
+
# Blocks two critical patterns that bypass safety:
|
|
6
|
+
# 1. --no-verify (skips pre-commit hooks)
|
|
7
|
+
# 2. Direct push to main (bypasses PR workflow)
|
|
8
|
+
#
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
INPUT=$(cat)
|
|
12
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
13
|
+
|
|
14
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
15
|
+
[ -z "$TOOL_NAME" ] && TOOL_NAME="$CLAUDE_TOOL_NAME"
|
|
16
|
+
|
|
17
|
+
# Only process Bash tool calls
|
|
18
|
+
[ "$TOOL_NAME" != "Bash" ] && exit 0
|
|
19
|
+
|
|
20
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
21
|
+
[ -z "$COMMAND" ] && COMMAND="$INPUT"
|
|
22
|
+
|
|
23
|
+
HOOK_DIR="$(dirname "$0")"
|
|
24
|
+
|
|
25
|
+
# Override mechanism: OVERRIDE_RULE="rule-name:reason"
|
|
26
|
+
# When set, logs the override and allows the command through
|
|
27
|
+
if [ -n "${OVERRIDE_RULE:-}" ]; then
|
|
28
|
+
RULE_NAME="${OVERRIDE_RULE%%:*}"
|
|
29
|
+
REASON="${OVERRIDE_RULE#*:}"
|
|
30
|
+
OVERRIDE_DATA=$(jq -n --arg rule "$RULE_NAME" --arg reason "$REASON" --arg outcome "overridden" '{rule: $rule, reason: $reason, outcome: $outcome}')
|
|
31
|
+
"$HOOK_DIR/orbital-emit.sh" OVERRIDE "$OVERRIDE_DATA"
|
|
32
|
+
echo "OVERRIDE: Rule '$RULE_NAME' overridden (reason: $REASON)"
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Pattern 1: --no-verify flag
|
|
37
|
+
if echo "$COMMAND" | grep -qE "\-\-no-verify"; then
|
|
38
|
+
"$HOOK_DIR/orbital-emit.sh" VIOLATION '{"rule":"no-verify","pattern":"--no-verify","outcome":"blocked"}'
|
|
39
|
+
echo "BLOCKED: Attempting to skip verification hooks"
|
|
40
|
+
echo ""
|
|
41
|
+
echo "Fix the failing checks instead:"
|
|
42
|
+
echo " cd backend && npm run type-check"
|
|
43
|
+
echo " cd backend && npm run lint"
|
|
44
|
+
echo ""
|
|
45
|
+
echo "If a check is genuinely wrong, discuss with the user."
|
|
46
|
+
exit 2
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Pattern 2: Direct push to main (covers: git push origin main, git push --force origin main, HEAD:main)
|
|
50
|
+
if echo "$COMMAND" | grep -qE 'git push\b.*\bmain\b|HEAD:main'; then
|
|
51
|
+
"$HOOK_DIR/orbital-emit.sh" VIOLATION '{"rule":"push-main","pattern":"push to main","outcome":"blocked"}'
|
|
52
|
+
echo "BLOCKED: Direct push to main is forbidden"
|
|
53
|
+
echo ""
|
|
54
|
+
echo "Use /git-commit to route to the proper workflow:"
|
|
55
|
+
echo " - Creates feature branch if needed"
|
|
56
|
+
echo " - Opens PR to staging (not main)"
|
|
57
|
+
echo " - Ensures CI runs before merge"
|
|
58
|
+
exit 2
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
exit 0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# blocker-check.sh — Note unresolved blockers when advancing scope status
|
|
3
|
+
# Trigger: PreToolUse:Edit (scope file with status change)
|
|
4
|
+
# Nudge-style: always exits 0
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
9
|
+
|
|
10
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
11
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty')
|
|
12
|
+
|
|
13
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
14
|
+
is_scope_file "$FILE_PATH" || exit 0
|
|
15
|
+
echo "$NEW_STRING" | grep -qiE "status:.*implementing|status:.*backlog|In Progress" || exit 0
|
|
16
|
+
|
|
17
|
+
# Count BLOCKER references (exclude resolved ones)
|
|
18
|
+
[ -f "$FILE_PATH" ] || exit 0
|
|
19
|
+
BLOCKERS=$(grep -c "^- \[B-" "$FILE_PATH" || echo "0")
|
|
20
|
+
|
|
21
|
+
if [ "$BLOCKERS" -gt 0 ]; then
|
|
22
|
+
echo ""
|
|
23
|
+
echo "🚧 $BLOCKERS blocker(s) found in $(basename "$FILE_PATH")"
|
|
24
|
+
echo " Verify all are resolved before advancing status."
|
|
25
|
+
echo ""
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
exit 0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# completion-checklist.sh — Block completion when Definition of Done items are unchecked
|
|
3
|
+
# Trigger: PreToolUse:Edit (scope status → complete)
|
|
4
|
+
# Blocking: exits 2 when unchecked DoD items found
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
9
|
+
|
|
10
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
11
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty')
|
|
12
|
+
|
|
13
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
14
|
+
is_scope_file "$FILE_PATH" || exit 0
|
|
15
|
+
echo "$NEW_STRING" | grep -qiE "status:.*complete" || exit 0
|
|
16
|
+
|
|
17
|
+
# Count unchecked DoD items
|
|
18
|
+
UNCHECKED=$(sed -n '/Definition of Done/,/^═/p' "$FILE_PATH" 2>/dev/null | grep -c "\- \[ \]")
|
|
19
|
+
|
|
20
|
+
if [ "${UNCHECKED:-0}" -gt 0 ]; then
|
|
21
|
+
echo "" >&2
|
|
22
|
+
echo "MUST_BLOCK: $UNCHECKED unchecked Definition of Done items in $(basename "$FILE_PATH")" >&2
|
|
23
|
+
echo " Check all items in the '## Definition of Done' section: - [x] item (checked) vs - [ ] item (unchecked)." >&2
|
|
24
|
+
echo "" >&2
|
|
25
|
+
exit 2
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
exit 0
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# decision-capture.sh — Prompt to log decisions after user questions
|
|
3
|
+
# Trigger: PostToolUse:AskUserQuestion
|
|
4
|
+
# Nudge-style: always exits 0
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
8
|
+
SCOPE=$(find_active_scope) || exit 0
|
|
9
|
+
|
|
10
|
+
echo ""
|
|
11
|
+
echo "📋 User decision made — consider logging in"
|
|
12
|
+
echo " PROCESS > Decisions & Reasoning of $(basename "$SCOPE")"
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
exit 0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# dependency-check.sh — Check blocked_by dependencies when advancing status
|
|
3
|
+
# Trigger: PreToolUse:Edit (scope file with status change)
|
|
4
|
+
# Nudge-style: always exits 0
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
9
|
+
|
|
10
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
11
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty')
|
|
12
|
+
|
|
13
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
14
|
+
is_scope_file "$FILE_PATH" || exit 0
|
|
15
|
+
echo "$NEW_STRING" | grep -qiE "status:.*implementing|status:.*backlog" || exit 0
|
|
16
|
+
|
|
17
|
+
# Extract blocked_by from frontmatter
|
|
18
|
+
BLOCKED_BY=$(sed -n '2,/^---$/p' "$FILE_PATH" | grep "^blocked_by:" | sed 's/blocked_by:[[:space:]]*//' | tr -d '[]"')
|
|
19
|
+
|
|
20
|
+
if [ -n "$BLOCKED_BY" ] && [ "$BLOCKED_BY" != " " ]; then
|
|
21
|
+
echo ""
|
|
22
|
+
echo "🔗 Dependencies: blocked_by: $BLOCKED_BY"
|
|
23
|
+
echo " Verify blocking scopes are complete before starting."
|
|
24
|
+
echo ""
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
exit 0
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Claude Code SessionEnd Hook: Session Cleanup
|
|
4
|
+
#
|
|
5
|
+
# Emits SESSION_END event to Orbital dashboard so active dispatch indicators
|
|
6
|
+
# are cleared when a Claude session exits normally.
|
|
7
|
+
#
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
PID="$PPID"
|
|
13
|
+
|
|
14
|
+
# Emit session end event to Orbital dashboard (non-blocking)
|
|
15
|
+
SESSION_DATA="{\"pid\":$PID"
|
|
16
|
+
# Include dispatch ID if this session was launched by Orbital dispatch
|
|
17
|
+
if [ -n "$ORBITAL_DISPATCH_ID" ]; then
|
|
18
|
+
SESSION_DATA="${SESSION_DATA},\"dispatch_id\":\"$ORBITAL_DISPATCH_ID\""
|
|
19
|
+
fi
|
|
20
|
+
SESSION_DATA="${SESSION_DATA}}"
|
|
21
|
+
"$SCRIPT_DIR/orbital-emit.sh" SESSION_END "$SESSION_DATA" 2>/dev/null &
|
|
22
|
+
|
|
23
|
+
# Clean up cached session ID file (new glob format + old format)
|
|
24
|
+
rm -f "$PROJECT_DIR/.claude/metrics/.session-ids/${PID}"-* 2>/dev/null
|
|
25
|
+
rm -f "$PROJECT_DIR/.claude/metrics/.session-ids/$PID" 2>/dev/null
|
|
26
|
+
|
|
27
|
+
# Clean up skill guard flags
|
|
28
|
+
rm -f "$PROJECT_DIR/.claude/.block-push-active" 2>/dev/null
|
|
29
|
+
|
|
30
|
+
# SessionEnd hooks must never block termination
|
|
31
|
+
exit 0
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# exploration-logger.sh — Remind to log exploration findings periodically
|
|
3
|
+
# Trigger: PostToolUse:Grep|Glob (search operations)
|
|
4
|
+
# Nudge-style: always exits 0
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
9
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
10
|
+
[[ "$TOOL_NAME" == "Grep" || "$TOOL_NAME" == "Glob" ]] || exit 0
|
|
11
|
+
|
|
12
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
13
|
+
COUNTER_FILE="$PROJECT_DIR/.claude/metrics/.exploration-count"
|
|
14
|
+
mkdir -p "$(dirname "$COUNTER_FILE")"
|
|
15
|
+
|
|
16
|
+
# Atomic counter increment with flock
|
|
17
|
+
(
|
|
18
|
+
flock -x 200 2>/dev/null || true
|
|
19
|
+
COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
|
|
20
|
+
COUNT=$((COUNT + 1))
|
|
21
|
+
echo "$COUNT" > "$COUNTER_FILE"
|
|
22
|
+
) 200>"${COUNTER_FILE}.lock"
|
|
23
|
+
rm -f "${COUNTER_FILE}.lock"
|
|
24
|
+
COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
|
|
25
|
+
|
|
26
|
+
# Remind every 25 searches
|
|
27
|
+
if [ $((COUNT % 25)) -eq 0 ]; then
|
|
28
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
29
|
+
SCOPE=$(find_active_scope) || exit 0
|
|
30
|
+
|
|
31
|
+
echo ""
|
|
32
|
+
echo "🔍 $COUNT searches this session — log key findings in"
|
|
33
|
+
echo " PROCESS > Exploration Log of $(basename "$SCOPE")"
|
|
34
|
+
echo ""
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
exit 0
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# files-changed-summary.sh — Show planned vs actual files before completion
|
|
3
|
+
# Trigger: PreToolUse:Edit (scope status → complete)
|
|
4
|
+
# Nudge-style: always exits 0
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
9
|
+
|
|
10
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
11
|
+
NEW_STRING=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty')
|
|
12
|
+
|
|
13
|
+
source "$(dirname "$0")/scope-helpers.sh"
|
|
14
|
+
is_scope_file "$FILE_PATH" || exit 0
|
|
15
|
+
echo "$NEW_STRING" | grep -qiE "status:.*complete" || exit 0
|
|
16
|
+
|
|
17
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
18
|
+
|
|
19
|
+
# Count file references in scope
|
|
20
|
+
PLANNED=$(grep -cE '`[^`]+\.(ts|tsx|js|jsx|css|sh)`' "$FILE_PATH" 2>/dev/null || echo "?")
|
|
21
|
+
|
|
22
|
+
# Count actual files changed since scope began (use baseCommit if available)
|
|
23
|
+
BASE_COMMIT=$(get_frontmatter "$FILE_PATH" "baseCommit" 2>/dev/null)
|
|
24
|
+
if [ -n "$BASE_COMMIT" ]; then
|
|
25
|
+
ACTUAL=$(cd "$PROJECT_DIR" && git diff --name-only "$BASE_COMMIT"...HEAD 2>/dev/null | wc -l | tr -d ' ')
|
|
26
|
+
else
|
|
27
|
+
ACTUAL=$(cd "$PROJECT_DIR" && git diff --name-only HEAD~5 2>/dev/null | wc -l | tr -d ' ')
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
echo ""
|
|
31
|
+
echo "📂 Scope completion summary for $(basename "$FILE_PATH"):"
|
|
32
|
+
echo " Planned: ~$PLANNED file references in scope"
|
|
33
|
+
echo " Changed: ~$ACTUAL files in recent commits"
|
|
34
|
+
echo " Review PROCESS > Deviations from Spec if significant difference"
|
|
35
|
+
echo ""
|
|
36
|
+
|
|
37
|
+
exit 0
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# get-session-id.sh — Parallel-safe session UUID lookup
|
|
3
|
+
#
|
|
4
|
+
# Reads the session ID cached by init-session.sh at session start.
|
|
5
|
+
# Walks up the process tree from $PPID to find the session file,
|
|
6
|
+
# which handles callers nested at any depth (e.g. subagent shells).
|
|
7
|
+
#
|
|
8
|
+
# Usage (from skills via Bash tool):
|
|
9
|
+
# SESSION_UUID=$(bash .claude/hooks/get-session-id.sh)
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 — Success, UUID printed to stdout
|
|
13
|
+
# 1 — Session ID not found
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
17
|
+
SESSION_DIR="$PROJECT_DIR/.claude/metrics/.session-ids"
|
|
18
|
+
|
|
19
|
+
# Walk up the process tree checking each ancestor PID.
|
|
20
|
+
# init-session.sh keys on $PPID (Claude Code's PID), but callers
|
|
21
|
+
# may be nested deeper (e.g. Skill tool -> Bash tool -> this script).
|
|
22
|
+
CURRENT_PID=$PPID
|
|
23
|
+
VISITED=""
|
|
24
|
+
while [ "$CURRENT_PID" -gt 1 ] 2>/dev/null; do
|
|
25
|
+
# Cycle detection
|
|
26
|
+
case " $VISITED " in
|
|
27
|
+
*" $CURRENT_PID "*) break ;;
|
|
28
|
+
esac
|
|
29
|
+
VISITED="$VISITED $CURRENT_PID"
|
|
30
|
+
|
|
31
|
+
# New format: {PID}-{UUID}
|
|
32
|
+
for f in "$SESSION_DIR/${CURRENT_PID}"-*; do
|
|
33
|
+
if [ -f "$f" ]; then
|
|
34
|
+
cat "$f"
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
done
|
|
38
|
+
# Old format: just {PID}
|
|
39
|
+
if [ -f "$SESSION_DIR/$CURRENT_PID" ]; then
|
|
40
|
+
cat "$SESSION_DIR/$CURRENT_PID"
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
# Move to parent
|
|
44
|
+
CURRENT_PID=$(ps -o ppid= -p "$CURRENT_PID" 2>/dev/null | tr -d ' ')
|
|
45
|
+
[ -z "$CURRENT_PID" ] && break
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
echo "ERROR: No session ID found in process tree from PID $PPID. Was init-session.sh invoked?" >&2
|
|
49
|
+
exit 1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# git-commit-guard.sh — PreToolUse:Skill hook
|
|
3
|
+
#
|
|
4
|
+
# Manages skill-scoped flag files so block-push.sh can enforce
|
|
5
|
+
# stage-specific restrictions:
|
|
6
|
+
# /git-commit → .block-push-active (blocks git push)
|
|
7
|
+
# /scope-implement → .implementing-session (blocks git commit/add)
|
|
8
|
+
# Clears flags when any other skill is invoked.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
INPUT=$(cat)
|
|
12
|
+
echo "$INPUT" | jq empty 2>/dev/null || exit 0
|
|
13
|
+
|
|
14
|
+
SKILL=$(echo "$INPUT" | jq -r '.tool_input.skill // empty')
|
|
15
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
|
|
16
|
+
|
|
17
|
+
PUSH_FLAG="$PROJECT_DIR/.claude/.block-push-active"
|
|
18
|
+
IMPL_FLAG="$PROJECT_DIR/.claude/.implementing-session"
|
|
19
|
+
|
|
20
|
+
# /git-commit → block pushes during commit skill
|
|
21
|
+
if [ "$SKILL" = "git-commit" ]; then
|
|
22
|
+
touch "$PUSH_FLAG"
|
|
23
|
+
else
|
|
24
|
+
rm -f "$PUSH_FLAG"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# /scope-implement → block commits during implementing
|
|
28
|
+
if [ "$SKILL" = "scope-implement" ]; then
|
|
29
|
+
touch "$IMPL_FLAG"
|
|
30
|
+
else
|
|
31
|
+
rm -f "$IMPL_FLAG"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
exit 0
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Claude Code SessionStart Hook: Session Initialization
|
|
4
|
+
#
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
if echo "$INPUT" | jq empty 2>/dev/null; then
|
|
9
|
+
SOURCE=$(echo "$INPUT" | jq -r '.source // "startup"')
|
|
10
|
+
else
|
|
11
|
+
SOURCE="startup"
|
|
12
|
+
fi
|
|
13
|
+
[ -z "$SOURCE" ] && SOURCE="startup"
|
|
14
|
+
|
|
15
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
16
|
+
|
|
17
|
+
# ─── Cache session ID for parallel-safe lookup by skills ───
|
|
18
|
+
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
|
|
19
|
+
if [ -n "$SESSION_ID" ]; then
|
|
20
|
+
SESSION_DIR="$PROJECT_DIR/.claude/metrics/.session-ids"
|
|
21
|
+
mkdir -p "$SESSION_DIR"
|
|
22
|
+
printf '%s' "$SESSION_ID" > "$SESSION_DIR/${PPID}-${SESSION_ID}"
|
|
23
|
+
# Clean up stale session files older than 4h with PID liveness check
|
|
24
|
+
find "$SESSION_DIR" -type f -mmin +240 2>/dev/null | while IFS= read -r f; do
|
|
25
|
+
STALE_PID=$(basename "$f" | cut -d'-' -f1)
|
|
26
|
+
if [ -n "$STALE_PID" ] && ! kill -0 "$STALE_PID" 2>/dev/null; then
|
|
27
|
+
rm -f "$f"
|
|
28
|
+
fi
|
|
29
|
+
done
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Clean stale markers from previous sessions
|
|
33
|
+
rm -f "$PROJECT_DIR/.claude/metrics/.scope-create-session"
|
|
34
|
+
rm -f "$PROJECT_DIR/.claude/metrics/.exploration-count"
|
|
35
|
+
rm -f "$PROJECT_DIR/.claude/metrics/.active-scope"
|
|
36
|
+
|
|
37
|
+
# Resolve project name from orbital.config.json or git repo name
|
|
38
|
+
PROJECT_NAME=""
|
|
39
|
+
if command -v jq >/dev/null 2>&1 && [ -f "$PROJECT_DIR/.claude/orbital.config.json" ]; then
|
|
40
|
+
PROJECT_NAME=$(jq -r '.projectName // empty' "$PROJECT_DIR/.claude/orbital.config.json" 2>/dev/null)
|
|
41
|
+
fi
|
|
42
|
+
[ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(basename "$(git -C "$PROJECT_DIR" rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null) || true
|
|
43
|
+
[ -z "$PROJECT_NAME" ] && PROJECT_NAME="Project"
|
|
44
|
+
|
|
45
|
+
# Abbreviated banner for resumed/compacted sessions
|
|
46
|
+
if [ "$SOURCE" = "resume" ] || [ "$SOURCE" = "compact" ]; then
|
|
47
|
+
cat << EOF
|
|
48
|
+
|
|
49
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
50
|
+
${PROJECT_NAME} SESSION RESUMED
|
|
51
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
52
|
+
|
|
53
|
+
Rules: .claude/quick/rules.md | Git: /git-commit | Test: /test-checks
|
|
54
|
+
|
|
55
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
56
|
+
|
|
57
|
+
EOF
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Full banner for new/cleared sessions
|
|
62
|
+
cat << EOF
|
|
63
|
+
|
|
64
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
65
|
+
${PROJECT_NAME} SESSION INITIALIZED
|
|
66
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
67
|
+
|
|
68
|
+
KEY REFERENCES:
|
|
69
|
+
|
|
70
|
+
Entry point: .claude/INDEX.md
|
|
71
|
+
All rules: .claude/quick/rules.md
|
|
72
|
+
Anti-patterns: .claude/anti-patterns/dangerous-shortcuts.md
|
|
73
|
+
|
|
74
|
+
GIT WORKFLOW:
|
|
75
|
+
|
|
76
|
+
/git-commit → Commit work
|
|
77
|
+
/git-main → Push to main (or /git-staging, /git-production for Gitflow)
|
|
78
|
+
|
|
79
|
+
══════════════════════════════════════════════════════════════════════════════
|
|
80
|
+
|
|
81
|
+
EOF
|
|
82
|
+
|
|
83
|
+
# Emit session start event to Orbital dashboard (non-blocking)
|
|
84
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
85
|
+
SESSION_DATA="{\"source\":\"$SOURCE\",\"pid\":$PPID"
|
|
86
|
+
# Include dispatch ID if this session was launched by Orbital dispatch
|
|
87
|
+
if [ -n "$ORBITAL_DISPATCH_ID" ]; then
|
|
88
|
+
SESSION_DATA="${SESSION_DATA},\"dispatch_id\":\"$ORBITAL_DISPATCH_ID\""
|
|
89
|
+
fi
|
|
90
|
+
SESSION_DATA="${SESSION_DATA}}"
|
|
91
|
+
"$SCRIPT_DIR/orbital-emit.sh" SESSION_START "$SESSION_DATA" 2>/dev/null &
|
|
92
|
+
|
|
93
|
+
exit 0
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# orbital-emit.sh — Emit events to Orbital dashboard via file-based bus
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# orbital-emit EVENT_TYPE '{"key": "value"}'
|
|
6
|
+
# orbital-emit EVENT_TYPE '{"key": "value"}' --scope 78 --agent attacker --session abc123
|
|
7
|
+
#
|
|
8
|
+
# Events are written as JSON files to .claude/orbital-events/
|
|
9
|
+
# The Orbital server watches this directory and ingests them.
|
|
10
|
+
# If the server isn't running, events queue up and are processed on startup.
|
|
11
|
+
set -e
|
|
12
|
+
|
|
13
|
+
EVENT_TYPE="${1:?Usage: orbital-emit EVENT_TYPE '{\"key\": \"value\"}' [--scope N] [--agent NAME] [--session ID]}"
|
|
14
|
+
EVENT_DATA="${2:-'{}'}"
|
|
15
|
+
shift 2 2>/dev/null || shift 1
|
|
16
|
+
|
|
17
|
+
# Parse optional named arguments
|
|
18
|
+
SCOPE_ID=""
|
|
19
|
+
AGENT=""
|
|
20
|
+
SESSION_ID=""
|
|
21
|
+
|
|
22
|
+
while [[ $# -gt 0 ]]; do
|
|
23
|
+
case "$1" in
|
|
24
|
+
--scope) SCOPE_ID="$2"; shift 2 ;;
|
|
25
|
+
--agent) AGENT="$2"; shift 2 ;;
|
|
26
|
+
--session) SESSION_ID="$2"; shift 2 ;;
|
|
27
|
+
*) shift ;;
|
|
28
|
+
esac
|
|
29
|
+
done
|
|
30
|
+
|
|
31
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
32
|
+
EVENT_ID=$(uuidgen 2>/dev/null | tr '[:upper:]' '[:lower:]' \
|
|
33
|
+
|| cat /proc/sys/kernel/random/uuid 2>/dev/null \
|
|
34
|
+
|| python3 -c 'import uuid; print(uuid.uuid4())' 2>/dev/null \
|
|
35
|
+
|| echo "$(date +%s)-$$-$RANDOM")
|
|
36
|
+
|
|
37
|
+
# Find project root
|
|
38
|
+
if [ -n "$CLAUDE_PROJECT_DIR" ]; then
|
|
39
|
+
PROJECT_ROOT="$CLAUDE_PROJECT_DIR"
|
|
40
|
+
else
|
|
41
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo ".")
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
EVENTS_DIR="${PROJECT_ROOT}/.claude/orbital-events"
|
|
45
|
+
mkdir -p "$EVENTS_DIR"
|
|
46
|
+
|
|
47
|
+
# Validate inputs
|
|
48
|
+
[[ -n "$SCOPE_ID" && ! "$SCOPE_ID" =~ ^[0-9]+$ ]] && SCOPE_ID=""
|
|
49
|
+
|
|
50
|
+
# Validate EVENT_DATA is valid JSON; fall back to wrapping as string
|
|
51
|
+
if ! echo "$EVENT_DATA" | jq empty 2>/dev/null; then
|
|
52
|
+
EVENT_DATA=$(jq -n --arg d "$EVENT_DATA" '$d')
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Build JSON with optional top-level fields using jq for safe escaping
|
|
56
|
+
EVENT_FILE="${EVENTS_DIR}/${EVENT_ID}.json"
|
|
57
|
+
|
|
58
|
+
JQ_ARGS=(
|
|
59
|
+
--arg id "$EVENT_ID"
|
|
60
|
+
--arg type "$EVENT_TYPE"
|
|
61
|
+
--argjson data "$EVENT_DATA"
|
|
62
|
+
--arg timestamp "$TIMESTAMP"
|
|
63
|
+
)
|
|
64
|
+
JQ_EXPR='{id: $id, type: $type, data: $data, timestamp: $timestamp}'
|
|
65
|
+
|
|
66
|
+
if [ -n "$SCOPE_ID" ]; then
|
|
67
|
+
JQ_ARGS+=(--argjson scope_id "$SCOPE_ID")
|
|
68
|
+
JQ_EXPR='{id: $id, type: $type, scope_id: $scope_id, data: $data, timestamp: $timestamp}'
|
|
69
|
+
fi
|
|
70
|
+
if [ -n "$AGENT" ]; then
|
|
71
|
+
JQ_ARGS+=(--arg agent "$AGENT")
|
|
72
|
+
JQ_EXPR=$(echo "$JQ_EXPR" | sed 's/}$/, agent: $agent}/')
|
|
73
|
+
fi
|
|
74
|
+
if [ -n "$SESSION_ID" ]; then
|
|
75
|
+
JQ_ARGS+=(--arg session_id "$SESSION_ID")
|
|
76
|
+
JQ_EXPR=$(echo "$JQ_EXPR" | sed 's/}$/, session_id: $session_id}/')
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
jq -n "${JQ_ARGS[@]}" "$JQ_EXPR" > "$EVENT_FILE"
|