@vortex-os/base 0.7.0 → 0.7.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/LICENSE +21 -21
- package/README.md +1 -1
- package/bin/vortex.mjs +17 -17
- package/dist/{catch-up-GDDKPZHJ.js → catch-up-KIHTAUPX.js} +2 -2
- package/dist/{chunk-3L5DLEGP.js → chunk-7SNLVGBO.js} +1 -1
- package/dist/chunk-7SNLVGBO.js.map +1 -0
- package/dist/index.d.ts +25 -4
- package/dist/index.js +122 -26
- package/dist/index.js.map +1 -1
- package/dist/{vectorize-PN4Y7XMO.js → vectorize-RBDBTSTW.js} +1 -1
- package/dist/vectorize-RBDBTSTW.js.map +1 -0
- package/package.json +1 -1
- package/templates/commands/agenda.md +15 -15
- package/templates/commands/resume.md +52 -52
- package/templates/config/vortex.json +13 -13
- package/templates/manifest.json +2 -2
- package/templates/routers/.cursorrules +14 -14
- package/templates/routers/AGENTS.md +27 -27
- package/templates/routers/CLAUDE.md +39 -39
- package/templates/routers/GEMINI.md +16 -16
- package/dist/chunk-3L5DLEGP.js.map +0 -1
- package/dist/vectorize-PN4Y7XMO.js.map +0 -1
- /package/dist/{catch-up-GDDKPZHJ.js.map → catch-up-KIHTAUPX.js.map} +0 -0
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 vortex-os-project
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vortex-os-project
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ npx vortex init # scaffold the instance
|
|
|
40
40
|
|
|
41
41
|
- the per-agent files — `AGENTS.md` (the thin Codex-CLI entry, auto-loaded by Codex and other `AGENTS.md`-aware tools) plus thin routers `CLAUDE.md`, `GEMINI.md`, `.cursorrules`, all pointing at `AI-RULES.md` (the single source of truth for shared rules) — so any agent host finds VortEX's behavior contract (these are generic templates you personalize over time);
|
|
42
42
|
- the `data/` skeleton (`_memory/`, `worklog/`, `decision-log/`, `runbooks/`, `hubs/`, `inbox/`), your user-profile memory, and today's first worklog;
|
|
43
|
-
- `.claude/settings.json` with the session hooks wired as `npx --no-install
|
|
43
|
+
- `.claude/settings.json` with the session hooks wired as `npx --no-install vortex session-start` / `… session-end` (the `--no-install` flag makes the auto-firing hook fail closed rather than install on a cache miss; resolving the bare `vortex` bin — local `node_modules/.bin` first, then PATH — lets the `global-setup` hook fire from any folder, not only where a local install exists), plus the agent-mediated slash-commands in `.claude/commands/`;
|
|
44
44
|
- `.agent/vortex.json` (auto-record config) and a minimal `package.json` with `"type":"module"` if none exists.
|
|
45
45
|
|
|
46
46
|
`vortex import --from <folder>` brings an existing notes folder in — markdown is auto-classified (worklog / decision-log / …) and **attachments (PDFs, images, …) are copied byte-for-byte** into the same layout; credential files (`*.key`, `.env`, `secrets/` …) and oversized files are skipped and reported. As the framework improves, `vortex update` refreshes the installed templates **without ever overwriting a file you edited** (your edit is parked at `<file>.new`); `vortex doctor` checks instance health.
|
package/bin/vortex.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// `vortex` — the CLI shipped by @vortex-os/base.
|
|
3
|
-
//
|
|
4
|
-
// `npm i @vortex-os/base` puts this on the instance's path (node_modules/.bin),
|
|
5
|
-
// so `npx vortex init` / `npx vortex session-start` / `npx vortex --list` work
|
|
6
|
-
// without any monorepo checkout. It is a thin wrapper over the canonical
|
|
7
|
-
// dispatch (`runVortexCli`), which is bundled into base from
|
|
8
|
-
// `@vortex-os/session-rituals` — exactly one source of truth for the CLI logic.
|
|
9
|
-
//
|
|
10
|
-
// The dispatch lazily probes the optional `@vortex-os/memory-extended` add-on:
|
|
11
|
-
// when it is installed alongside base, `/recall` lights up; on a lean base-only
|
|
12
|
-
// install the probe is caught and the CLI runs with every other command.
|
|
13
|
-
|
|
14
|
-
import { sessionRituals } from "../dist/index.js";
|
|
15
|
-
|
|
16
|
-
const code = await sessionRituals.runVortexCli(process.argv.slice(2));
|
|
17
|
-
process.exitCode = code;
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `vortex` — the CLI shipped by @vortex-os/base.
|
|
3
|
+
//
|
|
4
|
+
// `npm i @vortex-os/base` puts this on the instance's path (node_modules/.bin),
|
|
5
|
+
// so `npx vortex init` / `npx vortex session-start` / `npx vortex --list` work
|
|
6
|
+
// without any monorepo checkout. It is a thin wrapper over the canonical
|
|
7
|
+
// dispatch (`runVortexCli`), which is bundled into base from
|
|
8
|
+
// `@vortex-os/session-rituals` — exactly one source of truth for the CLI logic.
|
|
9
|
+
//
|
|
10
|
+
// The dispatch lazily probes the optional `@vortex-os/memory-extended` add-on:
|
|
11
|
+
// when it is installed alongside base, `/recall` lights up; on a lean base-only
|
|
12
|
+
// install the probe is caught and the CLI runs with every other command.
|
|
13
|
+
|
|
14
|
+
import { sessionRituals } from "../dist/index.js";
|
|
15
|
+
|
|
16
|
+
const code = await sessionRituals.runVortexCli(process.argv.slice(2));
|
|
17
|
+
process.exitCode = code;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../plugins/session-rituals/src/catch-up.ts"],"sourcesContent":["import type { ModuleContext } from \"@vortex-os/core\";\r\n// Type-only — erased at compile time, so importing it does NOT pull the\r\n// `@vortex-os/memory-extended` add-on (or its native sqlite/level deps) into\r\n// the module graph of consumers that only need the types. The runtime engine\r\n// is loaded lazily inside the function body via `await import(...)`.\r\nimport type { sessionArchive } from \"@vortex-os/memory-extended\";\r\n\r\n/**\r\n * Start-of-session \"catch-up\": fold conversation transcripts into the local\r\n * search archive without the user ever having to wrap up a session.\r\n *\r\n * Two sources, one pass:\r\n * - **local (a)** — this machine's own transcripts that are not archived yet,\r\n * read from every detected agent host's transcript store (Claude Code,\r\n * Codex, Gemini) and scoped to the current project. Because all hosts are\r\n * swept on every start, a single Claude Code session-start also folds in the\r\n * Codex/Gemini sessions you ran in the same project, into one archive.\r\n * - **pulled (b)** — transcripts created on another machine that arrived as\r\n * normalized text via git sync. Their text is present but this machine's\r\n * DB (local, derived, gitignored) has never indexed them.\r\n *\r\n * Text only — vectorization is deferred to recall/rebuild so session start\r\n * stays fast. The whole step is gated by `autoRecord.archive` at the call site\r\n * and is best-effort: callers should treat a thrown archive backend (e.g. the\r\n * native sqlite module not built) as \"skip\", never as a fatal start error.\r\n */\r\nexport interface CatchUpResult {\r\n /** Local transcripts newly archived this run (source a). */\r\n readonly ingestedLocal: number;\r\n /** Normalized transcripts from another machine newly indexed (source b). */\r\n readonly indexedPulled: number;\r\n /** Per-session ingest errors (source a). */\r\n readonly errors: number;\r\n}\r\n\r\nexport interface CatchUpOptions {\r\n /** Restrict local ingest to one project's transcripts. Default: `ctx.repoRoot`. */\r\n readonly cwd?: string;\r\n /**\r\n * Transcript adapters for local ingest. Default: all CLI hosts — Claude Code,\r\n * Codex, and Gemini. Each adapter's `detect()` returns false when its host is\r\n * absent, so registering all three is ~free on a machine that only uses one.\r\n * (Claude Desktop is opt-in — it needs the `classic-level` dependency — so it\r\n * is not in the default set; a caller can add it.) Tests inject fakes (or a\r\n * sandbox `env.home`) so the scan never touches the real home directory.\r\n */\r\n readonly adapters?: sessionArchive.IngestParams[\"adapters\"];\r\n /** Adapter environment override (e.g. a sandbox HOME). Tests use this. */\r\n readonly env?: sessionArchive.IngestParams[\"env\"];\r\n}\r\n\r\nexport async function catchUpSessions(\r\n ctx: ModuleContext,\r\n opts?: CatchUpOptions,\r\n): Promise<CatchUpResult> {\r\n // Lazy-load the optional add-on. Base ships without `memory-extended`; this\r\n // import resolves only when the add-on is installed alongside it. The call\r\n // site already gates this step on `autoRecord.archive` and treats a thrown\r\n // backend as \"skip\", so a missing add-on surfaces as a normal load error\r\n // the caller can catch.\r\n const { sessionArchive } = await import(\"@vortex-os/memory-extended\");\r\n\r\n const dataDir = ctx.dataDir;\r\n const cwd = opts?.cwd ?? ctx.repoRoot;\r\n const adapters = opts?.adapters ?? [\r\n sessionArchive.claudeCodeAdapter,\r\n sessionArchive.codexAdapter,\r\n sessionArchive.geminiAdapter,\r\n ];\r\n\r\n // (a) Ingest this machine's not-yet-archived transcripts for the current\r\n // project. Writes the normalized copy into the archive (which git syncs) and\r\n // a local DB row. Text only — no vectorization here.\r\n const ingestResult = await sessionArchive.ingest({ adapters, dataDir, cwd, env: opts?.env });\r\n\r\n // (b) Index normalized transcripts that arrived from another machine via git\r\n // pull — their text is on disk but this machine's DB has no row yet.\r\n const store = new sessionArchive.SessionArchiveStore(dataDir);\r\n let indexedPulled = 0;\r\n try {\r\n indexedPulled = store.reindexFromNormalized().indexed;\r\n } finally {\r\n store.close();\r\n }\r\n\r\n return {\r\n ingestedLocal: ingestResult.sessionsIngested,\r\n indexedPulled,\r\n errors: ingestResult.errors.length,\r\n };\r\n}\r\n"],"mappings":";AAmDA,eAAsB,gBACpB,KACA,MAAqB;AAOrB,QAAM,EAAE,eAAc,IAAK,MAAM,OAAO,4BAA4B;AAEpE,QAAM,UAAU,IAAI;AACpB,QAAM,MAAM,MAAM,OAAO,IAAI;AAC7B,QAAM,WAAW,MAAM,YAAY;IACjC,eAAe;IACf,eAAe;IACf,eAAe;;AAMjB,QAAM,eAAe,MAAM,eAAe,OAAO,EAAE,UAAU,SAAS,KAAK,KAAK,MAAM,IAAG,CAAE;AAI3F,QAAM,QAAQ,IAAI,eAAe,oBAAoB,OAAO;AAC5D,MAAI,gBAAgB;AACpB,MAAI;AACF,oBAAgB,MAAM,sBAAqB,EAAG;EAChD;AACE,UAAM,MAAK;EACb;AAEA,SAAO;IACL,eAAe,aAAa;IAC5B;IACA,QAAQ,aAAa,OAAO;;AAEhC;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -131,6 +131,21 @@ interface AutoRecordConfig {
|
|
|
131
131
|
* `vectorize` is off, nothing runs regardless.
|
|
132
132
|
*/
|
|
133
133
|
readonly vectorizeAutoDownload: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Auto-commit framework bookkeeping. When `vortex update` refreshes
|
|
136
|
+
* framework-owned files it also rewrites the ownership manifest
|
|
137
|
+
* (`data/.vortex/ownership.json`); on its own that leaves an uncommitted
|
|
138
|
+
* "trail" that the next session reports as carried-over work, even though it
|
|
139
|
+
* is plumbing the user never touched. With this on, `vortex update` commits
|
|
140
|
+
* exactly the framework files it changed (the manifest + the templates it
|
|
141
|
+
* refreshed) — and nothing else in the working tree — so an update leaves a
|
|
142
|
+
* clean tree. Best-effort: a non-git folder, or any git failure, is a silent
|
|
143
|
+
* no-op (the command still succeeds). On by default; set `false` to keep the
|
|
144
|
+
* commit manual (e.g. you prefer to review and commit framework changes
|
|
145
|
+
* yourself). Conflicts (`<file>.new`) are never auto-committed — those still
|
|
146
|
+
* wait for you to merge.
|
|
147
|
+
*/
|
|
148
|
+
readonly commitFrameworkChanges: boolean;
|
|
134
149
|
}
|
|
135
150
|
/**
|
|
136
151
|
* One environment label plus the signal that selects it. Rules are evaluated
|
|
@@ -2653,7 +2668,7 @@ declare function detectInterruptedGitOp(repoRoot: string): string | null;
|
|
|
2653
2668
|
* null when there is nothing to report (clean tree / not a git repo). Exported
|
|
2654
2669
|
* for tests. (decision-log 2026-06-04-session-recovery-two-tier.)
|
|
2655
2670
|
*/
|
|
2656
|
-
declare function collectCarryover(repoRoot: string): {
|
|
2671
|
+
declare function collectCarryover(repoRoot: string, ignore?: (repoRelPosixPath: string) => boolean): {
|
|
2657
2672
|
uncommitted: number;
|
|
2658
2673
|
interrupted: string | null;
|
|
2659
2674
|
} | null;
|
|
@@ -2669,8 +2684,8 @@ declare function collectCarryover(repoRoot: string): {
|
|
|
2669
2684
|
* file read/write around them. Keeping them pure makes the merge unit-testable
|
|
2670
2685
|
* and the "writes only what's missing" guarantee verifiable.
|
|
2671
2686
|
*/
|
|
2672
|
-
declare const SESSION_START_COMMAND = "npx --no-install
|
|
2673
|
-
declare const SESSION_END_COMMAND = "npx --no-install
|
|
2687
|
+
declare const SESSION_START_COMMAND = "npx --no-install vortex session-start || exit 0";
|
|
2688
|
+
declare const SESSION_END_COMMAND = "npx --no-install vortex session-end || exit 0";
|
|
2674
2689
|
interface HookCommand {
|
|
2675
2690
|
readonly type: "command";
|
|
2676
2691
|
readonly command: string;
|
|
@@ -3084,8 +3099,14 @@ declare function detectWorklogGaps(commitDays: readonly string[], presentDates:
|
|
|
3084
3099
|
* non-empty line. Pure: the hook runs git; this turns its stdout into the
|
|
3085
3100
|
* Tier-1 carryover count. (`--porcelain` emits exactly one line per changed
|
|
3086
3101
|
* path, including untracked, so a line count is the change count.)
|
|
3102
|
+
*
|
|
3103
|
+
* `ignore`, when given, drops paths it returns true for from the count — used to
|
|
3104
|
+
* exclude framework-generated bookkeeping (the ownership manifest under
|
|
3105
|
+
* `data/.vortex/`), which is auto-maintained plumbing the user never edits, so
|
|
3106
|
+
* it must not be reported as carried-over WIP. A line whose path can't be parsed
|
|
3107
|
+
* is counted (fail toward surfacing, not hiding).
|
|
3087
3108
|
*/
|
|
3088
|
-
declare function countUncommitted(porcelain: string): number;
|
|
3109
|
+
declare function countUncommitted(porcelain: string, ignore?: (repoRelPosixPath: string) => boolean): number;
|
|
3089
3110
|
/**
|
|
3090
3111
|
* Render a session-start report as a compact markdown block for a host hook
|
|
3091
3112
|
* to inject as session context. A pull conflict and any worklog gaps are
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
catchUpSessions
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7SNLVGBO.js";
|
|
4
4
|
import {
|
|
5
5
|
__export
|
|
6
6
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -105,7 +105,7 @@ function moduleDir(ctx, moduleName) {
|
|
|
105
105
|
import { existsSync, readFileSync } from "fs";
|
|
106
106
|
import { join as join2 } from "path";
|
|
107
107
|
var DEFAULT_CONFIG = {
|
|
108
|
-
autoRecord: { sessionStart: true, worklog: true, decision: true, ambientRecall: true, archive: true, vectorize: true, vectorizeAutoDownload: true },
|
|
108
|
+
autoRecord: { sessionStart: true, worklog: true, decision: true, ambientRecall: true, archive: true, vectorize: true, vectorizeAutoDownload: true, commitFrameworkChanges: true },
|
|
109
109
|
updates: { check: "session" },
|
|
110
110
|
environments: []
|
|
111
111
|
};
|
|
@@ -147,11 +147,13 @@ function loadVortexConfig(ctx) {
|
|
|
147
147
|
const check = rawCheck === void 0 ? "session" : typeof rawCheck === "string" && rawCheck.trim().toLowerCase() === "session" ? "session" : "off";
|
|
148
148
|
const rawAuto = raw.autoRecord && typeof raw.autoRecord === "object" && !Array.isArray(raw.autoRecord) ? raw.autoRecord : {};
|
|
149
149
|
const vectorizeAutoDownload = rawAuto.vectorizeAutoDownload === void 0 ? true : rawAuto.vectorizeAutoDownload === true;
|
|
150
|
+
const commitFrameworkChanges = rawAuto.commitFrameworkChanges === void 0 ? true : rawAuto.commitFrameworkChanges === true;
|
|
150
151
|
return {
|
|
151
152
|
autoRecord: {
|
|
152
153
|
...DEFAULT_CONFIG.autoRecord,
|
|
153
154
|
...raw.autoRecord ?? {},
|
|
154
|
-
vectorizeAutoDownload
|
|
155
|
+
vectorizeAutoDownload,
|
|
156
|
+
commitFrameworkChanges
|
|
155
157
|
},
|
|
156
158
|
updates: { check },
|
|
157
159
|
environments
|
|
@@ -4778,11 +4780,17 @@ import { basename as basename7, dirname as dirname5, extname as extname11, join
|
|
|
4778
4780
|
import { fileURLToPath } from "url";
|
|
4779
4781
|
|
|
4780
4782
|
// ../plugins/session-rituals/dist/ensure-hooks.js
|
|
4781
|
-
var SESSION_START_COMMAND = "npx --no-install
|
|
4782
|
-
var SESSION_END_COMMAND = "npx --no-install
|
|
4783
|
+
var SESSION_START_COMMAND = "npx --no-install vortex session-start || exit 0";
|
|
4784
|
+
var SESSION_END_COMMAND = "npx --no-install vortex session-end || exit 0";
|
|
4783
4785
|
var LEGACY_COMMANDS = {
|
|
4784
|
-
SessionStart:
|
|
4785
|
-
|
|
4786
|
+
SessionStart: [
|
|
4787
|
+
"npx --no-install -p @vortex-os/base vortex session-start || exit 0",
|
|
4788
|
+
"npx --no-install -p @vortex-os/base vortex session-start"
|
|
4789
|
+
],
|
|
4790
|
+
SessionEnd: [
|
|
4791
|
+
"npx --no-install -p @vortex-os/base vortex session-end || exit 0",
|
|
4792
|
+
"npx --no-install -p @vortex-os/base vortex session-end"
|
|
4793
|
+
]
|
|
4786
4794
|
};
|
|
4787
4795
|
function parseSettings(text) {
|
|
4788
4796
|
const trimmed = (text ?? "").trim();
|
|
@@ -4812,7 +4820,7 @@ function ensureVortexHooks(existing) {
|
|
|
4812
4820
|
for (const g of src) {
|
|
4813
4821
|
const hookList = [];
|
|
4814
4822
|
for (const h of g.hooks ?? []) {
|
|
4815
|
-
const migrated = h.command
|
|
4823
|
+
const migrated = legacy.includes(h.command);
|
|
4816
4824
|
const cmd = migrated ? command : h.command;
|
|
4817
4825
|
if (cmd === command) {
|
|
4818
4826
|
if (kept) {
|
|
@@ -5005,6 +5013,21 @@ var MANIFEST_NAME = "manifest.json";
|
|
|
5005
5013
|
function ownershipManifestPath(ctx) {
|
|
5006
5014
|
return join24(ctx.dataDir, ".vortex", "ownership.json");
|
|
5007
5015
|
}
|
|
5016
|
+
function frameworkBookkeepingPrefix(ctx) {
|
|
5017
|
+
return toPosix(relative4(ctx.repoRoot, join24(ctx.dataDir, ".vortex"))) + "/";
|
|
5018
|
+
}
|
|
5019
|
+
function committableUpdatePaths(ctx, result) {
|
|
5020
|
+
const out = /* @__PURE__ */ new Set();
|
|
5021
|
+
for (const a of result.actions) {
|
|
5022
|
+
if (a.error)
|
|
5023
|
+
continue;
|
|
5024
|
+
if (a.action === "replace" || a.action === "restore" || a.action === "install" || a.action === "adopt") {
|
|
5025
|
+
out.add(a.path);
|
|
5026
|
+
}
|
|
5027
|
+
}
|
|
5028
|
+
out.add(toPosix(relative4(ctx.repoRoot, ownershipManifestPath(ctx))));
|
|
5029
|
+
return [...out];
|
|
5030
|
+
}
|
|
5008
5031
|
function toPosix(p) {
|
|
5009
5032
|
return p.split(sep4).join("/");
|
|
5010
5033
|
}
|
|
@@ -5030,6 +5053,8 @@ function templateDestRelPath(templateRelPath) {
|
|
|
5030
5053
|
const parts = templateRelPath.split("/");
|
|
5031
5054
|
if (parts.length < 2)
|
|
5032
5055
|
return null;
|
|
5056
|
+
if (parts.some((p) => p === ".." || p === "."))
|
|
5057
|
+
return null;
|
|
5033
5058
|
const [top, ...rest] = parts;
|
|
5034
5059
|
const tail = rest.join("/");
|
|
5035
5060
|
if (top === "routers")
|
|
@@ -5608,6 +5633,41 @@ function buildNextActions(status, summary, actions, dryRun, fromVersion, toVersi
|
|
|
5608
5633
|
return out;
|
|
5609
5634
|
}
|
|
5610
5635
|
|
|
5636
|
+
// ../plugins/session-rituals/dist/git-commit.js
|
|
5637
|
+
import { execFileSync } from "child_process";
|
|
5638
|
+
function git(repoRoot, args) {
|
|
5639
|
+
return execFileSync("git", [...args], {
|
|
5640
|
+
cwd: repoRoot,
|
|
5641
|
+
encoding: "utf8",
|
|
5642
|
+
// GIT_LITERAL_PATHSPECS=1 makes every `-- <path>` a LITERAL filename, not a
|
|
5643
|
+
// pathspec: it disables glob magic (`*` `?` `[…]`) and `:(…)` prefixes. So
|
|
5644
|
+
// even a path carrying those bytes (e.g. from a malformed template index)
|
|
5645
|
+
// can only ever match the exact file named — never a wider set.
|
|
5646
|
+
env: { ...process.env, GIT_LITERAL_PATHSPECS: "1" },
|
|
5647
|
+
// Suppress git's own stderr; the caller treats a non-zero exit as "no commit".
|
|
5648
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
5649
|
+
});
|
|
5650
|
+
}
|
|
5651
|
+
function commitFrameworkPaths(repoRoot, paths, message) {
|
|
5652
|
+
if (paths.length === 0)
|
|
5653
|
+
return { committed: false, reason: "no-paths" };
|
|
5654
|
+
try {
|
|
5655
|
+
git(repoRoot, ["rev-parse", "--git-dir"]);
|
|
5656
|
+
} catch {
|
|
5657
|
+
return { committed: false, reason: "not-a-git-repo" };
|
|
5658
|
+
}
|
|
5659
|
+
try {
|
|
5660
|
+
const status = git(repoRoot, ["status", "--porcelain", "--", ...paths]).trim();
|
|
5661
|
+
if (!status)
|
|
5662
|
+
return { committed: false, reason: "nothing-to-commit" };
|
|
5663
|
+
git(repoRoot, ["add", "--", ...paths]);
|
|
5664
|
+
git(repoRoot, ["commit", "-m", message, "--", ...paths]);
|
|
5665
|
+
return { committed: true };
|
|
5666
|
+
} catch (e) {
|
|
5667
|
+
return { committed: false, reason: "git-error", error: e?.message ?? String(e) };
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
|
|
5611
5671
|
// ../plugins/session-rituals/dist/commands/vortex.js
|
|
5612
5672
|
var PLANNED_SUBS = [];
|
|
5613
5673
|
var vortexCommand = {
|
|
@@ -6033,10 +6093,25 @@ async function runUpdate(input, tokens) {
|
|
|
6033
6093
|
const dryRun = tokens.includes("--dry-run");
|
|
6034
6094
|
const adopt = parseAdoptArgs(tokens);
|
|
6035
6095
|
const templatesDir = resolveTemplatesDir();
|
|
6036
|
-
|
|
6096
|
+
const result = await runTemplatesUpdate(input.context, templatesDir, {
|
|
6037
6097
|
dryRun,
|
|
6038
6098
|
adopt: adopt.size > 0 ? adopt : void 0
|
|
6039
6099
|
});
|
|
6100
|
+
if (dryRun || result.status === "no-manifest" || result.status === "no-templates")
|
|
6101
|
+
return result;
|
|
6102
|
+
if (!loadVortexConfig(input.context).autoRecord.commitFrameworkChanges)
|
|
6103
|
+
return result;
|
|
6104
|
+
const paths = committableUpdatePaths(input.context, result);
|
|
6105
|
+
const commit = commitFrameworkPaths(input.context.repoRoot, paths, `chore(vortex): sync framework templates to base ${result.toVersion ?? "?"}`);
|
|
6106
|
+
if (!commit.committed)
|
|
6107
|
+
return result;
|
|
6108
|
+
return {
|
|
6109
|
+
...result,
|
|
6110
|
+
nextActions: [
|
|
6111
|
+
...result.nextActions,
|
|
6112
|
+
`Committed the framework changes so nothing is left uncommitted (autoRecord.commitFrameworkChanges; set false to commit these yourself).`
|
|
6113
|
+
]
|
|
6114
|
+
};
|
|
6040
6115
|
}
|
|
6041
6116
|
function parseAdoptArgs(tokens) {
|
|
6042
6117
|
const adopt = /* @__PURE__ */ new Set();
|
|
@@ -7505,7 +7580,7 @@ function createRitualRegistry(options) {
|
|
|
7505
7580
|
}
|
|
7506
7581
|
|
|
7507
7582
|
// ../plugins/session-rituals/dist/cli-dispatch.js
|
|
7508
|
-
import { execFileSync, spawn as spawn2 } from "child_process";
|
|
7583
|
+
import { execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
|
|
7509
7584
|
import { existsSync as existsSync15, readFileSync as readFileSync4, mkdirSync, openSync, writeSync, closeSync, linkSync, rmSync, statSync } from "fs";
|
|
7510
7585
|
import { createRequire } from "module";
|
|
7511
7586
|
import { hostname } from "os";
|
|
@@ -7767,8 +7842,28 @@ function detectWorklogGaps(commitDays, presentDates) {
|
|
|
7767
7842
|
const present = new Set(presentDates);
|
|
7768
7843
|
return [...new Set(commitDays)].filter((d2) => d2 && !present.has(d2)).sort();
|
|
7769
7844
|
}
|
|
7770
|
-
function
|
|
7771
|
-
|
|
7845
|
+
function porcelainPath(line) {
|
|
7846
|
+
const body = line.slice(3);
|
|
7847
|
+
if (!body)
|
|
7848
|
+
return null;
|
|
7849
|
+
const arrow = body.indexOf(" -> ");
|
|
7850
|
+
const raw = (arrow >= 0 ? body.slice(arrow + 4) : body).trim();
|
|
7851
|
+
if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"'))
|
|
7852
|
+
return raw.slice(1, -1);
|
|
7853
|
+
return raw;
|
|
7854
|
+
}
|
|
7855
|
+
function countUncommitted(porcelain, ignore) {
|
|
7856
|
+
const lines = porcelain.split(/\r?\n/).filter((l3) => l3.trim().length > 0);
|
|
7857
|
+
if (!ignore)
|
|
7858
|
+
return lines.length;
|
|
7859
|
+
let n = 0;
|
|
7860
|
+
for (const l3 of lines) {
|
|
7861
|
+
const p = porcelainPath(l3);
|
|
7862
|
+
if (p && ignore(p))
|
|
7863
|
+
continue;
|
|
7864
|
+
n++;
|
|
7865
|
+
}
|
|
7866
|
+
return n;
|
|
7772
7867
|
}
|
|
7773
7868
|
function renderSessionStartReport(report, extras) {
|
|
7774
7869
|
const lines = [
|
|
@@ -7779,9 +7874,9 @@ function renderSessionStartReport(report, extras) {
|
|
|
7779
7874
|
];
|
|
7780
7875
|
const env = report.environment ? ` \xB7 env: ${envLabel(report.environment)}` : "";
|
|
7781
7876
|
lines.push(`- time: ${report.localTime ?? report.time}${env}`);
|
|
7782
|
-
const
|
|
7783
|
-
if (
|
|
7784
|
-
lines.push(
|
|
7877
|
+
const git2 = extras?.git;
|
|
7878
|
+
if (git2?.ran) {
|
|
7879
|
+
lines.push(git2.conflict ? `- git: \u26A0\uFE0F ${git2.summary} \u2014 resolve manually (not auto-resolved)` : `- git: ${git2.summary}`);
|
|
7785
7880
|
}
|
|
7786
7881
|
const countStr = COUNTED_DIRS2.map((d2) => `${d2} ${report.counts[d2] ?? 0}`).join(" \xB7 ");
|
|
7787
7882
|
const miss = report.missing.length ? ` (missing: ${report.missing.join(", ")})` : "";
|
|
@@ -8558,7 +8653,7 @@ async function runVectorizeSetup(repoRoot, out, err) {
|
|
|
8558
8653
|
return;
|
|
8559
8654
|
}
|
|
8560
8655
|
cleanTmp();
|
|
8561
|
-
const { vectorizeIndex } = await import("./vectorize-
|
|
8656
|
+
const { vectorizeIndex } = await import("./vectorize-RBDBTSTW.js");
|
|
8562
8657
|
const result = await vectorizeIndex(ctx, { dbPath: tmpDb, allowDownload: true });
|
|
8563
8658
|
const sqliteSpecifier = "better-sqlite3";
|
|
8564
8659
|
const mod = await import(sqliteSpecifier);
|
|
@@ -8599,16 +8694,16 @@ async function runSessionStart(repoRoot, out) {
|
|
|
8599
8694
|
if (!config.autoRecord.sessionStart)
|
|
8600
8695
|
return;
|
|
8601
8696
|
const environment = resolveSessionEnvironment(ctx, config);
|
|
8602
|
-
let
|
|
8697
|
+
let git2 = null;
|
|
8603
8698
|
try {
|
|
8604
8699
|
const remotes = gitOut(repoRoot, ["remote"]).trim();
|
|
8605
8700
|
if (remotes) {
|
|
8606
8701
|
try {
|
|
8607
8702
|
const pulled = gitOut(repoRoot, ["pull", "--ff-only"]);
|
|
8608
8703
|
const lastLine = pulled.trim().split(/\r?\n/).pop() || "up to date";
|
|
8609
|
-
|
|
8704
|
+
git2 = { ran: true, summary: lastLine, conflict: false };
|
|
8610
8705
|
} catch {
|
|
8611
|
-
|
|
8706
|
+
git2 = {
|
|
8612
8707
|
ran: true,
|
|
8613
8708
|
summary: "fast-forward pull failed (diverged or dirty tree)",
|
|
8614
8709
|
conflict: true
|
|
@@ -8617,7 +8712,8 @@ async function runSessionStart(repoRoot, out) {
|
|
|
8617
8712
|
}
|
|
8618
8713
|
} catch {
|
|
8619
8714
|
}
|
|
8620
|
-
const
|
|
8715
|
+
const bookkeepingPrefix = frameworkBookkeepingPrefix(ctx);
|
|
8716
|
+
const carryover = collectCarryover(repoRoot, (p) => p.startsWith(bookkeepingPrefix));
|
|
8621
8717
|
const report = await collectSessionStartReport(ctx, { environment });
|
|
8622
8718
|
let missingWorklogDays = [];
|
|
8623
8719
|
try {
|
|
@@ -8629,7 +8725,7 @@ async function runSessionStart(repoRoot, out) {
|
|
|
8629
8725
|
let catchUp = null;
|
|
8630
8726
|
if (config.autoRecord.archive) {
|
|
8631
8727
|
try {
|
|
8632
|
-
const { catchUpSessions: catchUpSessions2 } = await import("./catch-up-
|
|
8728
|
+
const { catchUpSessions: catchUpSessions2 } = await import("./catch-up-KIHTAUPX.js");
|
|
8633
8729
|
catchUp = await catchUpSessions2(ctx);
|
|
8634
8730
|
} catch {
|
|
8635
8731
|
}
|
|
@@ -8648,7 +8744,7 @@ async function runSessionStart(repoRoot, out) {
|
|
|
8648
8744
|
});
|
|
8649
8745
|
if (action === "inline") {
|
|
8650
8746
|
try {
|
|
8651
|
-
const { vectorizeIndex } = await import("./vectorize-
|
|
8747
|
+
const { vectorizeIndex } = await import("./vectorize-RBDBTSTW.js");
|
|
8652
8748
|
vectorized = await vectorizeIndex(ctx);
|
|
8653
8749
|
} catch {
|
|
8654
8750
|
}
|
|
@@ -8688,7 +8784,7 @@ async function runSessionStart(repoRoot, out) {
|
|
|
8688
8784
|
} catch {
|
|
8689
8785
|
}
|
|
8690
8786
|
out(renderSessionStartReport(report, {
|
|
8691
|
-
git,
|
|
8787
|
+
git: git2,
|
|
8692
8788
|
missingWorklogDays,
|
|
8693
8789
|
catchUp: catchUp ?? void 0,
|
|
8694
8790
|
vectorized: vectorized ?? void 0,
|
|
@@ -8712,7 +8808,7 @@ async function runSessionEnd(repoRoot, out) {
|
|
|
8712
8808
|
}
|
|
8713
8809
|
}
|
|
8714
8810
|
function gitOut(cwd, gitArgs) {
|
|
8715
|
-
return
|
|
8811
|
+
return execFileSync2("git", [...gitArgs], {
|
|
8716
8812
|
cwd,
|
|
8717
8813
|
encoding: "utf8",
|
|
8718
8814
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -8740,11 +8836,11 @@ function detectInterruptedGitOp(repoRoot) {
|
|
|
8740
8836
|
}
|
|
8741
8837
|
return null;
|
|
8742
8838
|
}
|
|
8743
|
-
function collectCarryover(repoRoot) {
|
|
8839
|
+
function collectCarryover(repoRoot, ignore) {
|
|
8744
8840
|
const interrupted = detectInterruptedGitOp(repoRoot);
|
|
8745
8841
|
let uncommitted = 0;
|
|
8746
8842
|
try {
|
|
8747
|
-
uncommitted = countUncommitted(gitOut(repoRoot, ["status", "--porcelain"]));
|
|
8843
|
+
uncommitted = countUncommitted(gitOut(repoRoot, ["status", "--porcelain"]), ignore);
|
|
8748
8844
|
} catch {
|
|
8749
8845
|
}
|
|
8750
8846
|
return uncommitted > 0 || interrupted ? { uncommitted, interrupted } : null;
|