aiwcli 0.12.7 → 0.13.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/dist/commands/clean.d.ts +7 -0
- package/dist/commands/clean.js +17 -8
- package/dist/commands/clear.d.ts +85 -0
- package/dist/commands/clear.js +455 -347
- package/dist/commands/init/index.d.ts +15 -0
- package/dist/commands/init/index.js +79 -38
- package/dist/lib/gitignore-manager.js +12 -13
- package/dist/lib/settings-hierarchy.d.ts +13 -1
- package/dist/lib/settings-hierarchy.js +1 -1
- package/dist/lib/template-linter.d.ts +4 -0
- package/dist/lib/template-linter.js +1 -1
- package/dist/lib/tty-detection.d.ts +1 -0
- package/dist/lib/tty-detection.js +1 -0
- package/dist/templates/CLAUDE.md +27 -0
- package/dist/templates/_shared/.claude/settings.json +7 -7
- package/dist/templates/_shared/.claude/{commands/handoff.md → skills/handoff/SKILL.md} +4 -3
- package/dist/templates/_shared/.claude/{commands/handoff-resume.md → skills/handoff-resume/SKILL.md} +3 -2
- package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +43 -0
- package/dist/templates/_shared/.codex/workflows/handoff.md +1 -1
- package/dist/templates/_shared/.codex/workflows/meta-plan.md +347 -0
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +1 -1
- package/dist/templates/_shared/.windsurf/workflows/meta-plan.md +347 -0
- package/dist/templates/_shared/hooks-ts/lint_after_edit.ts +59 -0
- package/dist/templates/_shared/hooks-ts/session_end.ts +11 -10
- package/dist/templates/_shared/hooks-ts/session_start.ts +15 -12
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +12 -12
- package/dist/templates/_shared/lib-ts/CLAUDE.md +3 -3
- package/dist/templates/_shared/lib-ts/base/constants.ts +324 -306
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +26 -7
- package/dist/templates/_shared/lib-ts/base/inference.ts +19 -19
- package/dist/templates/_shared/lib-ts/base/lint-dispatch.ts +287 -0
- package/dist/templates/_shared/lib-ts/base/state-io.ts +4 -3
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +3 -3
- package/dist/templates/_shared/lib-ts/context/CLAUDE.md +134 -0
- package/dist/templates/_shared/lib-ts/context/context-formatter.ts +16 -15
- package/dist/templates/_shared/lib-ts/context/context-selector.ts +16 -16
- package/dist/templates/_shared/lib-ts/context/context-store.ts +15 -14
- package/dist/templates/_shared/lib-ts/context/plan-manager.ts +2 -2
- package/dist/templates/_shared/scripts/resolve-run.ts +61 -0
- package/dist/templates/_shared/scripts/resolve_context.ts +1 -1
- package/dist/templates/_shared/scripts/status_line.ts +100 -94
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/CLAUDE.md +433 -421
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/lib/document-generator.ts +5 -4
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/lib/handoff-reader.ts +2 -1
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/scripts/resume_handoff.ts +6 -6
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/scripts/save_handoff.ts +16 -17
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/workflows/handoff-resume.md +2 -2
- package/dist/templates/_shared/{handoff-system → skills/handoff-system}/workflows/handoff.md +3 -3
- package/dist/templates/_shared/skills/meta-plan/CLAUDE.md +44 -0
- package/dist/templates/_shared/skills/meta-plan/workflows/meta-plan.md +347 -0
- package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +1 -1
- package/dist/templates/cc-native/.claude/settings.json +86 -57
- package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +64 -0
- package/dist/templates/cc-native/_cc-native/{lib-ts/artifacts → artifacts/lib}/format.ts +599 -597
- package/dist/templates/cc-native/_cc-native/{lib-ts/artifacts → artifacts/lib}/index.ts +26 -26
- package/dist/templates/cc-native/_cc-native/{lib-ts/artifacts → artifacts/lib}/tracker.ts +107 -106
- package/dist/templates/cc-native/_cc-native/{lib-ts/artifacts → artifacts/lib}/write.ts +119 -118
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +237 -247
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +76 -74
- package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +76 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +163 -156
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +15 -16
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +116 -116
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +3 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +16 -12
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +2 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +7 -6
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +9 -7
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +17 -14
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +41 -37
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +43 -33
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +9 -8
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +4 -3
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +9 -10
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +20 -19
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +329 -329
- package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +149 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/CLAUDE.md +143 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/PLAN-ORCHESTRATOR.md +213 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-questions/PLAN-QUESTIONER.md +70 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-EVOLUTION.md +62 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-PATTERNS.md +61 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-STRUCTURE.md +62 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ASSUMPTION-TRACER.md +56 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CLARITY-AUDITOR.md +53 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-FEASIBILITY.md +66 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-GAPS.md +70 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-ORDERING.md +62 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CONSTRAINT-VALIDATOR.md +72 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-ADR-VALIDATOR.md +61 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-SCALE-MATCHER.md +64 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DEVILS-ADVOCATE.md +56 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DOCUMENTATION-PHILOSOPHY.md +86 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HANDOFF-READINESS.md +59 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HIDDEN-COMPLEXITY.md +58 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/INCREMENTAL-DELIVERY.md +66 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-DEPENDENCY.md +62 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-FMEA.md +66 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-PREMORTEM.md +71 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-REVERSIBILITY.md +74 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SCOPE-BOUNDARY.md +77 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SIMPLICITY-GUARDIAN.md +62 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SKEPTIC.md +68 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md +61 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-CHARACTERIZATION.md +71 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-FIRST-VALIDATOR.md +61 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md +61 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-COSTS.md +67 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-STAKEHOLDERS.md +65 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-COVERAGE.md +74 -0
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-STRENGTH.md +69 -0
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/agent-selection.ts +162 -163
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/corroboration.ts +119 -119
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/graduation.ts +132 -132
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/orchestrator.ts +70 -70
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/output-builder.ts +121 -130
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/plan-questions.ts +101 -102
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/review-pipeline.ts +507 -511
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/agent.ts +73 -74
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/base/base-agent.ts +217 -217
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/index.ts +12 -12
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/providers/claude-agent.ts +66 -66
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/providers/codex-agent.ts +185 -185
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/providers/gemini-agent.ts +39 -39
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/providers/orchestrator-claude-agent.ts +196 -196
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/schemas.ts +201 -201
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/reviewers/types.ts +23 -23
- package/dist/templates/cc-native/_cc-native/{lib-ts → plan-review/lib}/verdict.ts +72 -72
- package/dist/templates/cc-native/_cc-native/{workflows → plan-review/workflows}/specdev.md +9 -9
- package/oclif.manifest.json +1 -1
- package/package.json +6 -5
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +0 -21
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
import * as path from "node:path";
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
import { getContextDir } from "../base/constants.js";
|
|
14
|
+
import { parseIsoTimestamp } from "../base/utils.js";
|
|
14
15
|
import type { ContextState, Task } from "../types.js";
|
|
15
16
|
|
|
16
17
|
const MAX_PLAN_INLINE_CHARS = 30_000;
|
|
@@ -44,7 +45,7 @@ export function getModeDisplay(mode: string): string {
|
|
|
44
45
|
export function formatRelativeTime(isoTimestamp: string | null): string {
|
|
45
46
|
if (!isoTimestamp) return "unknown";
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
const dt = parseIsoTimestamp(isoTimestamp);
|
|
48
49
|
if (!dt) return isoTimestamp.slice(0, 16);
|
|
49
50
|
|
|
50
51
|
const now = new Date();
|
|
@@ -100,7 +101,7 @@ function readPlanContent(planPath: string): [string | null, boolean, number] {
|
|
|
100
101
|
|
|
101
102
|
function modeLabel(ctx: ContextState): string {
|
|
102
103
|
const d = getModeDisplay(ctx.mode ?? "idle");
|
|
103
|
-
return d ? d.
|
|
104
|
+
return d ? d.replaceAll(/^\[|\]$/g, "") : "Active";
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
/**
|
|
@@ -119,7 +120,7 @@ export function buildRestoreSections(
|
|
|
119
120
|
const savedAt = lastSession.saved_at ?? "";
|
|
120
121
|
if (savedAt) {
|
|
121
122
|
const reason = lastSession.save_reason ?? "";
|
|
122
|
-
const reasonDisplay = reason ? reason.
|
|
123
|
+
const reasonDisplay = reason ? reason.replaceAll('_', " ") : "unknown";
|
|
123
124
|
sections.push(`**Last session ended:** ${formatRelativeTime(savedAt)} (${reasonDisplay})`);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
@@ -222,8 +223,8 @@ export function formatHandoffContinuation(ctx: ContextState, projectRoot?: strin
|
|
|
222
223
|
} else {
|
|
223
224
|
lines.push(`*Handoff document not found at \`${handoffPath}\`*`, "");
|
|
224
225
|
}
|
|
225
|
-
} catch (
|
|
226
|
-
lines.push(`*Handoff document at \`${handoffPath}\` could not be read: ${
|
|
226
|
+
} catch (error: any) {
|
|
227
|
+
lines.push(`*Handoff document at \`${handoffPath}\` could not be read: ${error}*`, "");
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
const restore = buildRestoreSections(ctx, projectRoot, true);
|
|
@@ -266,8 +267,8 @@ export function formatContextList(contexts: ContextState[]): string {
|
|
|
266
267
|
if (contexts.length === 0) return "No active contexts found.";
|
|
267
268
|
|
|
268
269
|
const lines = ["## Active Contexts\n"];
|
|
269
|
-
for (
|
|
270
|
-
const ctx =
|
|
270
|
+
for (const [i, context_] of contexts.entries()) {
|
|
271
|
+
const ctx = context_!;
|
|
271
272
|
const timeStr = formatRelativeTime(ctx.last_active);
|
|
272
273
|
const md = getModeDisplay(ctx.mode ?? "idle");
|
|
273
274
|
const si = md ? ` ${md}` : "";
|
|
@@ -349,11 +350,11 @@ export function formatContextPickerStderr(contexts: ContextState[]): string {
|
|
|
349
350
|
];
|
|
350
351
|
|
|
351
352
|
let selectableCount = 0;
|
|
352
|
-
for (
|
|
353
|
-
const ctx =
|
|
353
|
+
for (const [i, context_] of contexts.entries()) {
|
|
354
|
+
const ctx = context_!;
|
|
354
355
|
const timeStr = formatRelativeTime(ctx.last_active);
|
|
355
356
|
const mode = ctx.mode ?? "idle";
|
|
356
|
-
const isSelectable = mode === "active" ||
|
|
357
|
+
const isSelectable = mode === "active" || Boolean(ctx.handoff_path);
|
|
357
358
|
if (isSelectable) selectableCount++;
|
|
358
359
|
|
|
359
360
|
let status = "";
|
|
@@ -451,7 +452,7 @@ const KNOWN_FOLDERS: Record<string, string> = {
|
|
|
451
452
|
"notes": "Analysis files, reports, and documentation that don't belong in the codebase",
|
|
452
453
|
};
|
|
453
454
|
|
|
454
|
-
function collectFolderPath(contextId: string, contextDir: string,
|
|
455
|
+
function collectFolderPath(contextId: string, contextDir: string, _state: ContextState): string | null {
|
|
455
456
|
if (!fs.existsSync(contextDir)) return null;
|
|
456
457
|
return `**Context folder:** \`${contextDir}\`\n**State file:** \`${path.join(contextDir, "state.json")}\` — contains session history, task records, plan/handoff metadata`;
|
|
457
458
|
}
|
|
@@ -485,7 +486,7 @@ function countFilesRecursive(dirPath: string): number {
|
|
|
485
486
|
return count;
|
|
486
487
|
}
|
|
487
488
|
|
|
488
|
-
function collectFolderInventory(contextId: string, contextDir: string,
|
|
489
|
+
function collectFolderInventory(contextId: string, contextDir: string, _state: ContextState): string | null {
|
|
489
490
|
if (!fs.existsSync(contextDir)) return null;
|
|
490
491
|
let entries: fs.Dirent[];
|
|
491
492
|
try {
|
|
@@ -519,7 +520,7 @@ function collectSessionStats(contextId: string, contextDir: string, state: Conte
|
|
|
519
520
|
transcriptCount = files.length;
|
|
520
521
|
if (files.length > 1) {
|
|
521
522
|
const oldest = files[0]!.slice(0, 10);
|
|
522
|
-
const newest = files
|
|
523
|
+
const newest = files.at(-1)!.slice(0, 10);
|
|
523
524
|
if (oldest !== newest) timeRange = ` (${oldest} to ${newest})`;
|
|
524
525
|
}
|
|
525
526
|
} catch { /* ignore */ }
|
|
@@ -532,7 +533,7 @@ function collectSessionStats(contextId: string, contextDir: string, state: Conte
|
|
|
532
533
|
return line;
|
|
533
534
|
}
|
|
534
535
|
|
|
535
|
-
function collectNotesGuidance(contextId: string, contextDir: string,
|
|
536
|
+
function collectNotesGuidance(contextId: string, contextDir: string, _state: ContextState): string | null {
|
|
536
537
|
const notesDir = path.join(contextDir, "notes");
|
|
537
538
|
return `**Notes:** Put notes and files that don't belong in the codebase here. Reference them in other documents as needed: \`${notesDir}\``;
|
|
538
539
|
}
|
|
@@ -14,6 +14,15 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import * as crypto from "node:crypto";
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
formatActiveContextReminder,
|
|
20
|
+
formatContextCreated,
|
|
21
|
+
formatContextPickerStderr,
|
|
22
|
+
formatCommandFeedback,
|
|
23
|
+
formatHandoffContinuation,
|
|
24
|
+
formatPlanContinuation,
|
|
25
|
+
} from "./context-formatter.js";
|
|
17
26
|
import {
|
|
18
27
|
getContext,
|
|
19
28
|
getAllContexts,
|
|
@@ -25,18 +34,9 @@ import {
|
|
|
25
34
|
updateMode,
|
|
26
35
|
determineArtifactType,
|
|
27
36
|
} from "./context-store.js";
|
|
28
|
-
import {
|
|
29
|
-
formatActiveContextReminder,
|
|
30
|
-
formatContextCreated,
|
|
31
|
-
formatContextPickerStderr,
|
|
32
|
-
formatCommandFeedback,
|
|
33
|
-
formatHandoffContinuation,
|
|
34
|
-
formatPlanContinuation,
|
|
35
|
-
formatActiveContinuation,
|
|
36
|
-
} from "./context-formatter.js";
|
|
37
37
|
import { normalizePlanContent } from "./plan-manager.js";
|
|
38
|
+
import { logDebug, logInfo, logError } from "../base/logger.js";
|
|
38
39
|
import { isInternalCall } from "../base/subprocess-utils.js";
|
|
39
|
-
import { logDebug, logInfo, logWarn, logError } from "../base/logger.js";
|
|
40
40
|
import type { ContextState, CaretCommand } from "../types.js";
|
|
41
41
|
|
|
42
42
|
/** Minimum characters required for new context description. */
|
|
@@ -277,9 +277,9 @@ function matchPlanContent(prompt: string, hasPlanContexts: ContextState[]): Cont
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
// Tier 4 (legacy): Signature match
|
|
280
|
-
const promptHead = prompt.slice(0, 500);
|
|
280
|
+
const promptHead = new Set(prompt.slice(0, 500));
|
|
281
281
|
for (const ctx of hasPlanContexts) {
|
|
282
|
-
if (ctx.plan_signature && promptHead.
|
|
282
|
+
if (ctx.plan_signature && promptHead.has(ctx.plan_signature)) {
|
|
283
283
|
logDebug("context_selector", `Tier 4 legacy signature match: ${ctx.id}`);
|
|
284
284
|
return ctx;
|
|
285
285
|
}
|
|
@@ -302,8 +302,8 @@ function createNewContext(
|
|
|
302
302
|
newCtx.mode = "active";
|
|
303
303
|
logInfo("context_selector", `Auto-created context: ${newCtx.id}`);
|
|
304
304
|
return [newCtx.id, "auto_created", formatContextCreated(newCtx)];
|
|
305
|
-
} catch (
|
|
306
|
-
logError("context_selector", `Primary context creation failed: ${
|
|
305
|
+
} catch (error: any) {
|
|
306
|
+
logError("context_selector", `Primary context creation failed: ${error}`);
|
|
307
307
|
try {
|
|
308
308
|
const now = new Date();
|
|
309
309
|
const yy = String(now.getFullYear()).slice(2);
|
|
@@ -323,8 +323,8 @@ function createNewContext(
|
|
|
323
323
|
newCtx.mode = "active";
|
|
324
324
|
logInfo("context_selector", `Fallback context created: ${newCtx.id}`);
|
|
325
325
|
return [newCtx.id, "auto_created_fallback", formatContextCreated(newCtx)];
|
|
326
|
-
} catch (
|
|
327
|
-
logError("context_selector", `ALL context creation failed: ${
|
|
326
|
+
} catch (error: any) {
|
|
327
|
+
logError("context_selector", `ALL context creation failed: ${error}`);
|
|
328
328
|
return [null, "creation_failed", null];
|
|
329
329
|
}
|
|
330
330
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
import * as path from "node:path";
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
import { atomicWrite } from "../base/atomic-write.js";
|
|
14
14
|
import {
|
|
15
15
|
getContextDir,
|
|
@@ -20,7 +20,8 @@ import {
|
|
|
20
20
|
getArchiveIndexPath,
|
|
21
21
|
validateContextId,
|
|
22
22
|
} from "../base/constants.js";
|
|
23
|
-
import {
|
|
23
|
+
import { logInfo, logWarn, logError, setContextPath } from "../base/logger.js";
|
|
24
|
+
import { readStateJson, writeStateJson } from "../base/state-io.js";
|
|
24
25
|
import { nowIso, generateContextId } from "../base/utils.js";
|
|
25
26
|
import type { ContextState, IndexFile, IndexEntry, Mode } from "../types.js";
|
|
26
27
|
|
|
@@ -77,8 +78,8 @@ function loadIndex(projectRoot?: string): IndexFile {
|
|
|
77
78
|
try {
|
|
78
79
|
const raw = fs.readFileSync(indexPath, "utf-8");
|
|
79
80
|
return JSON.parse(raw) as IndexFile;
|
|
80
|
-
} catch (
|
|
81
|
-
logWarn("context_store", `Failed to read index, recreating: ${
|
|
81
|
+
} catch (error: any) {
|
|
82
|
+
logWarn("context_store", `Failed to read index, recreating: ${error}`);
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
return { version: INDEX_VERSION, updated_at: nowIso(), sessions: {}, contexts: {} };
|
|
@@ -145,8 +146,8 @@ function migrateContextJson(contextId: string, projectRoot?: string): ContextSta
|
|
|
145
146
|
last_session: null,
|
|
146
147
|
tasks: [],
|
|
147
148
|
};
|
|
148
|
-
} catch (
|
|
149
|
-
logWarn("context_store", `Failed to migrate context.json for '${contextId}': ${
|
|
149
|
+
} catch (error: any) {
|
|
150
|
+
logWarn("context_store", `Failed to migrate context.json for '${contextId}': ${error}`);
|
|
150
151
|
return null;
|
|
151
152
|
}
|
|
152
153
|
}
|
|
@@ -556,8 +557,8 @@ export function archiveContext(contextId: string, projectRoot?: string): Context
|
|
|
556
557
|
|
|
557
558
|
try {
|
|
558
559
|
fs.renameSync(sourceDir, archiveDest);
|
|
559
|
-
} catch (
|
|
560
|
-
logError("context_store", `Failed to move context to archive: ${
|
|
560
|
+
} catch (error: any) {
|
|
561
|
+
logError("context_store", `Failed to move context to archive: ${error}`);
|
|
561
562
|
return null;
|
|
562
563
|
}
|
|
563
564
|
|
|
@@ -647,8 +648,8 @@ function updateArchiveIndex(state: ContextState, projectRoot?: string): boolean
|
|
|
647
648
|
if (fs.existsSync(archiveIndexPath)) {
|
|
648
649
|
try {
|
|
649
650
|
archiveIndex = JSON.parse(fs.readFileSync(archiveIndexPath, "utf-8"));
|
|
650
|
-
} catch (
|
|
651
|
-
logWarn("context_store", `Failed to read archive index, recreating: ${
|
|
651
|
+
} catch (error_: any) {
|
|
652
|
+
logWarn("context_store", `Failed to read archive index, recreating: ${error_}`);
|
|
652
653
|
}
|
|
653
654
|
}
|
|
654
655
|
|
|
@@ -675,8 +676,8 @@ function restoreFromArchive(contextId: string, projectRoot?: string): ContextSta
|
|
|
675
676
|
|
|
676
677
|
try {
|
|
677
678
|
fs.renameSync(archiveDir, activeDir);
|
|
678
|
-
} catch (
|
|
679
|
-
logError("context_store", `Failed to restore context from archive: ${
|
|
679
|
+
} catch (error: any) {
|
|
680
|
+
logError("context_store", `Failed to restore context from archive: ${error}`);
|
|
680
681
|
return null;
|
|
681
682
|
}
|
|
682
683
|
|
|
@@ -705,8 +706,8 @@ function removeFromArchiveIndex(contextId: string, projectRoot?: string): boolea
|
|
|
705
706
|
}
|
|
706
707
|
}
|
|
707
708
|
return true;
|
|
708
|
-
} catch (
|
|
709
|
-
logWarn("context_store", `Failed to read archive index: ${
|
|
709
|
+
} catch (error: any) {
|
|
710
|
+
logWarn("context_store", `Failed to read archive index: ${error}`);
|
|
710
711
|
return false;
|
|
711
712
|
}
|
|
712
713
|
}
|
|
@@ -13,10 +13,9 @@ import * as fs from "node:fs";
|
|
|
13
13
|
import * as path from "node:path";
|
|
14
14
|
|
|
15
15
|
import { atomicWrite } from "../base/atomic-write.js";
|
|
16
|
-
import {
|
|
16
|
+
import { getContextPlansDir, sanitizeTitle } from "../base/constants.js";
|
|
17
17
|
import { logDebug, logInfo, logWarn, logError } from "../base/logger.js";
|
|
18
18
|
import { generateSlug } from "../base/utils.js";
|
|
19
|
-
import type { ContextState } from "../types.js";
|
|
20
19
|
|
|
21
20
|
// ---------------------------------------------------------------------------
|
|
22
21
|
// Plan archival
|
|
@@ -144,6 +143,7 @@ export function findLatestPlan(
|
|
|
144
143
|
// 1. Check state.json plan_path first
|
|
145
144
|
try {
|
|
146
145
|
// Dynamic import to avoid circular dependency at module level
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef -- dynamic require to avoid circular dependency
|
|
147
147
|
const stateIo = require("../base/state-io.js");
|
|
148
148
|
const state = stateIo.readStateJson(contextId, projectRoot);
|
|
149
149
|
if (state?.plan_path && fs.existsSync(state.plan_path)) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Cross-platform project root resolver for hook and status line commands.
|
|
4
|
+
*
|
|
5
|
+
* Finds the project root (via git or .aiwcli/ anchor walk-up), then spawns
|
|
6
|
+
* the target script with cwd set to the root. stdin/stdout/stderr pass through.
|
|
7
|
+
*
|
|
8
|
+
* Install: ~/.aiwcli/bin/resolve-run.ts (global, always findable via ~)
|
|
9
|
+
* Usage: bun ~/.aiwcli/bin/resolve-run.ts .aiwcli/_shared/scripts/status_line.ts
|
|
10
|
+
*
|
|
11
|
+
* Works on: bash, zsh, PowerShell, cmd (anywhere bun + ~ expansion works)
|
|
12
|
+
*/
|
|
13
|
+
import { execSync } from "node:child_process";
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import * as path from "node:path";
|
|
16
|
+
|
|
17
|
+
function findProjectRoot(): string {
|
|
18
|
+
// 1. git (works from any subdirectory of a repo)
|
|
19
|
+
try {
|
|
20
|
+
const root = execSync("git rev-parse --show-toplevel", {
|
|
21
|
+
encoding: "utf-8",
|
|
22
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
23
|
+
timeout: 2000,
|
|
24
|
+
}).trim();
|
|
25
|
+
if (root && fs.existsSync(path.join(root, ".aiwcli"))) return root;
|
|
26
|
+
} catch { /* not a git repo or git not available */ }
|
|
27
|
+
|
|
28
|
+
// 2. Walk up from cwd to find .aiwcli/ anchor
|
|
29
|
+
let dir = process.cwd();
|
|
30
|
+
while (true) {
|
|
31
|
+
if (fs.existsSync(path.join(dir, ".aiwcli"))) return dir;
|
|
32
|
+
const parent = path.dirname(dir);
|
|
33
|
+
if (parent === dir) break;
|
|
34
|
+
dir = parent;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return process.cwd(); // last resort
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const target = process.argv[2];
|
|
41
|
+
if (!target) {
|
|
42
|
+
process.stderr.write("resolve-run: missing script path argument\n");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const root = findProjectRoot();
|
|
47
|
+
const fullPath = path.resolve(root, target);
|
|
48
|
+
|
|
49
|
+
if (!fs.existsSync(fullPath)) {
|
|
50
|
+
process.stderr.write(`resolve-run: script not found: ${fullPath}\n`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const result = Bun.spawnSync(["bun", fullPath], {
|
|
55
|
+
stdin: "inherit",
|
|
56
|
+
stdout: "inherit",
|
|
57
|
+
stderr: "inherit",
|
|
58
|
+
cwd: root,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
process.exit(result.exitCode);
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Requires CLAUDE_SESSION_ID environment variable (set by Claude Code).
|
|
13
13
|
*/
|
|
14
|
-
import { getContextBySessionId } from "../lib-ts/context/context-store.js";
|
|
15
14
|
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
16
15
|
import { eprint } from "../lib-ts/base/utils.js";
|
|
16
|
+
import { getContextBySessionId } from "../lib-ts/context/context-store.js";
|
|
17
17
|
|
|
18
18
|
const projectRoot = getProjectRoot(process.cwd());
|
|
19
19
|
const sessionId = process.env.CLAUDE_SESSION_ID;
|
|
@@ -22,7 +22,10 @@ import { findLatestPlan } from "../lib-ts/context/plan-manager.js";
|
|
|
22
22
|
// Path setup
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
const SCRIPT_DIR = path.dirname(new URL(import.meta.url).pathname);
|
|
25
|
-
|
|
25
|
+
// Resolve project root from script location (.aiwcli/_shared/scripts/) so paths
|
|
26
|
+
// work even when cwd has drifted via `cd` in a Bash tool call.
|
|
27
|
+
const PROJECT_ROOT = path.resolve(SCRIPT_DIR, "..", "..", "..");
|
|
28
|
+
const OUTPUT_DIR = path.join(PROJECT_ROOT, "_output");
|
|
26
29
|
const CACHE_DIR = path.join(OUTPUT_DIR, "cache");
|
|
27
30
|
const STATUSLINE_CACHE = path.join(CACHE_DIR, ".statusline-cache.json");
|
|
28
31
|
|
|
@@ -266,9 +269,10 @@ function runGit(args: string[], cwd: string, timeout = 2000): string | null {
|
|
|
266
269
|
}
|
|
267
270
|
|
|
268
271
|
function getGitStatus(cwd: string): GitStatus | null {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
+
// One call replaces 6: branch, modified, staged, untracked, ahead/behind, and repo check.
|
|
273
|
+
// porcelain=v2 -b gives structured header lines + per-file XY status codes.
|
|
274
|
+
const porcelain = runGit(["status", "--porcelain=v2", "-b"], cwd);
|
|
275
|
+
if (porcelain === null) return null;
|
|
272
276
|
|
|
273
277
|
const status: GitStatus = {
|
|
274
278
|
branch: "detached",
|
|
@@ -282,36 +286,32 @@ function getGitStatus(cwd: string): GitStatus | null {
|
|
|
282
286
|
age_color: GIT_AGE_FRESH,
|
|
283
287
|
};
|
|
284
288
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
289
|
+
for (const line of porcelain.split(/\r?\n/)) {
|
|
290
|
+
if (line.startsWith("# branch.head ")) {
|
|
291
|
+
const b = line.slice(14).trim();
|
|
292
|
+
status.branch = b === "(detached)" ? "detached" : b;
|
|
293
|
+
} else if (line.startsWith("# branch.ab ")) {
|
|
294
|
+
// Format: "+<ahead> -<behind>"
|
|
295
|
+
const m = line.match(/\+(\d+) -(\d+)/);
|
|
296
|
+
if (m) {
|
|
297
|
+
status.ahead = parseInt(m[1]!, 10);
|
|
298
|
+
status.behind = parseInt(m[2]!, 10);
|
|
299
|
+
}
|
|
300
|
+
} else if (line.startsWith("1 ") || line.startsWith("2 ")) {
|
|
301
|
+
// Changed tracked file: "1 XY ..." where X=staged Y=unstaged, '.'=unchanged
|
|
302
|
+
const x = line[2]!;
|
|
303
|
+
const y = line[3]!;
|
|
304
|
+
if (x !== ".") status.staged++;
|
|
305
|
+
if (y !== ".") status.modified++;
|
|
306
|
+
} else if (line.startsWith("? ")) {
|
|
307
|
+
status.untracked++;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
300
310
|
|
|
301
|
-
// Stash count
|
|
311
|
+
// Stash count (no equivalent in status output)
|
|
302
312
|
const stash = runGit(["stash", "list"], cwd);
|
|
303
313
|
if (stash) status.stash_count = stash.split(/\r?\n/).filter(Boolean).length;
|
|
304
314
|
|
|
305
|
-
// Ahead/behind
|
|
306
|
-
const ab = runGit(["rev-list", "--left-right", "--count", "HEAD...@{u}"], cwd);
|
|
307
|
-
if (ab) {
|
|
308
|
-
const parts = ab.split(/\s+/);
|
|
309
|
-
if (parts.length >= 2) {
|
|
310
|
-
status.ahead = parseInt(parts[0]!, 10) || 0;
|
|
311
|
-
status.behind = parseInt(parts[1]!, 10) || 0;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
315
|
// Commit age
|
|
316
316
|
const log = runGit(["log", "-1", "--format=%ct"], cwd);
|
|
317
317
|
if (log) {
|
|
@@ -345,89 +345,97 @@ function getGitStatus(cwd: string): GitStatus | null {
|
|
|
345
345
|
return status;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
function renderGit(mode: string, git: GitStatus, dirName: string): void {
|
|
349
|
-
const totalChanged = git.modified + git.staged;
|
|
350
|
-
const statusIcon = (totalChanged > 0 || git.untracked > 0) ? "*" : "\u2713";
|
|
348
|
+
function renderGit(mode: string, git: GitStatus | null, dirName: string): void {
|
|
349
|
+
const totalChanged = git ? git.modified + git.staged : 0;
|
|
350
|
+
const statusIcon = git && (totalChanged > 0 || git.untracked > 0) ? "*" : "\u2713";
|
|
351
351
|
|
|
352
352
|
switch (mode) {
|
|
353
353
|
case "micro": {
|
|
354
|
-
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_DIR}${dirName}${RESET}
|
|
355
|
-
if (git
|
|
356
|
-
line += ` ${
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
line +=
|
|
361
|
-
|
|
362
|
-
|
|
354
|
+
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_DIR}${dirName}${RESET}`;
|
|
355
|
+
if (git) {
|
|
356
|
+
line += ` ${GIT_VALUE}${git.branch}${RESET}`;
|
|
357
|
+
if (git.age_display) {
|
|
358
|
+
line += ` ${git.age_color}${git.age_display}${RESET}`;
|
|
359
|
+
}
|
|
360
|
+
line += " ";
|
|
361
|
+
if (statusIcon === "\u2713") {
|
|
362
|
+
line += `${GIT_CLEAN}${statusIcon}${RESET}`;
|
|
363
|
+
} else {
|
|
364
|
+
line += `${GIT_MODIFIED}${statusIcon}${totalChanged}${RESET}`;
|
|
365
|
+
}
|
|
363
366
|
}
|
|
364
367
|
console.log(line);
|
|
365
|
-
|
|
368
|
+
|
|
366
369
|
break;
|
|
367
370
|
}
|
|
368
371
|
case "mini": {
|
|
369
|
-
let line =
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
372
|
+
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_DIR}${dirName}${RESET}`;
|
|
373
|
+
if (git) {
|
|
374
|
+
line += ` ${SLATE_600}\u2502${RESET} ${GIT_VALUE}${git.branch}${RESET}`;
|
|
375
|
+
if (git.age_display) {
|
|
376
|
+
line += ` ${SLATE_600}\u2502${RESET} ${git.age_color}${git.age_display}${RESET}`;
|
|
377
|
+
}
|
|
378
|
+
line += ` ${SLATE_600}\u2502${RESET} `;
|
|
379
|
+
if (statusIcon === "\u2713") {
|
|
380
|
+
line += `${GIT_CLEAN}${statusIcon}${RESET}`;
|
|
381
|
+
} else {
|
|
382
|
+
line += `${GIT_MODIFIED}${statusIcon}${totalChanged}${RESET}`;
|
|
383
|
+
if (git.untracked > 0) {
|
|
384
|
+
line += ` ${GIT_ADDED}+${git.untracked}${RESET}`;
|
|
385
|
+
}
|
|
382
386
|
}
|
|
383
387
|
}
|
|
384
388
|
console.log(line);
|
|
385
|
-
|
|
389
|
+
|
|
386
390
|
break;
|
|
387
391
|
}
|
|
388
392
|
case "nano": {
|
|
389
|
-
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_DIR}${dirName}${RESET}
|
|
390
|
-
if (
|
|
391
|
-
line +=
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_DIR}${dirName}${RESET}`;
|
|
394
|
+
if (git) {
|
|
395
|
+
line += ` ${GIT_VALUE}${git.branch}${RESET} `;
|
|
396
|
+
if (statusIcon === "\u2713") {
|
|
397
|
+
line += `${GIT_CLEAN}\u2713${RESET}`;
|
|
398
|
+
} else {
|
|
399
|
+
line += `${GIT_MODIFIED}*${totalChanged}${RESET}`;
|
|
400
|
+
}
|
|
394
401
|
}
|
|
395
402
|
console.log(line);
|
|
396
|
-
|
|
403
|
+
|
|
397
404
|
break;
|
|
398
405
|
}
|
|
399
406
|
default: {
|
|
400
|
-
let line =
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
if (git.stash_count > 0) {
|
|
408
|
-
line += ` ${SLATE_600}\u2502${RESET} ${GIT_PRIMARY}Stash:${RESET} ${GIT_STASH}${git.stash_count}${RESET}`;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
if (totalChanged > 0 || git.untracked > 0) {
|
|
412
|
-
line += ` ${SLATE_600}\u2502${RESET} `;
|
|
413
|
-
if (totalChanged > 0) {
|
|
414
|
-
line += `${GIT_PRIMARY}Mod:${RESET} ${GIT_MODIFIED}${totalChanged}${RESET}`;
|
|
407
|
+
let line = `${GIT_PRIMARY}\u25C8${RESET} ${GIT_PRIMARY}PWD:${RESET} ${GIT_DIR}${dirName}${RESET}`;
|
|
408
|
+
if (git) {
|
|
409
|
+
line += ` ${SLATE_600}\u2502${RESET} ` +
|
|
410
|
+
`${GIT_PRIMARY}Branch:${RESET} ${GIT_VALUE}${git.branch}${RESET}`;
|
|
411
|
+
if (git.age_display) {
|
|
412
|
+
line += ` ${SLATE_600}\u2502${RESET} ${GIT_PRIMARY}Age:${RESET} ${git.age_color}${git.age_display}${RESET}`;
|
|
415
413
|
}
|
|
416
|
-
if (git.
|
|
417
|
-
|
|
418
|
-
line += `${GIT_PRIMARY}New:${RESET} ${GIT_ADDED}${git.untracked}${RESET}`;
|
|
414
|
+
if (git.stash_count > 0) {
|
|
415
|
+
line += ` ${SLATE_600}\u2502${RESET} ${GIT_PRIMARY}Stash:${RESET} ${GIT_STASH}${git.stash_count}${RESET}`;
|
|
419
416
|
}
|
|
420
|
-
} else {
|
|
421
|
-
line += ` ${SLATE_600}\u2502${RESET} ${GIT_CLEAN}\u2713 clean${RESET}`;
|
|
422
|
-
}
|
|
423
417
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
418
|
+
if (totalChanged > 0 || git.untracked > 0) {
|
|
419
|
+
line += ` ${SLATE_600}\u2502${RESET} `;
|
|
420
|
+
if (totalChanged > 0) {
|
|
421
|
+
line += `${GIT_PRIMARY}Mod:${RESET} ${GIT_MODIFIED}${totalChanged}${RESET}`;
|
|
422
|
+
}
|
|
423
|
+
if (git.untracked > 0) {
|
|
424
|
+
if (totalChanged > 0) line += " ";
|
|
425
|
+
line += `${GIT_PRIMARY}New:${RESET} ${GIT_ADDED}${git.untracked}${RESET}`;
|
|
426
|
+
}
|
|
427
|
+
} else {
|
|
428
|
+
line += ` ${SLATE_600}\u2502${RESET} ${GIT_CLEAN}\u2713 clean${RESET}`;
|
|
428
429
|
}
|
|
429
|
-
|
|
430
|
-
|
|
430
|
+
|
|
431
|
+
if (git.ahead > 0 || git.behind > 0) {
|
|
432
|
+
line += ` ${SLATE_600}\u2502${RESET} ${GIT_PRIMARY}Sync:${RESET} `;
|
|
433
|
+
if (git.ahead > 0) {
|
|
434
|
+
line += `${GIT_CLEAN}\u2191${git.ahead}${RESET}`;
|
|
435
|
+
}
|
|
436
|
+
if (git.behind > 0) {
|
|
437
|
+
line += `${GIT_STASH}\u2193${git.behind}${RESET}`;
|
|
438
|
+
}
|
|
431
439
|
}
|
|
432
440
|
}
|
|
433
441
|
console.log(line);
|
|
@@ -687,11 +695,9 @@ function main(): void {
|
|
|
687
695
|
// Render context section
|
|
688
696
|
renderContext(mode, contextPct, contextK, maxK, timeDisplay, modelName);
|
|
689
697
|
|
|
690
|
-
// Render git section
|
|
698
|
+
// Render PWD + git section (PWD always shown, git stats only when in a repo)
|
|
691
699
|
const git = getGitStatus(currentDir);
|
|
692
|
-
|
|
693
|
-
renderGit(mode, git, dirName);
|
|
694
|
-
}
|
|
700
|
+
renderGit(mode, git, dirName);
|
|
695
701
|
|
|
696
702
|
// Render context manager line (line 3) with separator
|
|
697
703
|
console.log(SEPARATOR);
|