panopticon-cli 0.4.33 → 0.5.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/README.md +96 -210
- package/dist/{agents-VLK4BMVA.js → agents-E43Y3HNU.js} +5 -5
- package/dist/{chunk-ASY7T35E.js → chunk-AAFQANKW.js} +231 -76
- package/dist/chunk-AAFQANKW.js.map +1 -0
- package/dist/{chunk-KJ2TRXNK.js → chunk-FTCPTHIJ.js} +47 -420
- package/dist/chunk-FTCPTHIJ.js.map +1 -0
- package/dist/{chunk-PI7Y3PSN.js → chunk-GR6ZZMCX.js} +25 -6
- package/dist/chunk-GR6ZZMCX.js.map +1 -0
- package/dist/chunk-HJSM6E6U.js +1038 -0
- package/dist/chunk-HJSM6E6U.js.map +1 -0
- package/dist/{chunk-BKCWRMUX.js → chunk-HZT2AOPN.js} +81 -9
- package/dist/chunk-HZT2AOPN.js.map +1 -0
- package/dist/{chunk-XFR2DLMR.js → chunk-NTO3EDB3.js} +3 -3
- package/dist/{chunk-XFR2DLMR.js.map → chunk-NTO3EDB3.js.map} +1 -1
- package/dist/{chunk-RBUO57TC.js → chunk-PPRFKTVC.js} +2 -2
- package/dist/chunk-PPRFKTVC.js.map +1 -0
- package/dist/{chunk-XKT5MHPT.js → chunk-WQG2TYCB.js} +2 -2
- package/dist/cli/index.js +1383 -880
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/prompts/work-agent.md +2 -0
- package/dist/dashboard/public/assets/{index-UjZq6ykz.css → index-BxpjweAL.css} +1 -1
- package/dist/dashboard/public/assets/index-DQHkwvvJ.js +743 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/server.js +3593 -2052
- package/dist/index.d.ts +10 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/{specialist-context-T3NBMCIE.js → specialist-context-ZC6A4M3I.js} +4 -4
- package/dist/{specialist-logs-CVKD3YJ3.js → specialist-logs-KLGJCEUL.js} +4 -4
- package/dist/{specialists-TKAP6T6Z.js → specialists-O4HWDJL5.js} +4 -4
- package/dist/{traefik-QX4ZV4YG.js → traefik-QN7R5I6V.js} +2 -2
- package/dist/{workspace-manager-KLHUCIZV.js → workspace-manager-IE4JL2JP.js} +2 -2
- package/package.json +1 -1
- package/scripts/stop-hook +7 -0
- package/scripts/work-agent-stop-hook +137 -0
- package/skills/myn-standards/SKILL.md +351 -0
- package/skills/write-spec/SKILL.md +138 -0
- package/dist/chunk-7XNJJBH6.js +0 -538
- package/dist/chunk-7XNJJBH6.js.map +0 -1
- package/dist/chunk-ASY7T35E.js.map +0 -1
- package/dist/chunk-BKCWRMUX.js.map +0 -1
- package/dist/chunk-KJ2TRXNK.js.map +0 -1
- package/dist/chunk-PI7Y3PSN.js.map +0 -1
- package/dist/chunk-RBUO57TC.js.map +0 -1
- package/dist/dashboard/public/assets/index-kAJqtLDO.js +0 -708
- /package/dist/{agents-VLK4BMVA.js.map → agents-E43Y3HNU.js.map} +0 -0
- /package/dist/{chunk-XKT5MHPT.js.map → chunk-WQG2TYCB.js.map} +0 -0
- /package/dist/{specialist-context-T3NBMCIE.js.map → specialist-context-ZC6A4M3I.js.map} +0 -0
- /package/dist/{specialist-logs-CVKD3YJ3.js.map → specialist-logs-KLGJCEUL.js.map} +0 -0
- /package/dist/{specialists-TKAP6T6Z.js.map → specialists-O4HWDJL5.js.map} +0 -0
- /package/dist/{traefik-QX4ZV4YG.js.map → traefik-QN7R5I6V.js.map} +0 -0
- /package/dist/{workspace-manager-KLHUCIZV.js.map → workspace-manager-IE4JL2JP.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -829,5 +829,14 @@ declare function getProviderEnv(provider: ProviderConfig, apiKey: string): Recor
|
|
|
829
829
|
* Must be called before spawning the agent.
|
|
830
830
|
*/
|
|
831
831
|
declare function setupCredentialFileAuth(provider: ProviderConfig, workspacePath: string): void;
|
|
832
|
+
/**
|
|
833
|
+
* Clear credential-file auth from workspace settings.
|
|
834
|
+
*
|
|
835
|
+
* When switching from a credential-file provider (e.g. Kimi) to a static/plan-based
|
|
836
|
+
* provider (e.g. Anthropic), the apiKeyHelper must be removed from
|
|
837
|
+
* .claude/settings.local.json. Otherwise Claude Code will keep using the stale
|
|
838
|
+
* token helper and fail with "Invalid API key".
|
|
839
|
+
*/
|
|
840
|
+
declare function clearCredentialFileAuth(workspacePath: string): void;
|
|
832
841
|
|
|
833
|
-
export { AGENTS_DIR, ARCHIVES_DIR, type AnthropicModel, type ApiKeysConfig, BACKUPS_DIR, BIN_DIR, type BackupInfo, CACHE_AGENTS_DIR, CACHE_MANIFEST, CACHE_RULES_DIR, CACHE_SKILLS_DIR, CERTS_DIR, CLAUDE_DIR, CLAUDE_MD_TEMPLATES, COMMANDS_DIR, CONFIG_DIR, CONFIG_FILE, COSTS_DIR, type Comment, type ComplexityLevel, type ComplexityModels, DOCS_DIR, type DevrootSyncItem, type GitHubConfig, GitHubTracker, type GitLabConfig, GitLabTracker, type GoogleModel, HEARTBEATS_DIR, type HookItem, INIT_DIRS, type Issue, type IssueFilters, IssueNotFoundError, type IssueState, type IssueTracker, type IssueUpdate, type KimiModel, LEGACY_RUNTIME_DIRS, type LinearConfig, LinearTracker, type LinkDirection, LinkManager, type MigrationResult, type ModelId, type ModelsConfig, type NewIssue, NotImplementedError, type OpenAIModel, PANOPTICON_HOME, PRDS_DIR, PRD_DRAFTS_DIR, PRD_PUBLISHED_DIR, PROJECT_DOCS_SUBDIR, PROJECT_PRDS_ACTIVE_SUBDIR, PROJECT_PRDS_COMPLETED_SUBDIR, PROJECT_PRDS_PLANNED_SUBDIR, PROJECT_PRDS_SUBDIR, PROVIDERS, type PanopticonConfig, type ProviderAuthType, type ProviderCompatibility, type ProviderConfig, type ProviderName, type RallyConfig, type RefreshCacheResult, type RemoteConfig, type RemoteExeConfig, SETTINGS_FILE, SKILLS_DIR, SOURCE_AGENTS_DIR, SOURCE_DEV_SKILLS_DIR, SOURCE_RULES_DIR, SOURCE_SCRIPTS_DIR, SOURCE_SKILLS_DIR, SOURCE_TEMPLATES_DIR, SOURCE_TRAEFIK_TEMPLATES, SYNC_TARGET, type SettingsConfig, type ShadowConfig, type Shell, type SpecialistModels, type SyncItem, type SyncOptions, type SyncPlan, type SyncResult, TEMPLATES_DIR, TRAEFIK_CERTS_DIR, TRAEFIK_DIR, TRAEFIK_DYNAMIC_DIR, TrackerAuthError, type TrackerConfig, type TrackerConfigItem, type TrackerLink, type TrackerType, type TrackersConfig, type ZAIModel, addAlias, cleanOldBackups, createBackup, createBackupTimestamp, createTracker, createTrackerFromConfig, detectShell, executeSync, findDevrootForProject, formatIssueRef, getAgentCommand, getAliasInstructions, getAllTrackers, getAvailableModels, getClaudeModelFlag, getDashboardApiUrl, getDefaultConfig, getDefaultSettings, getDevrootPath, getDirectProviders, getLinkManager, getPanopticonHome, getPrimaryTracker, getProviderEnv, getProviderForModel, getRouterProviders, getSecondaryTracker, getShellRcFile, hasAlias, isAnthropicModel, isDevMode, isPanopticonSymlink, listBackups, loadConfig, loadSettings, migrateFromPersonalSymlinks, needsRouter, parseIssueRef, planHooksSync, planSync, refreshCache, requiresRouter, restoreBackup, saveConfig, saveSettings, setupCredentialFileAuth, syncHooks, syncStatusline, validateSettings };
|
|
842
|
+
export { AGENTS_DIR, ARCHIVES_DIR, type AnthropicModel, type ApiKeysConfig, BACKUPS_DIR, BIN_DIR, type BackupInfo, CACHE_AGENTS_DIR, CACHE_MANIFEST, CACHE_RULES_DIR, CACHE_SKILLS_DIR, CERTS_DIR, CLAUDE_DIR, CLAUDE_MD_TEMPLATES, COMMANDS_DIR, CONFIG_DIR, CONFIG_FILE, COSTS_DIR, type Comment, type ComplexityLevel, type ComplexityModels, DOCS_DIR, type DevrootSyncItem, type GitHubConfig, GitHubTracker, type GitLabConfig, GitLabTracker, type GoogleModel, HEARTBEATS_DIR, type HookItem, INIT_DIRS, type Issue, type IssueFilters, IssueNotFoundError, type IssueState, type IssueTracker, type IssueUpdate, type KimiModel, LEGACY_RUNTIME_DIRS, type LinearConfig, LinearTracker, type LinkDirection, LinkManager, type MigrationResult, type ModelId, type ModelsConfig, type NewIssue, NotImplementedError, type OpenAIModel, PANOPTICON_HOME, PRDS_DIR, PRD_DRAFTS_DIR, PRD_PUBLISHED_DIR, PROJECT_DOCS_SUBDIR, PROJECT_PRDS_ACTIVE_SUBDIR, PROJECT_PRDS_COMPLETED_SUBDIR, PROJECT_PRDS_PLANNED_SUBDIR, PROJECT_PRDS_SUBDIR, PROVIDERS, type PanopticonConfig, type ProviderAuthType, type ProviderCompatibility, type ProviderConfig, type ProviderName, type RallyConfig, type RefreshCacheResult, type RemoteConfig, type RemoteExeConfig, SETTINGS_FILE, SKILLS_DIR, SOURCE_AGENTS_DIR, SOURCE_DEV_SKILLS_DIR, SOURCE_RULES_DIR, SOURCE_SCRIPTS_DIR, SOURCE_SKILLS_DIR, SOURCE_TEMPLATES_DIR, SOURCE_TRAEFIK_TEMPLATES, SYNC_TARGET, type SettingsConfig, type ShadowConfig, type Shell, type SpecialistModels, type SyncItem, type SyncOptions, type SyncPlan, type SyncResult, TEMPLATES_DIR, TRAEFIK_CERTS_DIR, TRAEFIK_DIR, TRAEFIK_DYNAMIC_DIR, TrackerAuthError, type TrackerConfig, type TrackerConfigItem, type TrackerLink, type TrackerType, type TrackersConfig, type ZAIModel, addAlias, cleanOldBackups, clearCredentialFileAuth, createBackup, createBackupTimestamp, createTracker, createTrackerFromConfig, detectShell, executeSync, findDevrootForProject, formatIssueRef, getAgentCommand, getAliasInstructions, getAllTrackers, getAvailableModels, getClaudeModelFlag, getDashboardApiUrl, getDefaultConfig, getDefaultSettings, getDevrootPath, getDirectProviders, getLinkManager, getPanopticonHome, getPrimaryTracker, getProviderEnv, getProviderForModel, getRouterProviders, getSecondaryTracker, getShellRcFile, hasAlias, isAnthropicModel, isDevMode, isPanopticonSymlink, listBackups, loadConfig, loadSettings, migrateFromPersonalSymlinks, needsRouter, parseIssueRef, planHooksSync, planSync, refreshCache, requiresRouter, restoreBackup, saveConfig, saveSettings, setupCredentialFileAuth, syncHooks, syncStatusline, validateSettings };
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
restoreBackup,
|
|
22
22
|
syncHooks,
|
|
23
23
|
syncStatusline
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-WQG2TYCB.js";
|
|
25
25
|
import "./chunk-AQXETQHW.js";
|
|
26
26
|
import {
|
|
27
27
|
GitHubTracker,
|
|
@@ -32,9 +32,10 @@ import {
|
|
|
32
32
|
getAllTrackers,
|
|
33
33
|
getPrimaryTracker,
|
|
34
34
|
getSecondaryTracker
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-NTO3EDB3.js";
|
|
36
36
|
import {
|
|
37
37
|
PROVIDERS,
|
|
38
|
+
clearCredentialFileAuth,
|
|
38
39
|
getAgentCommand,
|
|
39
40
|
getAvailableModels,
|
|
40
41
|
getClaudeModelFlag,
|
|
@@ -52,7 +53,7 @@ import {
|
|
|
52
53
|
saveSettings,
|
|
53
54
|
setupCredentialFileAuth,
|
|
54
55
|
validateSettings
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-HJSM6E6U.js";
|
|
56
57
|
import {
|
|
57
58
|
findDevrootForProject,
|
|
58
59
|
getDashboardApiUrl,
|
|
@@ -177,6 +178,7 @@ export {
|
|
|
177
178
|
TrackerAuthError,
|
|
178
179
|
addAlias,
|
|
179
180
|
cleanOldBackups,
|
|
181
|
+
clearCredentialFileAuth,
|
|
180
182
|
createBackup,
|
|
181
183
|
createBackupTimestamp,
|
|
182
184
|
createTracker,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Panopticon CLI - Main exports for library usage\nexport * from './lib/paths.js';\nexport * from './lib/config.js';\nexport * from './lib/shell.js';\nexport * from './lib/backup.js';\nexport * from './lib/sync.js';\nexport * from './lib/tracker/index.js';\nexport * from './lib/providers.js';\nexport * from './lib/settings.js';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Panopticon CLI - Main exports for library usage\nexport * from './lib/paths.js';\nexport * from './lib/config.js';\nexport * from './lib/shell.js';\nexport * from './lib/backup.js';\nexport * from './lib/sync.js';\nexport * from './lib/tracker/index.js';\nexport * from './lib/providers.js';\nexport * from './lib/settings.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AAKA;AACA;","names":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getRecentRunLogs,
|
|
3
3
|
init_specialist_logs
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AAFQANKW.js";
|
|
5
5
|
import {
|
|
6
6
|
getModelId,
|
|
7
7
|
init_work_type_router
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FTCPTHIJ.js";
|
|
9
9
|
import "./chunk-JQBV3Q2W.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-HJSM6E6U.js";
|
|
11
11
|
import {
|
|
12
12
|
getProject,
|
|
13
13
|
init_projects
|
|
@@ -254,4 +254,4 @@ export {
|
|
|
254
254
|
regenerateContextDigest,
|
|
255
255
|
scheduleDigestGeneration
|
|
256
256
|
};
|
|
257
|
-
//# sourceMappingURL=specialist-context-
|
|
257
|
+
//# sourceMappingURL=specialist-context-ZC6A4M3I.js.map
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
isRunLogActive,
|
|
17
17
|
listRunLogs,
|
|
18
18
|
parseLogMetadata
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-AAFQANKW.js";
|
|
20
|
+
import "./chunk-FTCPTHIJ.js";
|
|
21
21
|
import "./chunk-JQBV3Q2W.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-HJSM6E6U.js";
|
|
23
23
|
import "./chunk-OMNXYPXC.js";
|
|
24
24
|
import "./chunk-ZTFNYOC7.js";
|
|
25
25
|
import "./chunk-ZHC57RCV.js";
|
|
@@ -42,4 +42,4 @@ export {
|
|
|
42
42
|
listRunLogs,
|
|
43
43
|
parseLogMetadata
|
|
44
44
|
};
|
|
45
|
-
//# sourceMappingURL=specialist-logs-
|
|
45
|
+
//# sourceMappingURL=specialist-logs-KLGJCEUL.js.map
|
|
@@ -55,10 +55,10 @@ import {
|
|
|
55
55
|
wakeSpecialist,
|
|
56
56
|
wakeSpecialistOrQueue,
|
|
57
57
|
wakeSpecialistWithTask
|
|
58
|
-
} from "./chunk-
|
|
59
|
-
import "./chunk-
|
|
58
|
+
} from "./chunk-AAFQANKW.js";
|
|
59
|
+
import "./chunk-FTCPTHIJ.js";
|
|
60
60
|
import "./chunk-JQBV3Q2W.js";
|
|
61
|
-
import "./chunk-
|
|
61
|
+
import "./chunk-HJSM6E6U.js";
|
|
62
62
|
import "./chunk-OMNXYPXC.js";
|
|
63
63
|
import "./chunk-ZTFNYOC7.js";
|
|
64
64
|
import "./chunk-ZHC57RCV.js";
|
|
@@ -120,4 +120,4 @@ export {
|
|
|
120
120
|
wakeSpecialistOrQueue,
|
|
121
121
|
wakeSpecialistWithTask
|
|
122
122
|
};
|
|
123
|
-
//# sourceMappingURL=specialists-
|
|
123
|
+
//# sourceMappingURL=specialists-O4HWDJL5.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ensureProjectCerts,
|
|
5
5
|
generatePanopticonTraefikConfig,
|
|
6
6
|
generateTlsConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-PPRFKTVC.js";
|
|
8
8
|
import "./chunk-FQ66DECN.js";
|
|
9
9
|
import "./chunk-OMNXYPXC.js";
|
|
10
10
|
import "./chunk-ZTFNYOC7.js";
|
|
@@ -16,4 +16,4 @@ export {
|
|
|
16
16
|
generatePanopticonTraefikConfig,
|
|
17
17
|
generateTlsConfig
|
|
18
18
|
};
|
|
19
|
-
//# sourceMappingURL=traefik-
|
|
19
|
+
//# sourceMappingURL=traefik-QN7R5I6V.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
preTrustDirectory,
|
|
5
5
|
removeWorkspace,
|
|
6
6
|
stopWorkspaceDocker
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GR6ZZMCX.js";
|
|
8
8
|
import "./chunk-7SN4L4PH.js";
|
|
9
9
|
import "./chunk-AQXETQHW.js";
|
|
10
10
|
import "./chunk-ZTFNYOC7.js";
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
removeWorkspace,
|
|
20
20
|
stopWorkspaceDocker
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=workspace-manager-
|
|
22
|
+
//# sourceMappingURL=workspace-manager-IE4JL2JP.js.map
|
package/package.json
CHANGED
package/scripts/stop-hook
CHANGED
|
@@ -57,5 +57,12 @@ if [ -x "$SPECIALIST_HOOK" ]; then
|
|
|
57
57
|
"$SPECIALIST_HOOK" &
|
|
58
58
|
fi
|
|
59
59
|
|
|
60
|
+
# Chain to work-agent completion detection hook
|
|
61
|
+
# Detects when a work agent forgot to call "pan work done" and nudges it
|
|
62
|
+
WORK_AGENT_HOOK="$HOME/.panopticon/bin/work-agent-stop-hook"
|
|
63
|
+
if [ -x "$WORK_AGENT_HOOK" ]; then
|
|
64
|
+
"$WORK_AGENT_HOOK" &
|
|
65
|
+
fi
|
|
66
|
+
|
|
60
67
|
# Always exit successfully
|
|
61
68
|
exit 0
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ~/.panopticon/bin/work-agent-stop-hook
|
|
3
|
+
# Called when any agent goes idle — detects work agents that forgot "pan work done"
|
|
4
|
+
#
|
|
5
|
+
# Uses a lightweight AI model to analyze the last N lines of terminal output
|
|
6
|
+
# and determine if the agent completed its work but failed to signal completion.
|
|
7
|
+
# If so, sends a nudge message to the agent via tmux.
|
|
8
|
+
#
|
|
9
|
+
# The model used is configurable via PANOPTICON_COMPLETION_CHECK_MODEL env var
|
|
10
|
+
# or defaults to the models.overrides.completion-check-hook setting in config.yaml,
|
|
11
|
+
# falling back to claude-haiku-4-5.
|
|
12
|
+
|
|
13
|
+
# Don't use set -e - resilient to failures, never break Claude Code execution
|
|
14
|
+
|
|
15
|
+
# Get agent ID
|
|
16
|
+
if [ -n "$PANOPTICON_AGENT_ID" ]; then
|
|
17
|
+
AGENT_ID="$PANOPTICON_AGENT_ID"
|
|
18
|
+
elif [ -n "$TMUX" ]; then
|
|
19
|
+
AGENT_ID=$(tmux display-message -p '#S' 2>/dev/null)
|
|
20
|
+
else
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Only run for work agents (agent-min-XXX, agent-pan-XXX, etc.)
|
|
25
|
+
case "$AGENT_ID" in
|
|
26
|
+
agent-*)
|
|
27
|
+
# Check it's not a specialist
|
|
28
|
+
case "$AGENT_ID" in
|
|
29
|
+
specialist-*) exit 0 ;;
|
|
30
|
+
esac
|
|
31
|
+
;;
|
|
32
|
+
*)
|
|
33
|
+
exit 0 # Not a work agent
|
|
34
|
+
;;
|
|
35
|
+
esac
|
|
36
|
+
|
|
37
|
+
# Extract issue ID from agent ID (e.g., "agent-min-725" -> "MIN-725")
|
|
38
|
+
ISSUE_ID=$(echo "$AGENT_ID" | sed 's/^agent-//' | tr '[:lower:]' '[:upper:]')
|
|
39
|
+
|
|
40
|
+
# Skip if completion marker already exists (agent already called pan work done)
|
|
41
|
+
COMPLETED_FILE="$HOME/.panopticon/agents/$AGENT_ID/completed"
|
|
42
|
+
if [ -f "$COMPLETED_FILE" ]; then
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Cooldown: don't nudge more than once per 10 minutes
|
|
47
|
+
NUDGE_FILE="$HOME/.panopticon/agents/$AGENT_ID/.last-completion-nudge"
|
|
48
|
+
if [ -f "$NUDGE_FILE" ]; then
|
|
49
|
+
LAST_NUDGE=$(cat "$NUDGE_FILE" 2>/dev/null || echo "0")
|
|
50
|
+
NOW=$(date +%s)
|
|
51
|
+
ELAPSED=$(( NOW - LAST_NUDGE ))
|
|
52
|
+
if [ "$ELAPSED" -lt 600 ]; then
|
|
53
|
+
exit 0 # Too soon since last nudge
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Capture the last 80 lines of terminal output
|
|
58
|
+
OUTPUT=$(tmux capture-pane -t "$AGENT_ID" -p -S -80 2>/dev/null || echo "")
|
|
59
|
+
if [ -z "$OUTPUT" ]; then
|
|
60
|
+
exit 0
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Quick heuristic pre-check: skip the expensive AI call if the output clearly
|
|
64
|
+
# shows the agent is mid-work (e.g., running tests, editing files, reading)
|
|
65
|
+
if echo "$OUTPUT" | grep -qE '(Reading|Editing|Searching|Running|Compiling|Building|Installing|●.*Bash|●.*Read|●.*Edit|●.*Grep|●.*Write|●.*Glob)' | tail -5 | grep -qE '●'; then
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Check if the agent appears to be at an idle prompt (not mid-response)
|
|
70
|
+
if ! echo "$OUTPUT" | tail -10 | grep -qE '(^❯|Worked for)'; then
|
|
71
|
+
exit 0 # Agent doesn't appear to be at an idle prompt
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Determine model to use for completion check
|
|
75
|
+
# Priority: env var > config.yaml override > default
|
|
76
|
+
COMPLETION_MODEL="${PANOPTICON_COMPLETION_CHECK_MODEL:-}"
|
|
77
|
+
if [ -z "$COMPLETION_MODEL" ]; then
|
|
78
|
+
CONFIG_FILE="$HOME/.panopticon/config.yaml"
|
|
79
|
+
if [ -f "$CONFIG_FILE" ] && command -v grep &> /dev/null; then
|
|
80
|
+
COMPLETION_MODEL=$(grep 'completion-check-hook:' "$CONFIG_FILE" 2>/dev/null | awk '{print $2}' | tr -d '"' || echo "")
|
|
81
|
+
fi
|
|
82
|
+
fi
|
|
83
|
+
COMPLETION_MODEL="${COMPLETION_MODEL:-claude-haiku-4-5}"
|
|
84
|
+
|
|
85
|
+
# Build the analysis prompt
|
|
86
|
+
ANALYSIS_PROMPT="You are analyzing a work agent's terminal output to determine if it finished its work but forgot to call 'pan work done'.
|
|
87
|
+
|
|
88
|
+
The agent was working on issue $ISSUE_ID. Here is the last 80 lines of its terminal output:
|
|
89
|
+
|
|
90
|
+
<terminal_output>
|
|
91
|
+
$OUTPUT
|
|
92
|
+
</terminal_output>
|
|
93
|
+
|
|
94
|
+
Respond with EXACTLY one of these words (nothing else):
|
|
95
|
+
- FORGOT_COMPLETION — if the agent clearly finished its implementation work (closed beads, committed code, ran tests) but stopped without calling 'pan work done'
|
|
96
|
+
- STILL_WORKING — if the agent appears to have more work to do (mentioned next steps, was mid-task)
|
|
97
|
+
- STOPPED_FOR_INPUT — if the agent stopped because it needs human input or hit a blocker
|
|
98
|
+
- UNCLEAR — if you cannot determine the state"
|
|
99
|
+
|
|
100
|
+
# Run the analysis using claude CLI (headless, no interactive session)
|
|
101
|
+
RESULT=$(echo "$ANALYSIS_PROMPT" | claude -p --model "$COMPLETION_MODEL" --max-tokens 20 2>/dev/null || echo "UNCLEAR")
|
|
102
|
+
|
|
103
|
+
# Extract just the verdict (first word of output, strip whitespace)
|
|
104
|
+
VERDICT=$(echo "$RESULT" | tr -d '[:space:]' | head -c 30)
|
|
105
|
+
|
|
106
|
+
# Log the check
|
|
107
|
+
LOG_DIR="$HOME/.panopticon/logs"
|
|
108
|
+
mkdir -p "$LOG_DIR"
|
|
109
|
+
echo "[$(date -Iseconds)] work-agent-stop-hook: $AGENT_ID ($ISSUE_ID) -> $VERDICT (model: $COMPLETION_MODEL)" \
|
|
110
|
+
>> "$LOG_DIR/hooks.log" 2>/dev/null || true
|
|
111
|
+
|
|
112
|
+
if [ "$VERDICT" = "FORGOT_COMPLETION" ]; then
|
|
113
|
+
# Record nudge timestamp for cooldown
|
|
114
|
+
mkdir -p "$(dirname "$NUDGE_FILE")"
|
|
115
|
+
date +%s > "$NUDGE_FILE" 2>/dev/null || true
|
|
116
|
+
|
|
117
|
+
# Write the nudge message to a temp file and use load-buffer + paste-buffer
|
|
118
|
+
# (the reliable tmux message delivery pattern from CLAUDE.md)
|
|
119
|
+
NUDGE_MSG="You stopped without calling pan work done. If your implementation is complete, you MUST run this command now:
|
|
120
|
+
|
|
121
|
+
pan work done $ISSUE_ID -c \"Implementation complete\"
|
|
122
|
+
|
|
123
|
+
If you still have remaining tasks, continue working on them. Do NOT stop until all work is done AND you have called pan work done."
|
|
124
|
+
|
|
125
|
+
TMPFILE=$(mktemp)
|
|
126
|
+
echo "$NUDGE_MSG" > "$TMPFILE"
|
|
127
|
+
tmux load-buffer "$TMPFILE" 2>/dev/null
|
|
128
|
+
tmux paste-buffer -t "$AGENT_ID" 2>/dev/null
|
|
129
|
+
sleep 0.3
|
|
130
|
+
tmux send-keys -t "$AGENT_ID" C-m 2>/dev/null
|
|
131
|
+
rm -f "$TMPFILE"
|
|
132
|
+
|
|
133
|
+
echo "[$(date -Iseconds)] work-agent-stop-hook: Sent completion nudge to $AGENT_ID" \
|
|
134
|
+
>> "$LOG_DIR/hooks.log" 2>/dev/null || true
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
exit 0
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: myn-standards
|
|
3
|
+
description: >
|
|
4
|
+
Mind Your Now coding standards, design system, and component patterns.
|
|
5
|
+
Auto-applied when writing or reviewing MYN code.
|
|
6
|
+
triggers:
|
|
7
|
+
- myn component
|
|
8
|
+
- mind your now
|
|
9
|
+
- myn styling
|
|
10
|
+
- myn design
|
|
11
|
+
- myn frontend
|
|
12
|
+
- myn ui
|
|
13
|
+
- notification toast
|
|
14
|
+
- task card
|
|
15
|
+
- briefing
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Mind Your Now Design System & Coding Standards
|
|
19
|
+
|
|
20
|
+
## Brand Identity
|
|
21
|
+
|
|
22
|
+
### Brand Colors
|
|
23
|
+
|
|
24
|
+
| Name | Hex | Tailwind Token | Usage |
|
|
25
|
+
|------|-----|----------------|-------|
|
|
26
|
+
| All-Knowing Blu | `#00AEEF` | `brand-blue` | Primary brand, links, CTAs |
|
|
27
|
+
| Yours Truly Blu | `#80D7F7` | `brand-blue-light` | Hover states, light accents |
|
|
28
|
+
| Golden Hour Yellow | `#FFC60B` | `brand-yellow` | Accent, highlights, "now" in wordmark |
|
|
29
|
+
| Midnight Blue | `#0C4064` | `brand-dark` | Headings on light backgrounds |
|
|
30
|
+
|
|
31
|
+
### Brand Wordmark
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<h1>
|
|
35
|
+
<span className="text-blue-800">mind</span>
|
|
36
|
+
<span className="font-thin text-blue-200">your</span>
|
|
37
|
+
<span className="text-yellow-500">now</span>
|
|
38
|
+
</h1>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Logo
|
|
42
|
+
|
|
43
|
+
- Asset: `/images/logo-no-text.png` (sun-burst motif)
|
|
44
|
+
- Always paired with the wordmark on splash/auth screens
|
|
45
|
+
|
|
46
|
+
## Color System
|
|
47
|
+
|
|
48
|
+
### Semantic Colors
|
|
49
|
+
|
|
50
|
+
| Token | Light | Dark | Usage |
|
|
51
|
+
|-------|-------|------|-------|
|
|
52
|
+
| `semantic-success` | `#22C55E` | `#4ADE80` | Completed, positive |
|
|
53
|
+
| `semantic-warning` | `#F59E0B` | `#FBBF24` | Attention needed |
|
|
54
|
+
| `semantic-error` | `#EF4444` | `#F87171` | Errors, overdue |
|
|
55
|
+
| `semantic-info` | `#3B82F6` | `#60A5FA` | Informational |
|
|
56
|
+
|
|
57
|
+
### Priority Colors
|
|
58
|
+
|
|
59
|
+
| Priority | Hex | Token |
|
|
60
|
+
|----------|-----|-------|
|
|
61
|
+
| Critical | `#EF4444` | `priority-critical` |
|
|
62
|
+
| High | `#F97316` | `priority-high` |
|
|
63
|
+
| Medium | `#EAB308` | `priority-medium` |
|
|
64
|
+
| Low | `#22C55E` | `priority-low` |
|
|
65
|
+
| None | `#6B7280` | `priority-none` |
|
|
66
|
+
|
|
67
|
+
### MYN Task Type Colors (Methodology)
|
|
68
|
+
|
|
69
|
+
| Type | Hex | Token |
|
|
70
|
+
|------|-----|-------|
|
|
71
|
+
| Parking Lot | `#F04F23` | `taskType-parkinglot` |
|
|
72
|
+
| Over the Horizon | `#F9913B` | `taskType-overthehorizon` |
|
|
73
|
+
| Critical Now | `#0C803D` | `taskType-critical` |
|
|
74
|
+
| Opportunity Now | `#107CC4` | `taskType-opportunitynow` |
|
|
75
|
+
| Tomorrow | `#854EB1` | `taskType-tomorrow` |
|
|
76
|
+
|
|
77
|
+
### Shadcn/UI Semantic Tokens (CSS Variables)
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
--background Page background (white / slate-950)
|
|
81
|
+
--foreground Primary text (slate-950 / slate-50)
|
|
82
|
+
--card Card backgrounds (white / slate-900)
|
|
83
|
+
--muted Muted backgrounds (slate-100 / slate-800)
|
|
84
|
+
--muted-foreground Secondary text (slate-500 / slate-400)
|
|
85
|
+
--border Borders (slate-200 / slate-700)
|
|
86
|
+
--primary Primary actions (blue-600 / blue-500)
|
|
87
|
+
--destructive Destructive actions (red-600 / red-500)
|
|
88
|
+
--ring Focus rings (blue-500 / blue-400)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### App Background
|
|
92
|
+
|
|
93
|
+
- Light: `#eff6ff` (blue-50)
|
|
94
|
+
- Dark: `#0f172a` (slate-900)
|
|
95
|
+
- Surfaces: `#1e293b` dark, `#334155` elevated dark
|
|
96
|
+
|
|
97
|
+
## Typography
|
|
98
|
+
|
|
99
|
+
### Font Stack
|
|
100
|
+
|
|
101
|
+
- **Primary**: Inter (all UI text)
|
|
102
|
+
- **Monospace**: SF Mono, Monaco, Cascadia Code
|
|
103
|
+
- **Accessibility**: Tiresias Infofont, OpenDyslexic3 (user-selectable)
|
|
104
|
+
- All legacy font aliases (Roboto, Lato, Montserrat, SF Pro) map to Inter
|
|
105
|
+
|
|
106
|
+
### Type Scale
|
|
107
|
+
|
|
108
|
+
| Token | Size | Weight | Letter Spacing | Usage |
|
|
109
|
+
|-------|------|--------|----------------|-------|
|
|
110
|
+
| `display` | 2.441rem (39px) | 700 | -0.02em | Hero headlines |
|
|
111
|
+
| `h1` | 1.953rem (31px) | 700 | -0.01em | Page titles |
|
|
112
|
+
| `h2` | 1.563rem (25px) | 600 | -0.01em | Section headers |
|
|
113
|
+
| `h3` | 1.25rem (20px) | 600 | -- | Card headers |
|
|
114
|
+
| `body-lg` | 1.125rem (18px) | 400 | -- | Large body text |
|
|
115
|
+
| `body` | 1rem (16px) | 400 | -- | Default body text |
|
|
116
|
+
| `body-sm` | 0.875rem (14px) | 400 | -- | Compact text, task titles |
|
|
117
|
+
| `caption` | 0.75rem (12px) | 400 | -- | Labels, hints |
|
|
118
|
+
| `overline` | 0.625rem (10px) | 600 | 0.1em | Category labels |
|
|
119
|
+
|
|
120
|
+
### Text Colors
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
text-foreground Primary text
|
|
124
|
+
text-muted-foreground Secondary text, labels, icons
|
|
125
|
+
text-primary Links, emphasis
|
|
126
|
+
text-destructive Errors
|
|
127
|
+
text-card-foreground Text on cards
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Spacing & Layout
|
|
131
|
+
|
|
132
|
+
### Spacing Scale
|
|
133
|
+
|
|
134
|
+
Standard Tailwind 4px base: `1`=4px, `2`=8px, `3`=12px, `4`=16px, `6`=24px, `8`=32px
|
|
135
|
+
|
|
136
|
+
### Common Patterns
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
// Page container
|
|
140
|
+
<div className="max-w-[1320px] mx-auto pt-4 px-3 sm:px-4 lg:px-6">
|
|
141
|
+
|
|
142
|
+
// Two-column grid (sidebar visible at xl)
|
|
143
|
+
<div className="grid gap-7 xl:grid-cols-[minmax(0,820px)_420px]">
|
|
144
|
+
|
|
145
|
+
// Card padding
|
|
146
|
+
p-3 // Compact
|
|
147
|
+
p-4 // Standard
|
|
148
|
+
p-5 // Spacious
|
|
149
|
+
|
|
150
|
+
// Section gaps
|
|
151
|
+
mt-3 // Between compact sections
|
|
152
|
+
mt-4 // Between standard sections
|
|
153
|
+
gap-2 // Icon + text
|
|
154
|
+
gap-3 // Form elements
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Breakpoints
|
|
158
|
+
|
|
159
|
+
| Token | Width | Usage |
|
|
160
|
+
|-------|-------|-------|
|
|
161
|
+
| `xxs` | 350px | Small phones |
|
|
162
|
+
| `sm` | 640px | Small tablets |
|
|
163
|
+
| `md` | 768px | Tablets |
|
|
164
|
+
| `lg` | 1024px | Small desktops |
|
|
165
|
+
| `xl` | 1280px | Desktop (sidebar visible) |
|
|
166
|
+
|
|
167
|
+
## Border & Shadow
|
|
168
|
+
|
|
169
|
+
### Border Radius
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
rounded-md (6px) Buttons, inputs, small cards
|
|
173
|
+
rounded-lg (8px) Cards, panels
|
|
174
|
+
rounded-xl (12px) Large cards, modals
|
|
175
|
+
rounded-full Pills, avatars
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Shadows
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
shadow-sm Sidebar cards, secondary
|
|
182
|
+
shadow-md Main cards, primary content
|
|
183
|
+
shadow-lg Dropdowns, modals
|
|
184
|
+
shadow-xl Popovers, overlays
|
|
185
|
+
shadow-2xl Dialogs
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Opacity Modifiers
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
bg-muted/40 // Very subtle containers
|
|
192
|
+
border-border/50 // Container borders (default)
|
|
193
|
+
border-border/60 // Button/input borders
|
|
194
|
+
ring-ring/40 // Focus state ring
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Component Patterns
|
|
198
|
+
|
|
199
|
+
### Buttons
|
|
200
|
+
|
|
201
|
+
| Size | Height | Padding | Icon | Usage |
|
|
202
|
+
|------|--------|---------|------|-------|
|
|
203
|
+
| xs | `h-7` | `px-2` | `h-3.5 w-3.5` | Inline actions |
|
|
204
|
+
| sm | `h-8` | `px-3` | `h-4 w-4` | Secondary actions |
|
|
205
|
+
| md | `h-9` | `px-3` | `h-4 w-4` | Icon buttons |
|
|
206
|
+
| lg | `h-10` | `px-4` | `h-5 w-5` | Primary actions |
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
// Primary
|
|
210
|
+
"h-10 px-4 rounded-md bg-primary text-primary-foreground hover:opacity-90"
|
|
211
|
+
|
|
212
|
+
// Secondary
|
|
213
|
+
"h-10 px-4 rounded-md border border-border/60 bg-card hover:bg-muted"
|
|
214
|
+
|
|
215
|
+
// Ghost
|
|
216
|
+
"h-9 px-3 rounded-md hover:bg-muted"
|
|
217
|
+
|
|
218
|
+
// Icon
|
|
219
|
+
"h-9 w-9 rounded-md hover:bg-muted text-muted-foreground"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Cards
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
// Main card (primary, higher elevation)
|
|
226
|
+
<Card className="bg-card text-card-foreground rounded-lg shadow-md">
|
|
227
|
+
|
|
228
|
+
// Sidebar card (secondary, lower)
|
|
229
|
+
<Card className="bg-card text-card-foreground rounded-lg shadow-sm">
|
|
230
|
+
|
|
231
|
+
// Subtle container
|
|
232
|
+
<div className="rounded-md border border-border/50 bg-muted/40 px-3 py-2">
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Frosted Glass (Auth/Splash Screens)
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
// Blue gradient background
|
|
239
|
+
style={{ background: 'linear-gradient(to bottom, rgb(56, 189, 248), rgb(37, 99, 235))' }}
|
|
240
|
+
|
|
241
|
+
// Frosted glass card
|
|
242
|
+
<Card className="bg-white/90 backdrop-blur-sm border-blue-200 hover:shadow-lg transition-all duration-300">
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Toast Notifications
|
|
246
|
+
|
|
247
|
+
Current implementation uses Radix UI `@radix-ui/react-toast` with CVA variants:
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
// Variants: default, destructive, success, error, warning, info
|
|
251
|
+
// Base style:
|
|
252
|
+
"rounded-lg border-2 p-5 pr-7 shadow-xl backdrop-blur-sm"
|
|
253
|
+
|
|
254
|
+
// Each variant has light/dark mode colors:
|
|
255
|
+
// success: border-green-300 bg-green-50/95 text-green-900
|
|
256
|
+
// error: border-red-300 bg-red-50/95 text-red-900
|
|
257
|
+
// warning: border-amber-300 bg-amber-50/95 text-amber-900
|
|
258
|
+
// info: border-blue-300 bg-blue-50/95 text-blue-900
|
|
259
|
+
|
|
260
|
+
// Viewport: bottom-right on desktop, top on mobile
|
|
261
|
+
// Max width: 420px
|
|
262
|
+
// Animations: slide-in-from-top (mobile), slide-in-from-bottom (desktop)
|
|
263
|
+
// Hover: shadow-2xl + translate-y-0.5 lift
|
|
264
|
+
// Icons: Lucide (CheckCircle2, AlertCircle, AlertTriangle, Info) in rounded-full bg
|
|
265
|
+
// Close: absolute top-right, visible on hover
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Form Controls
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
// Input
|
|
272
|
+
"h-10 rounded-md border border-border/60 bg-card px-3 text-sm focus:ring-2 focus:ring-ring/40"
|
|
273
|
+
|
|
274
|
+
// Textarea
|
|
275
|
+
"rounded-md border border-border/60 bg-card p-3 text-sm min-h-[80px] focus:ring-2 focus:ring-ring/40"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Animation System
|
|
279
|
+
|
|
280
|
+
### Tailwind Keyframes
|
|
281
|
+
|
|
282
|
+
| Name | Duration | Usage |
|
|
283
|
+
|------|----------|-------|
|
|
284
|
+
| `wiggle` | 1s infinite | Playful attention |
|
|
285
|
+
| `fade-in` | 0.5s ease-out | Element entrance (translateY 10px) |
|
|
286
|
+
| `spin-slow` | 3s linear infinite | Loading states |
|
|
287
|
+
| `pulse-subtle` | 2s infinite | Gentle pulse (opacity 1→0.9) |
|
|
288
|
+
| `shimmer` | 2s linear infinite | Loading skeleton |
|
|
289
|
+
| `bounce-once` | 1s ease | Single bounce |
|
|
290
|
+
|
|
291
|
+
### Framer Motion (Auth/Splash)
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
// Container: stagger children by 0.1s
|
|
295
|
+
const containerVariants = {
|
|
296
|
+
hidden: { opacity: 0 },
|
|
297
|
+
visible: { opacity: 1, transition: { staggerChildren: 0.1 } },
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Items: spring up from 20px below
|
|
301
|
+
const itemVariants = {
|
|
302
|
+
hidden: { y: 20, opacity: 0 },
|
|
303
|
+
visible: { y: 0, opacity: 1, transition: { type: 'spring', stiffness: 50 } },
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Task Completion
|
|
308
|
+
|
|
309
|
+
- Wavy green SVG strikethrough line + text fade
|
|
310
|
+
- 2s animation duration
|
|
311
|
+
- Do NOT modify sort logic in `sortTasksAndEvents.js`
|
|
312
|
+
|
|
313
|
+
## Design Principles
|
|
314
|
+
|
|
315
|
+
1. **Neutral Over Saturated** -- Use muted backgrounds, subtle borders. No saturated gradients for secondary elements.
|
|
316
|
+
2. **Elevation Hierarchy** -- Primary content gets `shadow-md`, secondary gets `shadow-sm`.
|
|
317
|
+
3. **Progressive Disclosure** -- Hide secondary actions until hover/focus.
|
|
318
|
+
4. **Density Over Chrome** -- Tight padding, compact buttons, reduce visual noise.
|
|
319
|
+
|
|
320
|
+
## Tech Stack
|
|
321
|
+
|
|
322
|
+
- **Framework**: React 19, Vite 7, TypeScript
|
|
323
|
+
- **State**: Jotai (client) + TanStack Query (server)
|
|
324
|
+
- **UI**: shadcn/ui (new-york style) + Material-UI (legacy, migrating away)
|
|
325
|
+
- **Styling**: Tailwind CSS with custom design tokens
|
|
326
|
+
- **Icons**: Lucide (primary), FontAwesome (legacy, GettingStarted only)
|
|
327
|
+
- **Animation**: Framer Motion (auth flows), Tailwind keyframes (in-app)
|
|
328
|
+
- **Mobile**: Capacitor for iOS/Android
|
|
329
|
+
- **Dark Mode**: `class` strategy via Tailwind `darkMode: 'class'`
|
|
330
|
+
|
|
331
|
+
## File Structure
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
src/
|
|
335
|
+
styles/
|
|
336
|
+
design-tokens.css CSS custom properties (brand, semantic, priority, task type)
|
|
337
|
+
notification-animations.css Toast animation keyframes
|
|
338
|
+
globals.css shadcn/ui CSS variables
|
|
339
|
+
components/
|
|
340
|
+
ui/ shadcn/ui base components (toast, card, button, etc.)
|
|
341
|
+
auth/ Auth flows (GettingStarted, EmailForm)
|
|
342
|
+
notifications/ NotificationItem, notification panels
|
|
343
|
+
lib/
|
|
344
|
+
utils.ts cn() helper (clsx + tailwind-merge)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Key Files
|
|
348
|
+
|
|
349
|
+
- `tailwind.config.js` -- All design tokens, type scale, colors, animations
|
|
350
|
+
- `src/styles/design-tokens.css` -- CSS custom properties with dark mode overrides
|
|
351
|
+
- `docs/technical/frontend/UI-DESIGN-SYSTEM.md` -- Full design system documentation
|