-
Notifications
You must be signed in to change notification settings - Fork 0
P1: add project lifecycle commands #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
1949166
Add MCP freshness checks
lzehrung b8bb529
Fix MCP freshness review findings
lzehrung 054a213
Harden SQLite artifact freshness
lzehrung 2216acd
Fix SQLite artifact freshness edge cases
lzehrung 84531fb
Complete SQLite artifact freshness hardening
lzehrung 1ee8780
Close SQLite freshness review gaps
lzehrung 1a07246
Cover SQLite freshness edge cases
lzehrung 5c1aa8e
Add explore facade
lzehrung 86a7083
Add agent installer workflow
lzehrung 30cf07f
Add project lifecycle commands
lzehrung ced65d1
Fix lifecycle freshness and force behavior
lzehrung 3dc25dd
Address lifecycle review findings
lzehrung 4bd1dbb
Resolve lifecycle verify regressions
lzehrung 9b911f4
Complete lifecycle review coverage
lzehrung ac97209
Normalize lifecycle option drift
lzehrung a8472f5
Cover lifecycle option defaults
lzehrung 674abe1
Merge origin/main into p1/lifecycle-commands
lzehrung 8a7f827
Fix lifecycle sync diffing, config drift, and root test coverage
lzehrung 14841f2
Centralize config drift hashing and strengthen content-drift coverage
lzehrung 4bf6920
Surface config hash errors and cover disk cache invalidation
lzehrung f19d53e
Cover lifecycle config hash warning path
lzehrung 07cf92c
Address Copilot review: lazy status I/O, metadata file signatures, st…
lzehrung 9a034f1
Address Copilot review: drop non-functional --cache from lifecycle co…
lzehrung d2534b6
Fix: restore --cache in EXPLORE_HELP_TEXT, only accurate for explore
lzehrung 935c4ab
Address Copilot review: make stableStringify total, relax brittle cac…
lzehrung 5444ce5
Address Copilot review: wrap uninit dir errors, drop no-op --pretty, …
lzehrung ddbe388
Address Copilot review + proactive self-review: consistent totalDelta…
lzehrung File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import type { BuildOptions } from "../indexer/types.js"; | ||
| import { | ||
| getCodegraphLifecycleStatus, | ||
| initCodegraphLifecycle, | ||
| syncCodegraphLifecycle, | ||
| uninitCodegraphLifecycle, | ||
| type CodegraphLifecycleStatus, | ||
| type CodegraphLifecycleSyncResult, | ||
| type CodegraphLifecycleUninitResult, | ||
| } from "../lifecycle/manifest.js"; | ||
|
|
||
| export type LifecycleCommandContext = { | ||
| command: "init" | "status" | "sync" | "uninit"; | ||
| root: string; | ||
| buildOptions?: BuildOptions; | ||
| hasFlag: (name: string) => boolean; | ||
| writeJSONLine: (value: unknown) => void; | ||
| writeStdoutLine: (message: string) => void; | ||
| }; | ||
|
|
||
| export async function handleLifecycleCommand(context: LifecycleCommandContext): Promise<void> { | ||
| if (context.command === "init") { | ||
| const result = await initCodegraphLifecycle(context.root, { | ||
| ...(context.buildOptions ? { buildOptions: context.buildOptions } : {}), | ||
| force: context.hasFlag("--force"), | ||
| }); | ||
| writeLifecycleResult(context, result, formatSyncResult("Initialized", result)); | ||
| return; | ||
| } | ||
|
|
||
| if (context.command === "sync") { | ||
| const result = await syncCodegraphLifecycle(context.root, { | ||
| ...(context.buildOptions ? { buildOptions: context.buildOptions } : {}), | ||
| init: context.hasFlag("--init"), | ||
| }); | ||
| writeLifecycleResult(context, result, formatSyncResult("Synced", result)); | ||
| return; | ||
| } | ||
|
|
||
| if (context.command === "uninit") { | ||
| const result = await uninitCodegraphLifecycle(context.root, { force: context.hasFlag("--force") }); | ||
| writeLifecycleResult(context, result, formatUninitResult(result)); | ||
| return; | ||
| } | ||
|
|
||
| const result = await getCodegraphLifecycleStatus(context.root, { | ||
| ...(context.buildOptions ? { buildOptions: context.buildOptions } : {}), | ||
| }); | ||
| writeLifecycleResult(context, result, formatStatus(result)); | ||
| } | ||
|
|
||
| function writeLifecycleResult( | ||
| context: LifecycleCommandContext, | ||
| value: CodegraphLifecycleStatus | CodegraphLifecycleSyncResult | CodegraphLifecycleUninitResult, | ||
| pretty: string, | ||
| ): void { | ||
| if (context.hasFlag("--json")) { | ||
| context.writeJSONLine(value); | ||
| } else { | ||
| context.writeStdoutLine(pretty); | ||
| } | ||
| } | ||
|
|
||
| function formatSyncResult(label: string, result: CodegraphLifecycleSyncResult): string { | ||
| const { added, removed } = result.changedFiles; | ||
| // Report added/removed explicitly rather than the net delta alone: equal adds and removes | ||
| // cancel out to a delta of 0, which would otherwise hide real file churn. | ||
| const changeLabel = added || removed ? `, +${added}/-${removed}` : ""; | ||
| return `${label} Codegraph at ${result.root}: ${result.manifest.fileCount} files${changeLabel}. Manifest: ${result.manifestPath}`; | ||
| } | ||
|
|
||
| function formatUninitResult(result: CodegraphLifecycleUninitResult): string { | ||
| if (!result.removed) return `Codegraph is not initialized at ${result.root}.`; | ||
| return `Removed Codegraph lifecycle state at ${result.root}.`; | ||
| } | ||
|
|
||
| function formatStatus(status: CodegraphLifecycleStatus): string { | ||
| if (!status.initialized) { | ||
| return `Codegraph is not initialized at ${status.root}. Next: ${status.suggestedNextCommand}`; | ||
| } | ||
| const fileCount = status.fileCount ? `${status.fileCount.then} then, ${status.fileCount.current} current` : "unknown"; | ||
| const filesChanged = status.filesChanged ? "yes" : "no"; | ||
| const configChanged = status.configChanged ? "yes" : "no"; | ||
| const buildOptionsChanged = status.buildOptionsChanged ? "yes" : "no"; | ||
| const analysis = status.analysis?.label ?? "unknown"; | ||
| return [ | ||
| `Codegraph initialized at ${status.root}.`, | ||
| `Last sync: ${status.lastSyncAt ?? "unknown"}`, | ||
| `Files: ${fileCount}`, | ||
| `Files changed: ${filesChanged}`, | ||
| `Config changed: ${configChanged}`, | ||
| `Build options changed: ${buildOptionsChanged}`, | ||
| `Analysis: ${analysis}`, | ||
| `Next: ${status.suggestedNextCommand}`, | ||
| ].join("\n"); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ddbe388: formatStatus now includes a 'Files changed: yes/no' line. While in the area, also fixed the closely related issue in formatSyncResult: it previously showed only the net delta, so e.g. 3 files added and 3 removed in the same sync produced totalDelta: 0 and the change label was suppressed entirely (deltaLabel was only shown when non-zero), silently hiding real churn. It now prints explicit +/- instead. Regression tests cover both via captureCli against the actual pretty-printed stdout (no --json).