@ginkoai/cli 2.5.1 → 2.5.2
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/dist/commands/handoff.d.ts +1 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +55 -9
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/health.js +1 -0
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +42 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pull/pull-command.d.ts.map +1 -1
- package/dist/commands/pull/pull-command.js +10 -0
- package/dist/commands/pull/pull-command.js.map +1 -1
- package/dist/commands/push/push-command.d.ts.map +1 -1
- package/dist/commands/push/push-command.js +10 -0
- package/dist/commands/push/push-command.js.map +1 -1
- package/dist/commands/sprint/index.d.ts.map +1 -1
- package/dist/commands/sprint/index.js +15 -0
- package/dist/commands/sprint/index.js.map +1 -1
- package/dist/commands/sprint/plan-check.d.ts +16 -0
- package/dist/commands/sprint/plan-check.d.ts.map +1 -0
- package/dist/commands/sprint/plan-check.js +122 -0
- package/dist/commands/sprint/plan-check.js.map +1 -0
- package/dist/commands/sprint/status.d.ts +1 -1
- package/dist/commands/sprint/status.d.ts.map +1 -1
- package/dist/commands/sprint/status.js +23 -1
- package/dist/commands/sprint/status.js.map +1 -1
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +28 -11
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/task/status.d.ts.map +1 -1
- package/dist/commands/task/status.js +228 -0
- package/dist/commands/task/status.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/health-checker.d.ts.map +1 -1
- package/dist/lib/health-checker.js +75 -0
- package/dist/lib/health-checker.js.map +1 -1
- package/dist/lib/integration-warnings.d.ts +72 -0
- package/dist/lib/integration-warnings.d.ts.map +1 -0
- package/dist/lib/integration-warnings.js +273 -0
- package/dist/lib/integration-warnings.js.map +1 -0
- package/dist/lib/output-formatter.d.ts +1 -1
- package/dist/lib/output-formatter.d.ts.map +1 -1
- package/dist/lib/output-formatter.js +31 -1
- package/dist/lib/output-formatter.js.map +1 -1
- package/dist/lib/protected-manifest.d.ts +34 -0
- package/dist/lib/protected-manifest.d.ts.map +1 -0
- package/dist/lib/protected-manifest.js +112 -0
- package/dist/lib/protected-manifest.js.map +1 -0
- package/dist/lib/protection-hook.d.ts +35 -0
- package/dist/lib/protection-hook.d.ts.map +1 -0
- package/dist/lib/protection-hook.js +154 -0
- package/dist/lib/protection-hook.js.map +1 -0
- package/dist/lib/realtime-cursor.js +3 -3
- package/dist/lib/realtime-cursor.js.map +1 -1
- package/dist/lib/session-health.d.ts +75 -0
- package/dist/lib/session-health.d.ts.map +1 -0
- package/dist/lib/session-health.js +252 -0
- package/dist/lib/session-health.js.map +1 -0
- package/dist/lib/sprint-state.d.ts +82 -0
- package/dist/lib/sprint-state.d.ts.map +1 -0
- package/dist/lib/sprint-state.js +338 -0
- package/dist/lib/sprint-state.js.map +1 -0
- package/dist/lib/structural-safeguards.d.ts +26 -0
- package/dist/lib/structural-safeguards.d.ts.map +1 -0
- package/dist/lib/structural-safeguards.js +91 -0
- package/dist/lib/structural-safeguards.js.map +1 -0
- package/dist/lib/task-parser.d.ts +2 -0
- package/dist/lib/task-parser.d.ts.map +1 -1
- package/dist/lib/task-parser.js +30 -0
- package/dist/lib/task-parser.js.map +1 -1
- package/dist/templates/ai-instructions-template.d.ts.map +1 -1
- package/dist/templates/ai-instructions-template.js +8 -1
- package/dist/templates/ai-instructions-template.js.map +1 -1
- package/dist/templates/sprint-template.md +52 -0
- package/package.json +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-03-09
|
|
5
|
+
* @tags: [protection, manifest, state-files, safety]
|
|
6
|
+
* @related: [protection-hook.ts, health-checker.ts, ../commands/init.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Protected Manifest Module
|
|
12
|
+
*
|
|
13
|
+
* Manages the .ginko/PROTECTED manifest — a tracked file listing local-only
|
|
14
|
+
* state files that must never be deleted. AI assistants see this file when
|
|
15
|
+
* doing cleanup tasks and know to leave these files alone.
|
|
16
|
+
*
|
|
17
|
+
* Background: Commit 1bc0c7a accidentally deleted graph/config.json,
|
|
18
|
+
* sync-state.json, and user-progress.json when an AI assistant widened
|
|
19
|
+
* gitignore patterns and ran `git rm`. These files are gitignored (local state)
|
|
20
|
+
* but have no remote backup.
|
|
21
|
+
*/
|
|
22
|
+
import fs from 'fs-extra';
|
|
23
|
+
import path from 'path';
|
|
24
|
+
// ── Default Protected Files ──────────────────────────────────────
|
|
25
|
+
const DEFAULT_PROTECTED_FILES = [
|
|
26
|
+
{
|
|
27
|
+
path: 'graph/config.json',
|
|
28
|
+
reason: 'Graph connection ID and document hashes. No remote backup.',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
path: 'sync-state.json',
|
|
32
|
+
reason: 'Push/pull timestamps and sync hashes. No remote backup.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
path: 'user-progress.json',
|
|
36
|
+
reason: 'CLI usage tracking and preferences. No remote backup.',
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
// ── Public API ───────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Returns the canonical list of files that should be protected.
|
|
42
|
+
*/
|
|
43
|
+
export function getDefaultProtectedFiles() {
|
|
44
|
+
return [...DEFAULT_PROTECTED_FILES];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Generate the PROTECTED manifest content.
|
|
48
|
+
*/
|
|
49
|
+
export function generateManifest(entries = DEFAULT_PROTECTED_FILES) {
|
|
50
|
+
const header = `# GINKO PROTECTED FILES
|
|
51
|
+
#
|
|
52
|
+
# These files are local-only state with NO remote backup.
|
|
53
|
+
# Deleting them causes silent failures and permanent data loss.
|
|
54
|
+
#
|
|
55
|
+
# AI assistants: NEVER delete, move, or git-rm these files.
|
|
56
|
+
# Developers: Run \`ginko init --upgrade\` to reinstall the
|
|
57
|
+
# pre-commit hook if it's missing.
|
|
58
|
+
#
|
|
59
|
+
# Format: relative-path-from-.ginko/ | reason
|
|
60
|
+
`;
|
|
61
|
+
const lines = entries.map((e) => `${e.path} | ${e.reason}`);
|
|
62
|
+
return header + '\n' + lines.join('\n') + '\n';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse a PROTECTED manifest into entries.
|
|
66
|
+
*/
|
|
67
|
+
export function parseManifest(content) {
|
|
68
|
+
const entries = [];
|
|
69
|
+
for (const line of content.split('\n')) {
|
|
70
|
+
const trimmed = line.trim();
|
|
71
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
72
|
+
continue;
|
|
73
|
+
const pipeIndex = trimmed.indexOf('|');
|
|
74
|
+
if (pipeIndex === -1) {
|
|
75
|
+
// Line without a reason — treat the whole line as a path
|
|
76
|
+
entries.push({ path: trimmed, reason: '' });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
entries.push({
|
|
80
|
+
path: trimmed.slice(0, pipeIndex).trim(),
|
|
81
|
+
reason: trimmed.slice(pipeIndex + 1).trim(),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return entries;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate that all protected files exist on disk.
|
|
89
|
+
* Returns lists of present and missing files.
|
|
90
|
+
*/
|
|
91
|
+
export async function validateManifest(ginkoDir) {
|
|
92
|
+
const manifestPath = path.join(ginkoDir, 'PROTECTED');
|
|
93
|
+
const present = [];
|
|
94
|
+
const missing = [];
|
|
95
|
+
if (!(await fs.pathExists(manifestPath))) {
|
|
96
|
+
// No manifest — treat all defaults as missing
|
|
97
|
+
return { present: [], missing: [...DEFAULT_PROTECTED_FILES] };
|
|
98
|
+
}
|
|
99
|
+
const content = await fs.readFile(manifestPath, 'utf8');
|
|
100
|
+
const entries = parseManifest(content);
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
const fullPath = path.join(ginkoDir, entry.path);
|
|
103
|
+
if (await fs.pathExists(fullPath)) {
|
|
104
|
+
present.push(entry);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
missing.push(entry);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { present, missing };
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=protected-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protected-manifest.js","sourceRoot":"","sources":["../../src/lib/protected-manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-03-09
|
|
5
|
+
* @tags: [protection, git-hook, pre-commit, safety]
|
|
6
|
+
* @related: [protected-manifest.ts, health-checker.ts, ../commands/init.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Generate the protection-only pre-commit hook script (Unix bash).
|
|
12
|
+
* Git for Windows uses MSYS2 bash, so this works cross-platform.
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateProtectionCheck(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Generate a standalone pre-commit hook (with shebang).
|
|
17
|
+
*/
|
|
18
|
+
export declare function generatePreCommitHook(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Install the pre-commit protection hook into the project's .git/hooks/.
|
|
21
|
+
*
|
|
22
|
+
* - If no hook exists: creates it directly.
|
|
23
|
+
* - If hook exists with our marker: skips (idempotent).
|
|
24
|
+
* - If hook exists without our marker: renames to pre-commit.user,
|
|
25
|
+
* creates wrapper that calls both.
|
|
26
|
+
*/
|
|
27
|
+
export declare function installPreCommitHook(projectRoot: string): Promise<{
|
|
28
|
+
installed: boolean;
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Check whether the protection hook is installed.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isHookInstalled(projectRoot: string): Promise<boolean>;
|
|
35
|
+
//# sourceMappingURL=protection-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protection-hook.d.ts","sourceRoot":"","sources":["../../src/lib/protection-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA4ChD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;AA4BD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IACvE,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAiCD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-03-09
|
|
5
|
+
* @tags: [protection, git-hook, pre-commit, safety]
|
|
6
|
+
* @related: [protected-manifest.ts, health-checker.ts, ../commands/init.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Protection Hook Module
|
|
12
|
+
*
|
|
13
|
+
* Generates and installs a git pre-commit hook that blocks commits
|
|
14
|
+
* deleting files listed in .ginko/PROTECTED. The hook is pure bash
|
|
15
|
+
* with no dependencies — it reads the manifest directly.
|
|
16
|
+
*
|
|
17
|
+
* Composition strategy: if a pre-commit hook already exists, the
|
|
18
|
+
* existing hook is renamed to pre-commit.user and a wrapper hook
|
|
19
|
+
* calls it first, then runs the protection check.
|
|
20
|
+
*/
|
|
21
|
+
import fs from 'fs-extra';
|
|
22
|
+
import path from 'path';
|
|
23
|
+
// ── Constants ────────────────────────────────────────────────────
|
|
24
|
+
const HOOK_MARKER = '# GINKO-PROTECTION-HOOK';
|
|
25
|
+
// ── Hook Generation ──────────────────────────────────────────────
|
|
26
|
+
/**
|
|
27
|
+
* Generate the protection-only pre-commit hook script (Unix bash).
|
|
28
|
+
* Git for Windows uses MSYS2 bash, so this works cross-platform.
|
|
29
|
+
*/
|
|
30
|
+
export function generateProtectionCheck() {
|
|
31
|
+
return `${HOOK_MARKER}
|
|
32
|
+
# Blocks commits that delete protected ginko state files.
|
|
33
|
+
# These files are local-only with no remote backup.
|
|
34
|
+
# Installed by: ginko init
|
|
35
|
+
|
|
36
|
+
PROTECTED_FILE=".ginko/PROTECTED"
|
|
37
|
+
|
|
38
|
+
if [ ! -f "$PROTECTED_FILE" ]; then
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
DELETED_FILES=$(git diff --cached --diff-filter=D --name-only 2>/dev/null)
|
|
43
|
+
if [ -z "$DELETED_FILES" ]; then
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
BLOCKED=0
|
|
48
|
+
while IFS='|' read -r filepath reason || [ -n "$filepath" ]; do
|
|
49
|
+
filepath=$(echo "$filepath" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
50
|
+
|
|
51
|
+
# Skip comments and blank lines
|
|
52
|
+
case "$filepath" in
|
|
53
|
+
'#'*|'') continue ;;
|
|
54
|
+
esac
|
|
55
|
+
|
|
56
|
+
full_path=".ginko/$filepath"
|
|
57
|
+
if echo "$DELETED_FILES" | grep -qF "$full_path"; then
|
|
58
|
+
echo "BLOCKED: Cannot delete protected file: $full_path"
|
|
59
|
+
reason=$(echo "$reason" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
60
|
+
[ -n "$reason" ] && echo " Reason: $reason"
|
|
61
|
+
BLOCKED=1
|
|
62
|
+
fi
|
|
63
|
+
done < "$PROTECTED_FILE"
|
|
64
|
+
|
|
65
|
+
if [ $BLOCKED -eq 1 ]; then
|
|
66
|
+
echo ""
|
|
67
|
+
echo "These files are local-only state with no remote backup."
|
|
68
|
+
echo "Deleting them causes permanent data loss."
|
|
69
|
+
echo "See .ginko/PROTECTED for details."
|
|
70
|
+
echo ""
|
|
71
|
+
echo "If you really need to remove these files, use: git commit --no-verify"
|
|
72
|
+
exit 1
|
|
73
|
+
fi`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate a standalone pre-commit hook (with shebang).
|
|
77
|
+
*/
|
|
78
|
+
export function generatePreCommitHook() {
|
|
79
|
+
return `#!/bin/bash
|
|
80
|
+
${generateProtectionCheck()}
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generate a wrapper hook that calls an existing hook first,
|
|
85
|
+
* then runs the protection check.
|
|
86
|
+
*/
|
|
87
|
+
function generateWrapperHook() {
|
|
88
|
+
return `#!/bin/bash
|
|
89
|
+
# Ginko wrapper pre-commit hook.
|
|
90
|
+
# Runs the original pre-commit hook first, then the protection check.
|
|
91
|
+
|
|
92
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
93
|
+
|
|
94
|
+
# Run the original pre-commit hook if it exists
|
|
95
|
+
if [ -x "$HOOK_DIR/pre-commit.user" ]; then
|
|
96
|
+
"$HOOK_DIR/pre-commit.user"
|
|
97
|
+
RESULT=$?
|
|
98
|
+
if [ $RESULT -ne 0 ]; then
|
|
99
|
+
exit $RESULT
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
${generateProtectionCheck()}
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
// ── Installation ─────────────────────────────────────────────────
|
|
107
|
+
/**
|
|
108
|
+
* Install the pre-commit protection hook into the project's .git/hooks/.
|
|
109
|
+
*
|
|
110
|
+
* - If no hook exists: creates it directly.
|
|
111
|
+
* - If hook exists with our marker: skips (idempotent).
|
|
112
|
+
* - If hook exists without our marker: renames to pre-commit.user,
|
|
113
|
+
* creates wrapper that calls both.
|
|
114
|
+
*/
|
|
115
|
+
export async function installPreCommitHook(projectRoot) {
|
|
116
|
+
const gitDir = path.join(projectRoot, '.git');
|
|
117
|
+
if (!(await fs.pathExists(gitDir))) {
|
|
118
|
+
return { installed: false, message: 'Not a git repository' };
|
|
119
|
+
}
|
|
120
|
+
const hooksDir = path.join(gitDir, 'hooks');
|
|
121
|
+
await fs.ensureDir(hooksDir);
|
|
122
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
123
|
+
const userHookPath = path.join(hooksDir, 'pre-commit.user');
|
|
124
|
+
// Check if hook already exists
|
|
125
|
+
if (await fs.pathExists(hookPath)) {
|
|
126
|
+
const existing = await fs.readFile(hookPath, 'utf8');
|
|
127
|
+
// Already installed — skip
|
|
128
|
+
if (existing.includes(HOOK_MARKER)) {
|
|
129
|
+
return { installed: true, message: 'Protection hook already installed' };
|
|
130
|
+
}
|
|
131
|
+
// Existing hook from another tool — compose
|
|
132
|
+
await fs.rename(hookPath, userHookPath);
|
|
133
|
+
await fs.writeFile(hookPath, generateWrapperHook(), { mode: 0o755 });
|
|
134
|
+
return {
|
|
135
|
+
installed: true,
|
|
136
|
+
message: 'Protection hook installed (existing hook preserved as pre-commit.user)',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// No existing hook — create directly
|
|
140
|
+
await fs.writeFile(hookPath, generatePreCommitHook(), { mode: 0o755 });
|
|
141
|
+
return { installed: true, message: 'Protection hook installed' };
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check whether the protection hook is installed.
|
|
145
|
+
*/
|
|
146
|
+
export async function isHookInstalled(projectRoot) {
|
|
147
|
+
const hookPath = path.join(projectRoot, '.git', 'hooks', 'pre-commit');
|
|
148
|
+
if (!(await fs.pathExists(hookPath))) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const content = await fs.readFile(hookPath, 'utf8');
|
|
152
|
+
return content.includes(HOOK_MARKER);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=protection-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protection-hook.js","sourceRoot":"","sources":["../../src/lib/protection-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,oEAAoE;AAEpE,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAE9C,oEAAoE;AAEpE;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CpB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO;EACP,uBAAuB,EAAE;CAC1B,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB;IAC1B,OAAO;;;;;;;;;;;;;;;EAeP,uBAAuB,EAAE;CAC1B,CAAC;AACF,CAAC;AAED,oEAAoE;AAEpE;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAI5D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAE5D,+BAA+B;IAC/B,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAErD,2BAA2B;QAC3B,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC;QAC3E,CAAC;QAED,4CAA4C;QAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACxC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,mBAAmB,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACrE,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,wEAAwE;SAClF,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,qBAAqB,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IACvE,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -50,9 +50,9 @@ export function getRealtimeCursorConfig() {
|
|
|
50
50
|
debounceMs: 100,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
const enabled = process.env.GINKO_REALTIME_CURSOR
|
|
53
|
+
// Disabled by default — no dashboard consumers yet.
|
|
54
|
+
// Enable with GINKO_REALTIME_CURSOR=true when team cursor features ship.
|
|
55
|
+
const enabled = process.env.GINKO_REALTIME_CURSOR === 'true';
|
|
56
56
|
return {
|
|
57
57
|
enabled,
|
|
58
58
|
apiUrl: process.env.GINKO_API_URL || 'https://app.ginkoai.com',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-cursor.js","sourceRoot":"","sources":["../../src/lib/realtime-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAsCzC;;GAEG;AACH,IAAI,eAAoC,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,eAAe,GAAG,OAAO,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,kDAAkD;IAClD,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,yBAAyB;YAC9D,UAAU,EAAE,GAAG;SAChB,CAAC;IACJ,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"realtime-cursor.js","sourceRoot":"","sources":["../../src/lib/realtime-cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-03-15
|
|
5
|
+
* @tags: [session-health, context-pressure, degradation, epic-025]
|
|
6
|
+
* @related: [context-metrics.ts, output-formatter.ts, health-checker.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: [fs-extra]
|
|
10
|
+
*/
|
|
11
|
+
export type HealthTier = 'fresh' | 'steady' | 'verify-deploys' | 'handoff-recommended';
|
|
12
|
+
export interface HealthTierInfo {
|
|
13
|
+
tier: HealthTier;
|
|
14
|
+
icon: string;
|
|
15
|
+
label: string;
|
|
16
|
+
messageCount: number;
|
|
17
|
+
durationMinutes: number;
|
|
18
|
+
}
|
|
19
|
+
export interface HealthThresholds {
|
|
20
|
+
/** Messages threshold for steady tier */
|
|
21
|
+
steadyMessages: number;
|
|
22
|
+
/** Messages threshold for verify-deploys tier */
|
|
23
|
+
verifyMessages: number;
|
|
24
|
+
/** Messages threshold for handoff-recommended tier */
|
|
25
|
+
handoffMessages: number;
|
|
26
|
+
/** Duration (minutes) threshold for steady tier */
|
|
27
|
+
steadyDurationMin: number;
|
|
28
|
+
/** Duration (minutes) threshold for verify-deploys tier */
|
|
29
|
+
verifyDurationMin: number;
|
|
30
|
+
/** Duration (minutes) threshold for handoff-recommended tier */
|
|
31
|
+
handoffDurationMin: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Default thresholds calibrated against EPIC-023/024 session data.
|
|
35
|
+
*
|
|
36
|
+
* EPIC-024 (262K token session):
|
|
37
|
+
* - Deployment failures began at ~35 messages
|
|
38
|
+
* - Serial bug fixing pattern at ~45 messages
|
|
39
|
+
* - Subagent collision at ~50 messages
|
|
40
|
+
*
|
|
41
|
+
* EPIC-023 (multi-session analysis):
|
|
42
|
+
* - Context score degradation at ~30 messages
|
|
43
|
+
* - CLI interop bugs surfaced at ~40 messages
|
|
44
|
+
* - E2E walkthrough late verification at ~45 messages
|
|
45
|
+
*/
|
|
46
|
+
export declare const DEFAULT_THRESHOLDS: HealthThresholds;
|
|
47
|
+
/**
|
|
48
|
+
* Calculate health tier from message count and session duration.
|
|
49
|
+
*
|
|
50
|
+
* Uses the higher of message-based or duration-based tier
|
|
51
|
+
* (whichever indicates more pressure).
|
|
52
|
+
*/
|
|
53
|
+
export declare function calculateHealthTier(messageCount: number, durationMinutes: number, thresholds?: HealthThresholds): HealthTierInfo;
|
|
54
|
+
/**
|
|
55
|
+
* Count messages in the current session from events JSONL.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getSessionMessageCount(projectRoot?: string): Promise<number>;
|
|
58
|
+
/**
|
|
59
|
+
* Get session duration in minutes from session start timestamp.
|
|
60
|
+
*/
|
|
61
|
+
export declare function getSessionDurationMinutes(projectRoot?: string): Promise<number>;
|
|
62
|
+
/**
|
|
63
|
+
* Load custom thresholds from .ginko/config.json if configured.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadThresholds(projectRoot?: string): Promise<HealthThresholds>;
|
|
66
|
+
/**
|
|
67
|
+
* Get current session health tier (all-in-one).
|
|
68
|
+
*/
|
|
69
|
+
export declare function getCurrentHealthTier(projectRoot?: string): Promise<HealthTierInfo>;
|
|
70
|
+
/**
|
|
71
|
+
* Format health tier for status line display.
|
|
72
|
+
* Compact format: "12 msgs | ✅ fresh"
|
|
73
|
+
*/
|
|
74
|
+
export declare function formatHealthForStatusLine(info: HealthTierInfo): string;
|
|
75
|
+
//# sourceMappingURL=session-health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-health.d.ts","sourceRoot":"","sources":["../../src/lib/session-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2BH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,gBAAgB,GAAG,qBAAqB,CAAC;AAEvF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAOhC,CAAC;AAMF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,UAAU,GAAE,gBAAqC,GAChD,cAAc,CAkChB;AAwBD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoClF;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCrF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAepF;AAMD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAQxF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAEtE"}
|