@mrpatronz/nexusflow 0.2.19 → 1.3.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 +27 -3
- package/dist/analyzers/index.d.ts +23 -0
- package/dist/analyzers/index.d.ts.map +1 -1
- package/dist/analyzers/index.js +62 -0
- package/dist/analyzers/index.js.map +1 -1
- package/dist/commands/commands.test.js +20 -6
- package/dist/commands/commands.test.js.map +1 -1
- package/dist/commands/commit.d.ts +2 -0
- package/dist/commands/commit.d.ts.map +1 -1
- package/dist/commands/commit.js +27 -5
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/diff.d.ts +9 -2
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +36 -12
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff.js +2 -2
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/refresh.d.ts +4 -2
- package/dist/commands/refresh.d.ts.map +1 -1
- package/dist/commands/refresh.js +20 -36
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/schedule.d.ts +35 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +151 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +28 -7
- package/dist/commands/sync.js.map +1 -1
- package/dist/core/analysis-cache.d.ts +58 -0
- package/dist/core/analysis-cache.d.ts.map +1 -0
- package/dist/core/analysis-cache.js +116 -0
- package/dist/core/analysis-cache.js.map +1 -0
- package/dist/core/analysis-cache.test.d.ts +2 -0
- package/dist/core/analysis-cache.test.d.ts.map +1 -0
- package/dist/core/analysis-cache.test.js +108 -0
- package/dist/core/analysis-cache.test.js.map +1 -0
- package/dist/core/refresh.d.ts +41 -0
- package/dist/core/refresh.d.ts.map +1 -0
- package/dist/core/refresh.js +60 -0
- package/dist/core/refresh.js.map +1 -0
- package/dist/core/scheduler.d.ts +117 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +247 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/scheduler.test.d.ts +2 -0
- package/dist/core/scheduler.test.d.ts.map +1 -0
- package/dist/core/scheduler.test.js +111 -0
- package/dist/core/scheduler.test.js.map +1 -0
- package/dist/core/sync.d.ts +6 -0
- package/dist/core/sync.d.ts.map +1 -1
- package/dist/core/sync.js +15 -5
- package/dist/core/sync.js.map +1 -1
- package/dist/generators/index.d.ts +7 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +14 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/index.js +107 -4
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +81 -0
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +66 -0
- package/dist/server.test.js.map +1 -1
- package/dist/utils/multi-git.d.ts +21 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +40 -4
- package/dist/utils/multi-git.js.map +1 -1
- package/package.json +13 -1
- package/.agents/skills/ccc/SKILL.md +0 -71
- package/.agents/skills/ccc/references/management.md +0 -110
- package/.agents/skills/ccc/references/settings.md +0 -126
- package/.github/dependabot.yml +0 -52
- package/.github/workflows/ci.yml +0 -44
- package/.github/workflows/dependabot-merge.yml +0 -53
- package/.github/workflows/release-desktop.yml +0 -67
- package/.github/workflows/release-npm.yml +0 -65
- package/.github/workflows/release-vscode.yml +0 -61
- package/.vscode/launch.json +0 -17
- package/.vscode/tasks.json +0 -17
- package/GETTING_STARTED.md +0 -114
- package/desktop/build-installer.js +0 -228
- package/desktop/build.js +0 -118
- package/desktop/installer/nexusflow.iss +0 -35
- package/desktop/neutralino.config.json +0 -39
- package/desktop/package-lock.json +0 -1060
- package/desktop/package.json +0 -14
- package/extension/media/icon.svg +0 -1
- package/extension/package-lock.json +0 -6044
- package/extension/package.json +0 -117
- package/extension/src/extension.ts +0 -653
- package/extension/tsconfig.json +0 -21
- package/gui/README.md +0 -73
- package/gui/e2e/dashboard.spec.ts +0 -61
- package/gui/e2e/wizard.spec.ts +0 -346
- package/gui/eslint.config.js +0 -26
- package/gui/index.html +0 -17
- package/gui/package-lock.json +0 -3137
- package/gui/package.json +0 -37
- package/gui/playwright.config.ts +0 -41
- package/gui/public/app_logo.png +0 -0
- package/gui/public/favicon.svg +0 -1
- package/gui/public/icons.svg +0 -24
- package/gui/src/App.css +0 -1
- package/gui/src/App.tsx +0 -3573
- package/gui/src/app/AppSidebar.tsx +0 -69
- package/gui/src/assets/hero.png +0 -0
- package/gui/src/assets/react.svg +0 -1
- package/gui/src/assets/vite.svg +0 -1
- package/gui/src/components/AddRepoPicker.tsx +0 -81
- package/gui/src/components/ui/Button.tsx +0 -40
- package/gui/src/components/ui/Card.tsx +0 -6
- package/gui/src/components/ui/EmptyState.tsx +0 -22
- package/gui/src/components/ui/Input.tsx +0 -21
- package/gui/src/components/ui/Menu.tsx +0 -71
- package/gui/src/components/ui/Modal.tsx +0 -39
- package/gui/src/components/ui/PageHeader.tsx +0 -21
- package/gui/src/components/ui/RepoStatusStrip.tsx +0 -33
- package/gui/src/components/ui/Skeleton.tsx +0 -5
- package/gui/src/components/ui/StatusPill.tsx +0 -36
- package/gui/src/components/ui/Tabs.tsx +0 -40
- package/gui/src/components/ui/cn.ts +0 -4
- package/gui/src/components/ui/index.ts +0 -16
- package/gui/src/features/changes/ChangesViewer.tsx +0 -388
- package/gui/src/features/knowledge/KnowledgeBase.tsx +0 -84
- package/gui/src/features/onboarding/OnboardingWizard.tsx +0 -230
- package/gui/src/features/plan/ImplementationPlan.tsx +0 -32
- package/gui/src/features/services/ServiceConsole.tsx +0 -215
- package/gui/src/features/sessions/SessionHistory.tsx +0 -195
- package/gui/src/index.css +0 -167
- package/gui/src/lib/status.ts +0 -24
- package/gui/src/main.tsx +0 -94
- package/gui/src/pages/DashboardPage.tsx +0 -129
- package/gui/src/pages/WorkspacesPage.tsx +0 -352
- package/gui/src/types.ts +0 -81
- package/gui/tsconfig.app.json +0 -25
- package/gui/tsconfig.json +0 -7
- package/gui/tsconfig.node.json +0 -24
- package/gui/vite.config.ts +0 -12
- package/resources/workflows/plan-implement-review.md +0 -8
- package/resources/workflows/research-verify.md +0 -6
- package/resources/workflows/solo-developer.md +0 -3
- package/scripts/simulate-workspaces.ts +0 -55
- package/skills-lock.json +0 -11
- package/src/analyzers/detect-apis.ts +0 -290
- package/src/analyzers/detect-deps.ts +0 -315
- package/src/analyzers/detect-existing.ts +0 -74
- package/src/analyzers/detect-ports.ts +0 -110
- package/src/analyzers/index.ts +0 -97
- package/src/analyzers/messaging-analyzer.ts +0 -254
- package/src/analyzers/readme-summarizer.ts +0 -102
- package/src/analyzers/run-analyzer.ts +0 -269
- package/src/analyzers/tech-stack.ts +0 -283
- package/src/commands/adapter.ts +0 -348
- package/src/commands/add-repo.ts +0 -156
- package/src/commands/commands.test.ts +0 -156
- package/src/commands/commit.ts +0 -131
- package/src/commands/config.ts +0 -52
- package/src/commands/create.ts +0 -204
- package/src/commands/desktop.ts +0 -128
- package/src/commands/diff.ts +0 -125
- package/src/commands/doctor.ts +0 -370
- package/src/commands/handoff.ts +0 -266
- package/src/commands/init.ts +0 -134
- package/src/commands/list.ts +0 -46
- package/src/commands/logs.ts +0 -63
- package/src/commands/mcp.ts +0 -94
- package/src/commands/open.ts +0 -129
- package/src/commands/refresh.ts +0 -137
- package/src/commands/remove.ts +0 -98
- package/src/commands/start.ts +0 -117
- package/src/commands/status.ts +0 -54
- package/src/commands/stop.ts +0 -55
- package/src/commands/sync.ts +0 -125
- package/src/commands/tui.ts +0 -484
- package/src/commands/ui.ts +0 -111
- package/src/core/adapters/local-storage.ts +0 -66
- package/src/core/adapters/obsidian-storage.ts +0 -151
- package/src/core/adapters/registry.ts +0 -44
- package/src/core/adapters/storage.test.ts +0 -174
- package/src/core/adapters/vault-storage.ts +0 -86
- package/src/core/config.test.ts +0 -96
- package/src/core/config.ts +0 -140
- package/src/core/graph.ts +0 -344
- package/src/core/plugins/index.ts +0 -17
- package/src/core/plugins/loader.ts +0 -36
- package/src/core/ports/storage.ts +0 -71
- package/src/core/scanner.test.ts +0 -61
- package/src/core/scanner.ts +0 -91
- package/src/core/storage.ts +0 -37
- package/src/core/sync.ts +0 -121
- package/src/core/workspace-state.test.ts +0 -108
- package/src/core/workspace-state.ts +0 -130
- package/src/core/workspace.ts +0 -487
- package/src/core/worktree.ts +0 -120
- package/src/generators/antigravity.ts +0 -32
- package/src/generators/base.ts +0 -243
- package/src/generators/claude.ts +0 -34
- package/src/generators/codex.ts +0 -48
- package/src/generators/copilot.ts +0 -56
- package/src/generators/cursor.ts +0 -44
- package/src/generators/diff-context.ts +0 -75
- package/src/generators/index.ts +0 -322
- package/src/generators/map-generator.test.ts +0 -159
- package/src/generators/map-generator.ts +0 -539
- package/src/generators/plan-generator.ts +0 -483
- package/src/generators/skills-generator.ts +0 -259
- package/src/index.ts +0 -539
- package/src/mcp/server.ts +0 -338
- package/src/orchestration/detect.ts +0 -313
- package/src/orchestration/index.ts +0 -7
- package/src/orchestration/runner.ts +0 -283
- package/src/server.test.ts +0 -618
- package/src/server.ts +0 -1402
- package/src/types.ts +0 -451
- package/src/utils/detect-ai.test.ts +0 -44
- package/src/utils/detect-ai.ts +0 -84
- package/src/utils/detect-editors.test.ts +0 -48
- package/src/utils/detect-editors.ts +0 -57
- package/src/utils/git.test.ts +0 -74
- package/src/utils/git.ts +0 -117
- package/src/utils/local-ai.test.ts +0 -130
- package/src/utils/local-ai.ts +0 -116
- package/src/utils/multi-git.test.ts +0 -158
- package/src/utils/multi-git.ts +0 -405
- package/src/utils/prompts.ts +0 -209
- package/src/utils/session-finder.ts +0 -483
- package/src/utils/system-scanner.test.ts +0 -89
- package/src/utils/system-scanner.ts +0 -96
- package/src/utils/update-check.ts +0 -286
- package/src/utils/workflow-advisor.ts +0 -118
- package/src/utils/workflows.test.ts +0 -114
- package/src/utils/workflows.ts +0 -178
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -14
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/scheduler
|
|
3
|
+
* Recurring workspace jobs — periodic `sync` and `refresh` runs per workspace.
|
|
4
|
+
*
|
|
5
|
+
* Job definitions are persisted at `~/.nexusflow/schedules.json` and executed
|
|
6
|
+
* by any long-running NexusFlow process (the dashboard server started with
|
|
7
|
+
* `nexusflow ui` runs the scheduler automatically). Jobs use the headless
|
|
8
|
+
* cores (`syncWorkspace`, `refreshWorkspace`), which are cache-aware: a
|
|
9
|
+
* scheduled run only re-analyzes repos whose content changed, so unattended
|
|
10
|
+
* schedules stay token-efficient and never churn unchanged context files.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'node:fs/promises';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
import { getConfigDir, ensureConfigDir } from './config.js';
|
|
15
|
+
import { syncWorkspace } from './sync.js';
|
|
16
|
+
import { refreshWorkspace } from './refresh.js';
|
|
17
|
+
/** Name of the schedules file inside ~/.nexusflow. */
|
|
18
|
+
const SCHEDULES_FILE = 'schedules.json';
|
|
19
|
+
/**
|
|
20
|
+
* Returns the path to the schedules file (~/.nexusflow/schedules.json).
|
|
21
|
+
*/
|
|
22
|
+
export function getSchedulesPath() {
|
|
23
|
+
return path.join(getConfigDir(), SCHEDULES_FILE);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Loads all schedules, returning an empty store when the file does not exist
|
|
27
|
+
* or cannot be parsed.
|
|
28
|
+
*/
|
|
29
|
+
export async function loadSchedules() {
|
|
30
|
+
try {
|
|
31
|
+
const raw = await fs.readFile(getSchedulesPath(), 'utf-8');
|
|
32
|
+
const store = JSON.parse(raw);
|
|
33
|
+
if (!Array.isArray(store.jobs)) {
|
|
34
|
+
store.jobs = [];
|
|
35
|
+
}
|
|
36
|
+
return store;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { version: 1, jobs: [] };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Persists the schedule store to ~/.nexusflow/schedules.json.
|
|
44
|
+
*/
|
|
45
|
+
export async function saveSchedules(store) {
|
|
46
|
+
await ensureConfigDir();
|
|
47
|
+
const data = JSON.stringify(store, null, 2) + '\n';
|
|
48
|
+
await fs.writeFile(getSchedulesPath(), data, 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parses a human interval like '30m', '2h', '1d', or a bare minute count
|
|
52
|
+
* ('45') into minutes. Returns null for unparseable or non-positive input.
|
|
53
|
+
*/
|
|
54
|
+
export function parseInterval(text) {
|
|
55
|
+
const match = String(text).trim().match(/^(\d+)\s*([mhd]?)$/i);
|
|
56
|
+
if (!match)
|
|
57
|
+
return null;
|
|
58
|
+
const value = parseInt(match[1], 10);
|
|
59
|
+
if (value <= 0)
|
|
60
|
+
return null;
|
|
61
|
+
switch ((match[2] || 'm').toLowerCase()) {
|
|
62
|
+
case 'h':
|
|
63
|
+
return value * 60;
|
|
64
|
+
case 'd':
|
|
65
|
+
return value * 60 * 24;
|
|
66
|
+
default:
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Formats an interval in minutes back to a compact human string.
|
|
72
|
+
*/
|
|
73
|
+
export function formatInterval(minutes) {
|
|
74
|
+
if (minutes % (60 * 24) === 0)
|
|
75
|
+
return `${minutes / (60 * 24)}d`;
|
|
76
|
+
if (minutes % 60 === 0)
|
|
77
|
+
return `${minutes / 60}h`;
|
|
78
|
+
return `${minutes}m`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Whether a job is due to run: it is enabled and either never ran or its
|
|
82
|
+
* interval has elapsed since the last run. A job whose interval elapsed while
|
|
83
|
+
* no scheduler was running simply runs on the next tick.
|
|
84
|
+
*/
|
|
85
|
+
export function isDue(job, now = new Date()) {
|
|
86
|
+
if (!job.enabled)
|
|
87
|
+
return false;
|
|
88
|
+
if (!job.lastRunAt)
|
|
89
|
+
return true;
|
|
90
|
+
const last = Date.parse(job.lastRunAt);
|
|
91
|
+
if (Number.isNaN(last))
|
|
92
|
+
return true;
|
|
93
|
+
return now.getTime() - last >= job.intervalMinutes * 60_000;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Computes when a job will next be due, for display purposes.
|
|
97
|
+
*/
|
|
98
|
+
export function nextDueAt(job) {
|
|
99
|
+
if (!job.enabled)
|
|
100
|
+
return null;
|
|
101
|
+
if (!job.lastRunAt)
|
|
102
|
+
return new Date();
|
|
103
|
+
const last = Date.parse(job.lastRunAt);
|
|
104
|
+
if (Number.isNaN(last))
|
|
105
|
+
return new Date();
|
|
106
|
+
return new Date(last + job.intervalMinutes * 60_000);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Adds a new schedule and persists it.
|
|
110
|
+
*
|
|
111
|
+
* @param input - Workspace, task, and interval for the new job.
|
|
112
|
+
* @returns The created job.
|
|
113
|
+
*/
|
|
114
|
+
export async function addSchedule(input) {
|
|
115
|
+
const store = await loadSchedules();
|
|
116
|
+
const workspaceName = path.basename(input.workspacePath);
|
|
117
|
+
const job = {
|
|
118
|
+
id: `${input.task}-${workspaceName}-${Date.now().toString(36)}`,
|
|
119
|
+
workspacePath: input.workspacePath,
|
|
120
|
+
task: input.task,
|
|
121
|
+
intervalMinutes: input.intervalMinutes,
|
|
122
|
+
enabled: true,
|
|
123
|
+
createdAt: new Date().toISOString(),
|
|
124
|
+
};
|
|
125
|
+
store.jobs.push(job);
|
|
126
|
+
await saveSchedules(store);
|
|
127
|
+
return job;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Removes a schedule by id. Returns false when no job matched.
|
|
131
|
+
*/
|
|
132
|
+
export async function removeSchedule(id) {
|
|
133
|
+
const store = await loadSchedules();
|
|
134
|
+
const before = store.jobs.length;
|
|
135
|
+
store.jobs = store.jobs.filter((j) => j.id !== id);
|
|
136
|
+
if (store.jobs.length === before)
|
|
137
|
+
return false;
|
|
138
|
+
await saveSchedules(store);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Enables or disables a schedule by id. Returns the updated job, or null
|
|
143
|
+
* when no job matched.
|
|
144
|
+
*/
|
|
145
|
+
export async function setScheduleEnabled(id, enabled) {
|
|
146
|
+
const store = await loadSchedules();
|
|
147
|
+
const job = store.jobs.find((j) => j.id === id);
|
|
148
|
+
if (!job)
|
|
149
|
+
return null;
|
|
150
|
+
job.enabled = enabled;
|
|
151
|
+
await saveSchedules(store);
|
|
152
|
+
return job;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Runs a single job immediately and records the outcome in the store.
|
|
156
|
+
* Never throws — failures are captured in the returned result.
|
|
157
|
+
*
|
|
158
|
+
* @param job - The job to run.
|
|
159
|
+
* @returns The classified outcome with a summary message.
|
|
160
|
+
*/
|
|
161
|
+
export async function runJob(job) {
|
|
162
|
+
let result;
|
|
163
|
+
try {
|
|
164
|
+
if (job.task === 'sync') {
|
|
165
|
+
const report = await syncWorkspace(job.workspacePath);
|
|
166
|
+
const parts = [`${report.syncedCount} synced`];
|
|
167
|
+
if (report.conflictCount > 0)
|
|
168
|
+
parts.push(`${report.conflictCount} conflict(s)`);
|
|
169
|
+
if (report.errorCount > 0)
|
|
170
|
+
parts.push(`${report.errorCount} error(s)`);
|
|
171
|
+
parts.push(report.contextRefreshed ? 'context refreshed' : 'context unchanged');
|
|
172
|
+
result = {
|
|
173
|
+
status: report.conflictCount > 0 || report.errorCount > 0 ? 'error' : 'success',
|
|
174
|
+
message: parts.join(', '),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const report = await refreshWorkspace(job.workspacePath);
|
|
179
|
+
result = {
|
|
180
|
+
status: 'success',
|
|
181
|
+
message: `${report.analyzedRepos.length} repo(s) re-analyzed, ${report.reusedRepos.length} reused from cache`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
result = {
|
|
187
|
+
status: 'error',
|
|
188
|
+
message: error instanceof Error ? error.message : String(error),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// Record the run. Re-load the store so concurrent CLI edits are not lost.
|
|
192
|
+
try {
|
|
193
|
+
const store = await loadSchedules();
|
|
194
|
+
const stored = store.jobs.find((j) => j.id === job.id);
|
|
195
|
+
if (stored) {
|
|
196
|
+
stored.lastRunAt = new Date().toISOString();
|
|
197
|
+
stored.lastStatus = result.status;
|
|
198
|
+
stored.lastMessage = result.message;
|
|
199
|
+
await saveSchedules(store);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Best-effort bookkeeping; the job itself already ran.
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Starts the scheduler loop inside the current process. Every tick it
|
|
209
|
+
* re-loads the schedules file (so jobs added/removed via CLI are picked up
|
|
210
|
+
* without a restart) and runs all due jobs sequentially. Ticks never overlap.
|
|
211
|
+
*
|
|
212
|
+
* @param options - Tick interval (default 60s) and an optional log sink.
|
|
213
|
+
* @returns A stop function that clears the interval.
|
|
214
|
+
*/
|
|
215
|
+
export function startScheduler(options = {}) {
|
|
216
|
+
const tickMs = options.tickMs ?? 60_000;
|
|
217
|
+
const log = options.log ?? (() => { });
|
|
218
|
+
let running = false;
|
|
219
|
+
const tick = async () => {
|
|
220
|
+
if (running)
|
|
221
|
+
return;
|
|
222
|
+
running = true;
|
|
223
|
+
try {
|
|
224
|
+
const store = await loadSchedules();
|
|
225
|
+
for (const job of store.jobs) {
|
|
226
|
+
if (!isDue(job))
|
|
227
|
+
continue;
|
|
228
|
+
log(`Running scheduled ${job.task} for ${path.basename(job.workspacePath)} (${job.id})...`);
|
|
229
|
+
const result = await runJob(job);
|
|
230
|
+
log(`Scheduled ${job.task} ${result.status === 'success' ? 'completed' : 'failed'}: ${result.message}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// A broken schedules file must not kill the host process's timer.
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
running = false;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
const timer = setInterval(tick, tickMs);
|
|
241
|
+
// Don't let the scheduler keep a short-lived CLI process alive.
|
|
242
|
+
timer.unref?.();
|
|
243
|
+
// First tick runs immediately so overdue jobs don't wait a full interval.
|
|
244
|
+
void tick();
|
|
245
|
+
return () => clearInterval(timer);
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.test.d.ts","sourceRoot":"","sources":["../../src/core/scheduler.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import { addSchedule, formatInterval, isDue, loadSchedules, nextDueAt, parseInterval, removeSchedule, setScheduleEnabled, } from './scheduler.js';
|
|
4
|
+
vi.mock('node:fs/promises');
|
|
5
|
+
/** Parses the JSON written by the most recent writeFile call. */
|
|
6
|
+
function lastWritten() {
|
|
7
|
+
const calls = vi.mocked(fs.writeFile).mock.calls;
|
|
8
|
+
const data = calls[calls.length - 1][1];
|
|
9
|
+
return JSON.parse(data);
|
|
10
|
+
}
|
|
11
|
+
function makeJob(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
id: 'sync-ws-abc',
|
|
14
|
+
workspacePath: '/ws',
|
|
15
|
+
task: 'sync',
|
|
16
|
+
intervalMinutes: 60,
|
|
17
|
+
enabled: true,
|
|
18
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
19
|
+
...overrides,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
describe('scheduler', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.clearAllMocks();
|
|
25
|
+
vi.mocked(fs.writeFile).mockResolvedValue(undefined);
|
|
26
|
+
vi.mocked(fs.mkdir).mockResolvedValue(undefined);
|
|
27
|
+
});
|
|
28
|
+
describe('parseInterval', () => {
|
|
29
|
+
it('parses minutes, hours, days, and bare numbers', () => {
|
|
30
|
+
expect(parseInterval('30m')).toBe(30);
|
|
31
|
+
expect(parseInterval('2h')).toBe(120);
|
|
32
|
+
expect(parseInterval('1d')).toBe(1440);
|
|
33
|
+
expect(parseInterval('45')).toBe(45);
|
|
34
|
+
});
|
|
35
|
+
it('rejects invalid or non-positive input', () => {
|
|
36
|
+
expect(parseInterval('')).toBeNull();
|
|
37
|
+
expect(parseInterval('abc')).toBeNull();
|
|
38
|
+
expect(parseInterval('0m')).toBeNull();
|
|
39
|
+
expect(parseInterval('-5m')).toBeNull();
|
|
40
|
+
expect(parseInterval('2w')).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('formatInterval', () => {
|
|
44
|
+
it('formats back to compact strings', () => {
|
|
45
|
+
expect(formatInterval(30)).toBe('30m');
|
|
46
|
+
expect(formatInterval(120)).toBe('2h');
|
|
47
|
+
expect(formatInterval(1440)).toBe('1d');
|
|
48
|
+
expect(formatInterval(90)).toBe('90m');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('isDue', () => {
|
|
52
|
+
it('is due when it has never run', () => {
|
|
53
|
+
expect(isDue(makeJob())).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
it('is not due when disabled, even if never run', () => {
|
|
56
|
+
expect(isDue(makeJob({ enabled: false }))).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it('respects the interval since the last run', () => {
|
|
59
|
+
const now = new Date('2026-01-02T12:00:00.000Z');
|
|
60
|
+
const recent = makeJob({ lastRunAt: '2026-01-02T11:30:00.000Z' }); // 30m ago, every 60m
|
|
61
|
+
const stale = makeJob({ lastRunAt: '2026-01-02T10:00:00.000Z' }); // 2h ago, every 60m
|
|
62
|
+
expect(isDue(recent, now)).toBe(false);
|
|
63
|
+
expect(isDue(stale, now)).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it('treats an unparseable lastRunAt as due', () => {
|
|
66
|
+
expect(isDue(makeJob({ lastRunAt: 'garbage' }))).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('nextDueAt', () => {
|
|
70
|
+
it('is null for disabled jobs', () => {
|
|
71
|
+
expect(nextDueAt(makeJob({ enabled: false }))).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
it('is lastRunAt + interval for jobs that ran', () => {
|
|
74
|
+
const job = makeJob({ lastRunAt: '2026-01-02T10:00:00.000Z' });
|
|
75
|
+
expect(nextDueAt(job).toISOString()).toBe('2026-01-02T11:00:00.000Z');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('store operations', () => {
|
|
79
|
+
it('loadSchedules returns an empty store when the file is absent', async () => {
|
|
80
|
+
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT'));
|
|
81
|
+
const store = await loadSchedules();
|
|
82
|
+
expect(store.jobs).toEqual([]);
|
|
83
|
+
});
|
|
84
|
+
it('addSchedule persists a new enabled job', async () => {
|
|
85
|
+
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT'));
|
|
86
|
+
const job = await addSchedule({ workspacePath: '/ws/feature-x', task: 'refresh', intervalMinutes: 120 });
|
|
87
|
+
expect(job.enabled).toBe(true);
|
|
88
|
+
expect(job.task).toBe('refresh');
|
|
89
|
+
expect(job.id).toContain('refresh-feature-x');
|
|
90
|
+
const written = lastWritten();
|
|
91
|
+
expect(written.jobs).toHaveLength(1);
|
|
92
|
+
expect(written.jobs[0].intervalMinutes).toBe(120);
|
|
93
|
+
});
|
|
94
|
+
it('removeSchedule deletes by id and reports misses', async () => {
|
|
95
|
+
const existing = { version: 1, jobs: [makeJob()] };
|
|
96
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(existing));
|
|
97
|
+
expect(await removeSchedule('sync-ws-abc')).toBe(true);
|
|
98
|
+
expect(lastWritten().jobs).toHaveLength(0);
|
|
99
|
+
expect(await removeSchedule('nope')).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
it('setScheduleEnabled toggles and persists', async () => {
|
|
102
|
+
const existing = { version: 1, jobs: [makeJob()] };
|
|
103
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(existing));
|
|
104
|
+
const job = await setScheduleEnabled('sync-ws-abc', false);
|
|
105
|
+
expect(job.enabled).toBe(false);
|
|
106
|
+
expect(lastWritten().jobs[0].enabled).toBe(false);
|
|
107
|
+
expect(await setScheduleEnabled('nope', true)).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=scheduler.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.test.js","sourceRoot":"","sources":["../../src/core/scheduler.test.ts"],"names":[],"mappings":"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"}
|
package/dist/core/sync.d.ts
CHANGED
|
@@ -10,12 +10,16 @@ import type { SyncStatus } from '../types.js';
|
|
|
10
10
|
export interface RepoSyncReport {
|
|
11
11
|
/** Directory name of the repo. */
|
|
12
12
|
name: string;
|
|
13
|
+
/** Base branch the repo rebases onto (e.g. 'main'). */
|
|
14
|
+
baseBranch: string;
|
|
13
15
|
/** Classified outcome. */
|
|
14
16
|
status: SyncStatus;
|
|
15
17
|
/** Human-readable message. */
|
|
16
18
|
message: string;
|
|
17
19
|
/** Conflict stderr — populated only for `status === 'conflict'`. */
|
|
18
20
|
conflict?: string;
|
|
21
|
+
/** Paths that had merge conflicts — populated only for `status === 'conflict'`. */
|
|
22
|
+
conflictFiles?: string[];
|
|
19
23
|
}
|
|
20
24
|
/** Aggregated result of syncing an entire workspace. */
|
|
21
25
|
export interface SyncReport {
|
|
@@ -31,6 +35,8 @@ export interface SyncReport {
|
|
|
31
35
|
conflictCount: number;
|
|
32
36
|
/** Count of repos that failed for infrastructure reasons (fetch/auth, etc.). */
|
|
33
37
|
errorCount: number;
|
|
38
|
+
/** Whether context files/maps were regenerated (only when content changed). */
|
|
39
|
+
contextRefreshed: boolean;
|
|
34
40
|
}
|
|
35
41
|
/**
|
|
36
42
|
* Syncs all repos in a workspace. Throws if the workspace configuration cannot
|
package/dist/core/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,aAAa,CAAC;AAEhE,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,aAAa,CAAC;AAEhE,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAOD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA0E9E"}
|
package/dist/core/sync.js
CHANGED
|
@@ -9,7 +9,7 @@ import * as path from 'node:path';
|
|
|
9
9
|
import { loadFeatureConfig } from './workspace.js';
|
|
10
10
|
import { recordRepoSync } from './workspace-state.js';
|
|
11
11
|
import { getWorkspaceRepos, rebaseRepo } from '../utils/multi-git.js';
|
|
12
|
-
import {
|
|
12
|
+
import { analyzeAllReposCached } from '../analyzers/index.js';
|
|
13
13
|
import { generateContextFiles } from '../generators/index.js';
|
|
14
14
|
/** A sync status counts as "synced" when the rebase itself landed. */
|
|
15
15
|
function isSynced(status) {
|
|
@@ -42,9 +42,11 @@ export async function syncWorkspace(workspacePath) {
|
|
|
42
42
|
});
|
|
43
43
|
repoReports.push({
|
|
44
44
|
name: repo.name,
|
|
45
|
+
baseBranch: defaultBranch,
|
|
45
46
|
status: result.status,
|
|
46
47
|
message: result.message,
|
|
47
48
|
conflict: result.conflict,
|
|
49
|
+
conflictFiles: result.conflictFiles,
|
|
48
50
|
});
|
|
49
51
|
if (isSynced(result.status))
|
|
50
52
|
syncedCount++;
|
|
@@ -53,18 +55,25 @@ export async function syncWorkspace(workspacePath) {
|
|
|
53
55
|
else
|
|
54
56
|
errorCount++;
|
|
55
57
|
}
|
|
56
|
-
// Regenerate maps/context when
|
|
58
|
+
// Regenerate maps/context only when a rebase actually changed repo content
|
|
59
|
+
// ('rebased' or 'stash-conflict'). When every repo was already up to date,
|
|
60
|
+
// skipping regeneration keeps context files byte-identical — no wasted
|
|
61
|
+
// analysis and no invalidated AI prompt caches. The cached analyzer then
|
|
62
|
+
// limits the work to the repos that changed. A regen failure must never
|
|
57
63
|
// fail the sync itself — the rebases already happened.
|
|
58
|
-
|
|
64
|
+
const contentChanged = repoReports.some((r) => r.status === 'rebased' || r.status === 'stash-conflict');
|
|
65
|
+
let contextRefreshed = false;
|
|
66
|
+
if (contentChanged) {
|
|
59
67
|
try {
|
|
60
68
|
const allRepos = feature.repos.map((r) => ({
|
|
61
69
|
name: path.basename(r),
|
|
62
70
|
path: r,
|
|
63
71
|
defaultBranch: 'main',
|
|
64
72
|
}));
|
|
65
|
-
const analysis = await
|
|
73
|
+
const { analysis, analyzed } = await analyzeAllReposCached(allRepos, workspacePath);
|
|
66
74
|
const ctx = { feature, repos: allRepos, analysis };
|
|
67
|
-
await generateContextFiles(ctx, feature.assistants, workspacePath);
|
|
75
|
+
await generateContextFiles(ctx, feature.assistants, workspacePath, undefined, undefined, analyzed);
|
|
76
|
+
contextRefreshed = true;
|
|
68
77
|
}
|
|
69
78
|
catch {
|
|
70
79
|
// Best-effort regeneration; ignore failures.
|
|
@@ -77,6 +86,7 @@ export async function syncWorkspace(workspacePath) {
|
|
|
77
86
|
syncedCount,
|
|
78
87
|
conflictCount,
|
|
79
88
|
errorCount,
|
|
89
|
+
contextRefreshed,
|
|
80
90
|
};
|
|
81
91
|
}
|
|
82
92
|
//# sourceMappingURL=sync.js.map
|
package/dist/core/sync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,8 +10,14 @@ import type { AIAssistant, WorkspaceContext } from '../types.js';
|
|
|
10
10
|
* @param ctx - The workspace context (feature + repos).
|
|
11
11
|
* @param assistants - Which AI assistants to generate context files for.
|
|
12
12
|
* @param workspacePath - Absolute path to the workspace root directory.
|
|
13
|
+
* @param onlyRepo - Restrict per-repo output to a single repo by name.
|
|
14
|
+
* @param onlyBase - Only generate base-layer maps/knowledge.
|
|
15
|
+
* @param changedRepos - When provided, per-repo architecture maps are only
|
|
16
|
+
* rewritten for these repos (unchanged repos keep their
|
|
17
|
+
* existing map byte-identical, preserving AI prompt
|
|
18
|
+
* caches). A missing map file is generated regardless.
|
|
13
19
|
*/
|
|
14
|
-
export declare function generateContextFiles(ctx: WorkspaceContext, assistants: AIAssistant[], workspacePath: string, onlyRepo?: string, onlyBase?: boolean): Promise<void>;
|
|
20
|
+
export declare function generateContextFiles(ctx: WorkspaceContext, assistants: AIAssistant[], workspacePath: string, onlyRepo?: string, onlyBase?: boolean, changedRepos?: string[]): Promise<void>;
|
|
15
21
|
export { generateClaudeConfig } from './claude.js';
|
|
16
22
|
export { generateAntigravityConfig } from './antigravity.js';
|
|
17
23
|
export { generateCodexConfig } from './codex.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmIjE
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmIjE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,gBAAgB,EACrB,UAAU,EAAE,WAAW,EAAE,EACzB,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,OAAO,EAClB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAuKf;AAGD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/generators/index.js
CHANGED
|
@@ -127,8 +127,14 @@ function buildBaseKnowledgeContent(repoName) {
|
|
|
127
127
|
* @param ctx - The workspace context (feature + repos).
|
|
128
128
|
* @param assistants - Which AI assistants to generate context files for.
|
|
129
129
|
* @param workspacePath - Absolute path to the workspace root directory.
|
|
130
|
+
* @param onlyRepo - Restrict per-repo output to a single repo by name.
|
|
131
|
+
* @param onlyBase - Only generate base-layer maps/knowledge.
|
|
132
|
+
* @param changedRepos - When provided, per-repo architecture maps are only
|
|
133
|
+
* rewritten for these repos (unchanged repos keep their
|
|
134
|
+
* existing map byte-identical, preserving AI prompt
|
|
135
|
+
* caches). A missing map file is generated regardless.
|
|
130
136
|
*/
|
|
131
|
-
export async function generateContextFiles(ctx, assistants, workspacePath, onlyRepo, onlyBase) {
|
|
137
|
+
export async function generateContextFiles(ctx, assistants, workspacePath, onlyRepo, onlyBase, changedRepos) {
|
|
132
138
|
// Always generate a universal WORKSPACE.md at the workspace root
|
|
133
139
|
if (!onlyBase) {
|
|
134
140
|
try {
|
|
@@ -195,6 +201,13 @@ export async function generateContextFiles(ctx, assistants, workspacePath, onlyR
|
|
|
195
201
|
}
|
|
196
202
|
const a = ctx.analysis.get(repo.path);
|
|
197
203
|
if (a) {
|
|
204
|
+
if (changedRepos && !changedRepos.includes(repo.name)) {
|
|
205
|
+
const mapExists = await baseFileExists(workspacePath, repo.name, `nexusflow-map-${repo.name}.md`);
|
|
206
|
+
if (mapExists) {
|
|
207
|
+
console.log(chalk.gray(' ○'), `Architecture Map for ${repo.name} unchanged — skipped (cache hit)`);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
198
211
|
try {
|
|
199
212
|
const { generateRepoMap } = await import('./map-generator.js');
|
|
200
213
|
await generateRepoMap(repo, a, workspacePath, allProduced);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"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"}
|