qodewk 0.9.2 → 0.10.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/index.cjs +654 -219
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1157,8 +1157,8 @@ var require_command = __commonJS({
|
|
|
1157
1157
|
"use strict";
|
|
1158
1158
|
var EventEmitter2 = require("events").EventEmitter;
|
|
1159
1159
|
var childProcess = require("child_process");
|
|
1160
|
-
var
|
|
1161
|
-
var
|
|
1160
|
+
var path17 = require("path");
|
|
1161
|
+
var fs16 = require("fs");
|
|
1162
1162
|
var process3 = require("process");
|
|
1163
1163
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1164
1164
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2139,7 +2139,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2139
2139
|
* @param {string} subcommandName
|
|
2140
2140
|
*/
|
|
2141
2141
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2142
|
-
if (
|
|
2142
|
+
if (fs16.existsSync(executableFile)) return;
|
|
2143
2143
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2144
2144
|
const executableMissing = `'${executableFile}' does not exist
|
|
2145
2145
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2157,11 +2157,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2157
2157
|
let launchWithNode = false;
|
|
2158
2158
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2159
2159
|
function findFile(baseDir, baseName) {
|
|
2160
|
-
const localBin =
|
|
2161
|
-
if (
|
|
2162
|
-
if (sourceExt.includes(
|
|
2160
|
+
const localBin = path17.resolve(baseDir, baseName);
|
|
2161
|
+
if (fs16.existsSync(localBin)) return localBin;
|
|
2162
|
+
if (sourceExt.includes(path17.extname(baseName))) return void 0;
|
|
2163
2163
|
const foundExt = sourceExt.find(
|
|
2164
|
-
(ext) =>
|
|
2164
|
+
(ext) => fs16.existsSync(`${localBin}${ext}`)
|
|
2165
2165
|
);
|
|
2166
2166
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2167
2167
|
return void 0;
|
|
@@ -2173,21 +2173,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2173
2173
|
if (this._scriptPath) {
|
|
2174
2174
|
let resolvedScriptPath;
|
|
2175
2175
|
try {
|
|
2176
|
-
resolvedScriptPath =
|
|
2176
|
+
resolvedScriptPath = fs16.realpathSync(this._scriptPath);
|
|
2177
2177
|
} catch {
|
|
2178
2178
|
resolvedScriptPath = this._scriptPath;
|
|
2179
2179
|
}
|
|
2180
|
-
executableDir =
|
|
2181
|
-
|
|
2180
|
+
executableDir = path17.resolve(
|
|
2181
|
+
path17.dirname(resolvedScriptPath),
|
|
2182
2182
|
executableDir
|
|
2183
2183
|
);
|
|
2184
2184
|
}
|
|
2185
2185
|
if (executableDir) {
|
|
2186
2186
|
let localFile = findFile(executableDir, executableFile);
|
|
2187
2187
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2188
|
-
const legacyName =
|
|
2188
|
+
const legacyName = path17.basename(
|
|
2189
2189
|
this._scriptPath,
|
|
2190
|
-
|
|
2190
|
+
path17.extname(this._scriptPath)
|
|
2191
2191
|
);
|
|
2192
2192
|
if (legacyName !== this._name) {
|
|
2193
2193
|
localFile = findFile(
|
|
@@ -2198,7 +2198,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2198
2198
|
}
|
|
2199
2199
|
executableFile = localFile || executableFile;
|
|
2200
2200
|
}
|
|
2201
|
-
launchWithNode = sourceExt.includes(
|
|
2201
|
+
launchWithNode = sourceExt.includes(path17.extname(executableFile));
|
|
2202
2202
|
let proc;
|
|
2203
2203
|
if (process3.platform !== "win32") {
|
|
2204
2204
|
if (launchWithNode) {
|
|
@@ -3045,7 +3045,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3045
3045
|
* @return {Command}
|
|
3046
3046
|
*/
|
|
3047
3047
|
nameFromFilename(filename) {
|
|
3048
|
-
this._name =
|
|
3048
|
+
this._name = path17.basename(filename, path17.extname(filename));
|
|
3049
3049
|
return this;
|
|
3050
3050
|
}
|
|
3051
3051
|
/**
|
|
@@ -3059,9 +3059,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3059
3059
|
* @param {string} [path]
|
|
3060
3060
|
* @return {(string|null|Command)}
|
|
3061
3061
|
*/
|
|
3062
|
-
executableDir(
|
|
3063
|
-
if (
|
|
3064
|
-
this._executableDir =
|
|
3062
|
+
executableDir(path18) {
|
|
3063
|
+
if (path18 === void 0) return this._executableDir;
|
|
3064
|
+
this._executableDir = path18;
|
|
3065
3065
|
return this;
|
|
3066
3066
|
}
|
|
3067
3067
|
/**
|
|
@@ -4207,10 +4207,10 @@ var require_src2 = __commonJS({
|
|
|
4207
4207
|
var fs_1 = require("fs");
|
|
4208
4208
|
var debug_1 = __importDefault(require_src());
|
|
4209
4209
|
var log = debug_1.default("@kwsites/file-exists");
|
|
4210
|
-
function check(
|
|
4211
|
-
log(`checking %s`,
|
|
4210
|
+
function check(path17, isFile, isDirectory) {
|
|
4211
|
+
log(`checking %s`, path17);
|
|
4212
4212
|
try {
|
|
4213
|
-
const stat = fs_1.statSync(
|
|
4213
|
+
const stat = fs_1.statSync(path17);
|
|
4214
4214
|
if (stat.isFile() && isFile) {
|
|
4215
4215
|
log(`[OK] path represents a file`);
|
|
4216
4216
|
return true;
|
|
@@ -4230,8 +4230,8 @@ var require_src2 = __commonJS({
|
|
|
4230
4230
|
throw e;
|
|
4231
4231
|
}
|
|
4232
4232
|
}
|
|
4233
|
-
function exists2(
|
|
4234
|
-
return check(
|
|
4233
|
+
function exists2(path17, type = exports2.READABLE) {
|
|
4234
|
+
return check(path17, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
|
|
4235
4235
|
}
|
|
4236
4236
|
exports2.exists = exists2;
|
|
4237
4237
|
exports2.FILE = 1;
|
|
@@ -4842,8 +4842,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
4842
4842
|
function forEachLineWithContent(input, callback) {
|
|
4843
4843
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
4844
4844
|
}
|
|
4845
|
-
function folderExists(
|
|
4846
|
-
return (0, import_file_exists.exists)(
|
|
4845
|
+
function folderExists(path17) {
|
|
4846
|
+
return (0, import_file_exists.exists)(path17, import_file_exists.FOLDER);
|
|
4847
4847
|
}
|
|
4848
4848
|
function append(target, item) {
|
|
4849
4849
|
if (Array.isArray(target)) {
|
|
@@ -5034,8 +5034,8 @@ function checkIsRepoRootTask() {
|
|
|
5034
5034
|
commands,
|
|
5035
5035
|
format: "utf-8",
|
|
5036
5036
|
onError,
|
|
5037
|
-
parser(
|
|
5038
|
-
return /^\.(git)?$/.test(
|
|
5037
|
+
parser(path17) {
|
|
5038
|
+
return /^\.(git)?$/.test(path17.trim());
|
|
5039
5039
|
}
|
|
5040
5040
|
};
|
|
5041
5041
|
}
|
|
@@ -5291,11 +5291,11 @@ function parseGrep(grep) {
|
|
|
5291
5291
|
const paths = /* @__PURE__ */ new Set();
|
|
5292
5292
|
const results = {};
|
|
5293
5293
|
forEachLineWithContent(grep, (input) => {
|
|
5294
|
-
const [
|
|
5295
|
-
paths.add(
|
|
5296
|
-
(results[
|
|
5294
|
+
const [path17, line, preview] = input.split(NULL);
|
|
5295
|
+
paths.add(path17);
|
|
5296
|
+
(results[path17] = results[path17] || []).push({
|
|
5297
5297
|
line: asNumber(line),
|
|
5298
|
-
path:
|
|
5298
|
+
path: path17,
|
|
5299
5299
|
preview
|
|
5300
5300
|
});
|
|
5301
5301
|
});
|
|
@@ -5592,14 +5592,14 @@ function hashObjectTask(filePath, write) {
|
|
|
5592
5592
|
}
|
|
5593
5593
|
return straightThroughStringTask(commands, true);
|
|
5594
5594
|
}
|
|
5595
|
-
function parseInit(bare,
|
|
5595
|
+
function parseInit(bare, path17, text) {
|
|
5596
5596
|
const response = String(text).trim();
|
|
5597
5597
|
let result;
|
|
5598
5598
|
if (result = initResponseRegex.exec(response)) {
|
|
5599
|
-
return new InitSummary(bare,
|
|
5599
|
+
return new InitSummary(bare, path17, false, result[1]);
|
|
5600
5600
|
}
|
|
5601
5601
|
if (result = reInitResponseRegex.exec(response)) {
|
|
5602
|
-
return new InitSummary(bare,
|
|
5602
|
+
return new InitSummary(bare, path17, true, result[1]);
|
|
5603
5603
|
}
|
|
5604
5604
|
let gitDir = "";
|
|
5605
5605
|
const tokens = response.split(" ");
|
|
@@ -5610,12 +5610,12 @@ function parseInit(bare, path16, text) {
|
|
|
5610
5610
|
break;
|
|
5611
5611
|
}
|
|
5612
5612
|
}
|
|
5613
|
-
return new InitSummary(bare,
|
|
5613
|
+
return new InitSummary(bare, path17, /^re/i.test(response), gitDir);
|
|
5614
5614
|
}
|
|
5615
5615
|
function hasBareCommand(command) {
|
|
5616
5616
|
return command.includes(bareCommand);
|
|
5617
5617
|
}
|
|
5618
|
-
function initTask(bare = false,
|
|
5618
|
+
function initTask(bare = false, path17, customArgs) {
|
|
5619
5619
|
const commands = ["init", ...customArgs];
|
|
5620
5620
|
if (bare && !hasBareCommand(commands)) {
|
|
5621
5621
|
commands.splice(1, 0, bareCommand);
|
|
@@ -5624,7 +5624,7 @@ function initTask(bare = false, path16, customArgs) {
|
|
|
5624
5624
|
commands,
|
|
5625
5625
|
format: "utf-8",
|
|
5626
5626
|
parser(text) {
|
|
5627
|
-
return parseInit(commands.includes("--bare"),
|
|
5627
|
+
return parseInit(commands.includes("--bare"), path17, text);
|
|
5628
5628
|
}
|
|
5629
5629
|
};
|
|
5630
5630
|
}
|
|
@@ -5903,14 +5903,14 @@ function splitLine(result, lineStr) {
|
|
|
5903
5903
|
default:
|
|
5904
5904
|
return;
|
|
5905
5905
|
}
|
|
5906
|
-
function data(index, workingDir,
|
|
5906
|
+
function data(index, workingDir, path17) {
|
|
5907
5907
|
const raw = `${index}${workingDir}`;
|
|
5908
5908
|
const handler = parsers6.get(raw);
|
|
5909
5909
|
if (handler) {
|
|
5910
|
-
handler(result,
|
|
5910
|
+
handler(result, path17);
|
|
5911
5911
|
}
|
|
5912
5912
|
if (raw !== "##" && raw !== "!!") {
|
|
5913
|
-
result.files.push(new FileStatusSummary(
|
|
5913
|
+
result.files.push(new FileStatusSummary(path17, index, workingDir));
|
|
5914
5914
|
}
|
|
5915
5915
|
}
|
|
5916
5916
|
}
|
|
@@ -6097,8 +6097,8 @@ function deleteBranchTask(branch, forceDelete = false) {
|
|
|
6097
6097
|
return task;
|
|
6098
6098
|
}
|
|
6099
6099
|
function toPath(input) {
|
|
6100
|
-
const
|
|
6101
|
-
return
|
|
6100
|
+
const path17 = input.trim().replace(/^["']|["']$/g, "");
|
|
6101
|
+
return path17 && (0, import_node_path.normalize)(path17);
|
|
6102
6102
|
}
|
|
6103
6103
|
function checkIgnoreTask(paths) {
|
|
6104
6104
|
return {
|
|
@@ -6237,8 +6237,8 @@ function stashListTask(opt = {}, customArgs) {
|
|
|
6237
6237
|
parser: parser4
|
|
6238
6238
|
};
|
|
6239
6239
|
}
|
|
6240
|
-
function addSubModuleTask(repo,
|
|
6241
|
-
return subModuleTask(["add", repo,
|
|
6240
|
+
function addSubModuleTask(repo, path17) {
|
|
6241
|
+
return subModuleTask(["add", repo, path17]);
|
|
6242
6242
|
}
|
|
6243
6243
|
function initSubModuleTask(customArgs) {
|
|
6244
6244
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -6646,12 +6646,12 @@ function gitP(...args) {
|
|
|
6646
6646
|
);
|
|
6647
6647
|
}
|
|
6648
6648
|
return chain.then(function() {
|
|
6649
|
-
return new Promise(function(
|
|
6649
|
+
return new Promise(function(resolve6, reject) {
|
|
6650
6650
|
const callback = (err, result) => {
|
|
6651
6651
|
if (err) {
|
|
6652
6652
|
return reject(toError(err));
|
|
6653
6653
|
}
|
|
6654
|
-
|
|
6654
|
+
resolve6(result);
|
|
6655
6655
|
};
|
|
6656
6656
|
args2.push(callback);
|
|
6657
6657
|
git2[fn].apply(git2, args2);
|
|
@@ -7570,9 +7570,9 @@ var init_esm = __esm({
|
|
|
7570
7570
|
"src/lib/responses/InitSummary.ts"() {
|
|
7571
7571
|
"use strict";
|
|
7572
7572
|
InitSummary = class {
|
|
7573
|
-
constructor(bare,
|
|
7573
|
+
constructor(bare, path17, existing, gitDir) {
|
|
7574
7574
|
this.bare = bare;
|
|
7575
|
-
this.path =
|
|
7575
|
+
this.path = path17;
|
|
7576
7576
|
this.existing = existing;
|
|
7577
7577
|
this.gitDir = gitDir;
|
|
7578
7578
|
}
|
|
@@ -8105,12 +8105,12 @@ var init_esm = __esm({
|
|
|
8105
8105
|
"use strict";
|
|
8106
8106
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
8107
8107
|
FileStatusSummary = class {
|
|
8108
|
-
constructor(
|
|
8109
|
-
this.path =
|
|
8108
|
+
constructor(path17, index, working_dir) {
|
|
8109
|
+
this.path = path17;
|
|
8110
8110
|
this.index = index;
|
|
8111
8111
|
this.working_dir = working_dir;
|
|
8112
8112
|
if (index === "R" || working_dir === "R") {
|
|
8113
|
-
const detail = fromPathRegex.exec(
|
|
8113
|
+
const detail = fromPathRegex.exec(path17) || [null, path17, path17];
|
|
8114
8114
|
this.from = detail[2] || "";
|
|
8115
8115
|
this.path = detail[1] || "";
|
|
8116
8116
|
}
|
|
@@ -8372,9 +8372,9 @@ var init_esm = __esm({
|
|
|
8372
8372
|
next
|
|
8373
8373
|
);
|
|
8374
8374
|
}
|
|
8375
|
-
hashObject(
|
|
8375
|
+
hashObject(path17, write) {
|
|
8376
8376
|
return this._runTask(
|
|
8377
|
-
hashObjectTask(
|
|
8377
|
+
hashObjectTask(path17, write === true),
|
|
8378
8378
|
trailingFunctionArgument(arguments)
|
|
8379
8379
|
);
|
|
8380
8380
|
}
|
|
@@ -9011,8 +9011,8 @@ var init_esm = __esm({
|
|
|
9011
9011
|
}
|
|
9012
9012
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
9013
9013
|
};
|
|
9014
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
9015
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
9014
|
+
Git2.prototype.submoduleAdd = function(repo, path17, then) {
|
|
9015
|
+
return this._runTask(addSubModuleTask2(repo, path17), trailingFunctionArgument2(arguments));
|
|
9016
9016
|
};
|
|
9017
9017
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
9018
9018
|
return this._runTask(
|
|
@@ -9318,8 +9318,8 @@ var init_esm = __esm({
|
|
|
9318
9318
|
});
|
|
9319
9319
|
|
|
9320
9320
|
// src/index.ts
|
|
9321
|
-
var
|
|
9322
|
-
var
|
|
9321
|
+
var fs15 = __toESM(require("fs"), 1);
|
|
9322
|
+
var path16 = __toESM(require("path"), 1);
|
|
9323
9323
|
|
|
9324
9324
|
// ../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
|
|
9325
9325
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -9339,7 +9339,7 @@ var {
|
|
|
9339
9339
|
} = import_index.default;
|
|
9340
9340
|
|
|
9341
9341
|
// src/index.ts
|
|
9342
|
-
var
|
|
9342
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
9343
9343
|
|
|
9344
9344
|
// ../core/dist/index.js
|
|
9345
9345
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
@@ -9822,8 +9822,8 @@ function getErrorMap() {
|
|
|
9822
9822
|
|
|
9823
9823
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
9824
9824
|
var makeIssue = (params) => {
|
|
9825
|
-
const { data, path:
|
|
9826
|
-
const fullPath = [...
|
|
9825
|
+
const { data, path: path17, errorMaps, issueData } = params;
|
|
9826
|
+
const fullPath = [...path17, ...issueData.path || []];
|
|
9827
9827
|
const fullIssue = {
|
|
9828
9828
|
...issueData,
|
|
9829
9829
|
path: fullPath
|
|
@@ -9939,11 +9939,11 @@ var errorUtil;
|
|
|
9939
9939
|
|
|
9940
9940
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
9941
9941
|
var ParseInputLazyPath = class {
|
|
9942
|
-
constructor(parent, value,
|
|
9942
|
+
constructor(parent, value, path17, key) {
|
|
9943
9943
|
this._cachedPath = [];
|
|
9944
9944
|
this.parent = parent;
|
|
9945
9945
|
this.data = value;
|
|
9946
|
-
this._path =
|
|
9946
|
+
this._path = path17;
|
|
9947
9947
|
this._key = key;
|
|
9948
9948
|
}
|
|
9949
9949
|
get path() {
|
|
@@ -14496,8 +14496,8 @@ function harvestAntigravityFootprints(repoPath, sinceDate) {
|
|
|
14496
14496
|
const DatabaseSync2 = getSqliteDatabase();
|
|
14497
14497
|
if (!DatabaseSync2)
|
|
14498
14498
|
return footprints;
|
|
14499
|
-
const
|
|
14500
|
-
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(
|
|
14499
|
+
const homedir12 = os3.homedir();
|
|
14500
|
+
const antigravityDir = process.env.ANTIGRAVITY_APP_DATA_DIR || path3.join(homedir12, ".gemini", "antigravity");
|
|
14501
14501
|
const dbPath = path3.join(antigravityDir, "conversation_summaries.db");
|
|
14502
14502
|
if (!fs2.existsSync(dbPath)) {
|
|
14503
14503
|
return footprints;
|
|
@@ -14599,8 +14599,8 @@ var path4 = __toESM(require("path"), 1);
|
|
|
14599
14599
|
var os4 = __toESM(require("os"), 1);
|
|
14600
14600
|
function harvestClaudeFootprints(repoPath, projectAlias, sinceDate) {
|
|
14601
14601
|
const footprints = [];
|
|
14602
|
-
const
|
|
14603
|
-
const claudeProjectsDir = path4.join(
|
|
14602
|
+
const homedir12 = os4.homedir();
|
|
14603
|
+
const claudeProjectsDir = path4.join(homedir12, ".claude", "projects");
|
|
14604
14604
|
if (!fs3.existsSync(claudeProjectsDir)) {
|
|
14605
14605
|
return footprints;
|
|
14606
14606
|
}
|
|
@@ -15175,9 +15175,9 @@ function resolveClineStorageDirs(customDir) {
|
|
|
15175
15175
|
if (process.env.ROO_STORAGE_DIR && fs7.existsSync(process.env.ROO_STORAGE_DIR)) {
|
|
15176
15176
|
dirs.push(process.env.ROO_STORAGE_DIR);
|
|
15177
15177
|
}
|
|
15178
|
-
const
|
|
15178
|
+
const homedir12 = os7.homedir();
|
|
15179
15179
|
if (process.platform === "win32") {
|
|
15180
|
-
const appData = process.env.APPDATA || path8.join(
|
|
15180
|
+
const appData = process.env.APPDATA || path8.join(homedir12, "AppData", "Roaming");
|
|
15181
15181
|
const ideRoots = ["Code", "Code - Insiders", "Cursor", "Windsurf"];
|
|
15182
15182
|
const extensionIds = [
|
|
15183
15183
|
"saoudrizwan.claude-dev",
|
|
@@ -15191,7 +15191,7 @@ function resolveClineStorageDirs(customDir) {
|
|
|
15191
15191
|
}
|
|
15192
15192
|
}
|
|
15193
15193
|
} else if (process.platform === "darwin") {
|
|
15194
|
-
const appSupport = path8.join(
|
|
15194
|
+
const appSupport = path8.join(homedir12, "Library", "Application Support");
|
|
15195
15195
|
const ideRoots = ["Code", "Code - Insiders", "Cursor", "Windsurf"];
|
|
15196
15196
|
const extensionIds = [
|
|
15197
15197
|
"saoudrizwan.claude-dev",
|
|
@@ -15205,7 +15205,7 @@ function resolveClineStorageDirs(customDir) {
|
|
|
15205
15205
|
}
|
|
15206
15206
|
}
|
|
15207
15207
|
} else {
|
|
15208
|
-
const configRoot = process.env.XDG_CONFIG_HOME || path8.join(
|
|
15208
|
+
const configRoot = process.env.XDG_CONFIG_HOME || path8.join(homedir12, ".config");
|
|
15209
15209
|
const ideRoots = ["Code", "Code - Insiders", "Cursor", "Windsurf"];
|
|
15210
15210
|
const extensionIds = [
|
|
15211
15211
|
"saoudrizwan.claude-dev",
|
|
@@ -16063,6 +16063,289 @@ function formatMarkdownReceipt(receipt, publicUrl) {
|
|
|
16063
16063
|
return lines.join("\n");
|
|
16064
16064
|
}
|
|
16065
16065
|
|
|
16066
|
+
// ../core/dist/doctor.js
|
|
16067
|
+
var fs12 = __toESM(require("fs"), 1);
|
|
16068
|
+
var path13 = __toESM(require("path"), 1);
|
|
16069
|
+
var os12 = __toESM(require("os"), 1);
|
|
16070
|
+
var import_node_child_process = require("child_process");
|
|
16071
|
+
var HOOK_MARKER_BEGIN = "# --- BEGIN QODEWK HOOK ---";
|
|
16072
|
+
function auditAgentEnvironments(repoPath = process.cwd()) {
|
|
16073
|
+
const homedir12 = os12.homedir();
|
|
16074
|
+
const results = [];
|
|
16075
|
+
const agEnv = process.env.ANTIGRAVITY_APP_DATA_DIR;
|
|
16076
|
+
const agHome = path13.join(homedir12, ".gemini", "antigravity");
|
|
16077
|
+
const agPath = agEnv && fs12.existsSync(agEnv) ? agEnv : fs12.existsSync(agHome) ? agHome : void 0;
|
|
16078
|
+
results.push({
|
|
16079
|
+
id: "antigravity",
|
|
16080
|
+
name: "Google Antigravity",
|
|
16081
|
+
status: agPath ? "active" : "not_detected",
|
|
16082
|
+
path: agPath,
|
|
16083
|
+
details: agPath ? "Antigravity brain telemetry detected" : "No active session brain found"
|
|
16084
|
+
});
|
|
16085
|
+
const claudeProjects = path13.join(homedir12, ".claude", "projects");
|
|
16086
|
+
const claudeExists = fs12.existsSync(claudeProjects);
|
|
16087
|
+
results.push({
|
|
16088
|
+
id: "claude",
|
|
16089
|
+
name: "Claude Code CLI",
|
|
16090
|
+
status: claudeExists ? "active" : "not_detected",
|
|
16091
|
+
path: claudeExists ? claudeProjects : void 0,
|
|
16092
|
+
details: claudeExists ? "Claude project session directory found" : "No ~/.claude/projects directory found"
|
|
16093
|
+
});
|
|
16094
|
+
let cursorPath;
|
|
16095
|
+
if (process.platform === "win32") {
|
|
16096
|
+
const c3 = path13.join(process.env.APPDATA || path13.join(homedir12, "AppData", "Roaming"), "Cursor", "User", "workspaceStorage");
|
|
16097
|
+
if (fs12.existsSync(c3))
|
|
16098
|
+
cursorPath = c3;
|
|
16099
|
+
} else if (process.platform === "darwin") {
|
|
16100
|
+
const c3 = path13.join(homedir12, "Library", "Application Support", "Cursor", "User", "workspaceStorage");
|
|
16101
|
+
if (fs12.existsSync(c3))
|
|
16102
|
+
cursorPath = c3;
|
|
16103
|
+
} else {
|
|
16104
|
+
const c3 = path13.join(homedir12, ".config", "Cursor", "User", "workspaceStorage");
|
|
16105
|
+
if (fs12.existsSync(c3))
|
|
16106
|
+
cursorPath = c3;
|
|
16107
|
+
}
|
|
16108
|
+
results.push({
|
|
16109
|
+
id: "cursor",
|
|
16110
|
+
name: "Cursor IDE",
|
|
16111
|
+
status: cursorPath ? "active" : "not_detected",
|
|
16112
|
+
path: cursorPath,
|
|
16113
|
+
details: cursorPath ? "Cursor workspace storage detected" : "Cursor IDE storage not detected"
|
|
16114
|
+
});
|
|
16115
|
+
let windsurfPath;
|
|
16116
|
+
if (process.platform === "win32") {
|
|
16117
|
+
const w = path13.join(process.env.APPDATA || path13.join(homedir12, "AppData", "Roaming"), "Windsurf", "User", "workspaceStorage");
|
|
16118
|
+
if (fs12.existsSync(w))
|
|
16119
|
+
windsurfPath = w;
|
|
16120
|
+
} else if (process.platform === "darwin") {
|
|
16121
|
+
const w = path13.join(homedir12, "Library", "Application Support", "Windsurf", "User", "workspaceStorage");
|
|
16122
|
+
if (fs12.existsSync(w))
|
|
16123
|
+
windsurfPath = w;
|
|
16124
|
+
} else {
|
|
16125
|
+
const w = path13.join(homedir12, ".config", "Windsurf", "User", "workspaceStorage");
|
|
16126
|
+
if (fs12.existsSync(w))
|
|
16127
|
+
windsurfPath = w;
|
|
16128
|
+
}
|
|
16129
|
+
results.push({
|
|
16130
|
+
id: "windsurf",
|
|
16131
|
+
name: "Windsurf IDE",
|
|
16132
|
+
status: windsurfPath ? "active" : "not_detected",
|
|
16133
|
+
path: windsurfPath,
|
|
16134
|
+
details: windsurfPath ? "Cascade session workspace storage detected" : "Windsurf IDE storage not detected"
|
|
16135
|
+
});
|
|
16136
|
+
let clinePath;
|
|
16137
|
+
const localCline = path13.join(repoPath, ".cline");
|
|
16138
|
+
const localRoo = path13.join(repoPath, ".roo");
|
|
16139
|
+
if (fs12.existsSync(localCline)) {
|
|
16140
|
+
clinePath = localCline;
|
|
16141
|
+
} else if (fs12.existsSync(localRoo)) {
|
|
16142
|
+
clinePath = localRoo;
|
|
16143
|
+
} else {
|
|
16144
|
+
const appData = process.platform === "win32" ? process.env.APPDATA || path13.join(homedir12, "AppData", "Roaming") : process.platform === "darwin" ? path13.join(homedir12, "Library", "Application Support") : path13.join(homedir12, ".config");
|
|
16145
|
+
const clineExt = path13.join(appData, "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "tasks");
|
|
16146
|
+
const rooExt = path13.join(appData, "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline", "tasks");
|
|
16147
|
+
if (fs12.existsSync(clineExt))
|
|
16148
|
+
clinePath = clineExt;
|
|
16149
|
+
else if (fs12.existsSync(rooExt))
|
|
16150
|
+
clinePath = rooExt;
|
|
16151
|
+
}
|
|
16152
|
+
results.push({
|
|
16153
|
+
id: "cline",
|
|
16154
|
+
name: "Cline / Roo Code",
|
|
16155
|
+
status: clinePath ? "active" : "not_detected",
|
|
16156
|
+
path: clinePath,
|
|
16157
|
+
details: clinePath ? "VS Code autonomous agent task storage detected" : "No active Cline or Roo Code tasks found"
|
|
16158
|
+
});
|
|
16159
|
+
const aiderPath = path13.join(repoPath, ".aider.chat.history.md");
|
|
16160
|
+
const aiderExists = fs12.existsSync(aiderPath);
|
|
16161
|
+
results.push({
|
|
16162
|
+
id: "aider",
|
|
16163
|
+
name: "Aider CLI",
|
|
16164
|
+
status: aiderExists ? "active" : "not_detected",
|
|
16165
|
+
path: aiderExists ? aiderPath : void 0,
|
|
16166
|
+
details: aiderExists ? "Repository pairing transcript found" : "No repo-local .aider.chat.history.md found"
|
|
16167
|
+
});
|
|
16168
|
+
const localOpenCode = path13.join(repoPath, ".opencode");
|
|
16169
|
+
const homeOpenCode = path13.join(homedir12, ".opencode", "sessions");
|
|
16170
|
+
const opencodePath = fs12.existsSync(localOpenCode) ? localOpenCode : fs12.existsSync(homeOpenCode) ? homeOpenCode : void 0;
|
|
16171
|
+
results.push({
|
|
16172
|
+
id: "opencode",
|
|
16173
|
+
name: "OpenCode CLI",
|
|
16174
|
+
status: opencodePath ? "active" : "not_detected",
|
|
16175
|
+
path: opencodePath,
|
|
16176
|
+
details: opencodePath ? "OpenCode session history detected" : "No OpenCode session files found"
|
|
16177
|
+
});
|
|
16178
|
+
return results;
|
|
16179
|
+
}
|
|
16180
|
+
function resolveHooksDir(cwd = process.cwd()) {
|
|
16181
|
+
const gitPath = path13.join(cwd, ".git");
|
|
16182
|
+
if (!fs12.existsSync(gitPath))
|
|
16183
|
+
return null;
|
|
16184
|
+
try {
|
|
16185
|
+
const stat = fs12.statSync(gitPath);
|
|
16186
|
+
if (stat.isDirectory()) {
|
|
16187
|
+
return path13.join(gitPath, "hooks");
|
|
16188
|
+
}
|
|
16189
|
+
const content = fs12.readFileSync(gitPath, "utf-8");
|
|
16190
|
+
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16191
|
+
if (!match?.[1])
|
|
16192
|
+
return null;
|
|
16193
|
+
let gitDir = match[1].trim();
|
|
16194
|
+
if (!path13.isAbsolute(gitDir)) {
|
|
16195
|
+
gitDir = path13.resolve(cwd, gitDir);
|
|
16196
|
+
}
|
|
16197
|
+
const commonFile = path13.join(gitDir, "commondir");
|
|
16198
|
+
if (fs12.existsSync(commonFile)) {
|
|
16199
|
+
let common = fs12.readFileSync(commonFile, "utf-8").trim();
|
|
16200
|
+
if (!path13.isAbsolute(common))
|
|
16201
|
+
common = path13.resolve(gitDir, common);
|
|
16202
|
+
return path13.join(common, "hooks");
|
|
16203
|
+
} else if (path13.basename(path13.dirname(gitDir)) === "worktrees") {
|
|
16204
|
+
return path13.join(path13.dirname(path13.dirname(gitDir)), "hooks");
|
|
16205
|
+
}
|
|
16206
|
+
return path13.join(gitDir, "hooks");
|
|
16207
|
+
} catch {
|
|
16208
|
+
return null;
|
|
16209
|
+
}
|
|
16210
|
+
}
|
|
16211
|
+
function auditGitHooks(repoPath = process.cwd()) {
|
|
16212
|
+
const hooksDir = resolveHooksDir(repoPath);
|
|
16213
|
+
if (!hooksDir || !fs12.existsSync(hooksDir)) {
|
|
16214
|
+
return {
|
|
16215
|
+
isGitRepo: Boolean(hooksDir),
|
|
16216
|
+
hooksDir,
|
|
16217
|
+
postCommitInstalled: false,
|
|
16218
|
+
postRewriteInstalled: false,
|
|
16219
|
+
markerFound: false
|
|
16220
|
+
};
|
|
16221
|
+
}
|
|
16222
|
+
const postCommit = path13.join(hooksDir, "post-commit");
|
|
16223
|
+
const postRewrite = path13.join(hooksDir, "post-rewrite");
|
|
16224
|
+
const hasMarker = (filePath) => {
|
|
16225
|
+
if (!fs12.existsSync(filePath))
|
|
16226
|
+
return false;
|
|
16227
|
+
try {
|
|
16228
|
+
return fs12.readFileSync(filePath, "utf-8").includes(HOOK_MARKER_BEGIN);
|
|
16229
|
+
} catch {
|
|
16230
|
+
return false;
|
|
16231
|
+
}
|
|
16232
|
+
};
|
|
16233
|
+
const commitOk = hasMarker(postCommit);
|
|
16234
|
+
const rewriteOk = hasMarker(postRewrite);
|
|
16235
|
+
return {
|
|
16236
|
+
isGitRepo: true,
|
|
16237
|
+
hooksDir,
|
|
16238
|
+
postCommitInstalled: commitOk,
|
|
16239
|
+
postRewriteInstalled: rewriteOk,
|
|
16240
|
+
markerFound: commitOk || rewriteOk
|
|
16241
|
+
};
|
|
16242
|
+
}
|
|
16243
|
+
async function benchmarkHookLatency(trials = 3) {
|
|
16244
|
+
const samples = [];
|
|
16245
|
+
for (let i2 = 0; i2 < trials; i2++) {
|
|
16246
|
+
const start = process.hrtime.bigint();
|
|
16247
|
+
try {
|
|
16248
|
+
const child = (0, import_node_child_process.spawn)(process.execPath, ["-e", "process.exit(0)"], {
|
|
16249
|
+
detached: true,
|
|
16250
|
+
stdio: "ignore",
|
|
16251
|
+
windowsHide: true
|
|
16252
|
+
});
|
|
16253
|
+
child.unref();
|
|
16254
|
+
const end = process.hrtime.bigint();
|
|
16255
|
+
const diffMs = Number(end - start) / 1e6;
|
|
16256
|
+
samples.push(diffMs);
|
|
16257
|
+
} catch {
|
|
16258
|
+
samples.push(99);
|
|
16259
|
+
}
|
|
16260
|
+
}
|
|
16261
|
+
const minMs = samples.length > 0 ? Math.min(...samples) : 99;
|
|
16262
|
+
const roundedMs = Number(minMs.toFixed(2));
|
|
16263
|
+
if (roundedMs < 5) {
|
|
16264
|
+
return {
|
|
16265
|
+
executionMs: roundedMs,
|
|
16266
|
+
passedInvariant: true,
|
|
16267
|
+
status: "pass",
|
|
16268
|
+
message: `Detached in ${roundedMs} ms (passed < 5ms invariant)`
|
|
16269
|
+
};
|
|
16270
|
+
} else if (roundedMs < 45) {
|
|
16271
|
+
return {
|
|
16272
|
+
executionMs: roundedMs,
|
|
16273
|
+
passedInvariant: true,
|
|
16274
|
+
status: "warn",
|
|
16275
|
+
message: `Detached in ${roundedMs} ms (acceptable cold spawn, target is < 5ms)`
|
|
16276
|
+
};
|
|
16277
|
+
} else {
|
|
16278
|
+
return {
|
|
16279
|
+
executionMs: roundedMs,
|
|
16280
|
+
passedInvariant: false,
|
|
16281
|
+
status: "fail",
|
|
16282
|
+
message: `Detached in ${roundedMs} ms (exceeded non-blocking threshold)`
|
|
16283
|
+
};
|
|
16284
|
+
}
|
|
16285
|
+
}
|
|
16286
|
+
function auditStorageHealth() {
|
|
16287
|
+
const dbPath = path13.join(os12.homedir(), ".qodewk", "state.db");
|
|
16288
|
+
try {
|
|
16289
|
+
const db = new LocalStateDB();
|
|
16290
|
+
const stats = db.getStats();
|
|
16291
|
+
db.close();
|
|
16292
|
+
let sizeBytes = 0;
|
|
16293
|
+
if (fs12.existsSync(dbPath)) {
|
|
16294
|
+
sizeBytes = fs12.statSync(dbPath).size;
|
|
16295
|
+
}
|
|
16296
|
+
return {
|
|
16297
|
+
healthy: true,
|
|
16298
|
+
dbPath,
|
|
16299
|
+
receiptsCount: stats.totalReceipts,
|
|
16300
|
+
footprintsCount: stats.totalFootprints,
|
|
16301
|
+
sizeBytes
|
|
16302
|
+
};
|
|
16303
|
+
} catch {
|
|
16304
|
+
return {
|
|
16305
|
+
healthy: false,
|
|
16306
|
+
dbPath,
|
|
16307
|
+
receiptsCount: 0,
|
|
16308
|
+
footprintsCount: 0
|
|
16309
|
+
};
|
|
16310
|
+
}
|
|
16311
|
+
}
|
|
16312
|
+
function auditPricingSync() {
|
|
16313
|
+
const modelsCount = Object.keys(RATE_CARDS).length;
|
|
16314
|
+
const cachedJson = path13.join(os12.homedir(), ".qodewk", "pricing.json");
|
|
16315
|
+
const hasCached = fs12.existsSync(cachedJson);
|
|
16316
|
+
return {
|
|
16317
|
+
modelsLoaded: modelsCount,
|
|
16318
|
+
cachedRegistryPresent: hasCached,
|
|
16319
|
+
status: modelsCount > 0 ? "active" : "offline"
|
|
16320
|
+
};
|
|
16321
|
+
}
|
|
16322
|
+
async function runDiagnostics(options = {}) {
|
|
16323
|
+
const repoPath = options.repoPath || process.cwd();
|
|
16324
|
+
const agents = auditAgentEnvironments(repoPath);
|
|
16325
|
+
const hooks = auditGitHooks(repoPath);
|
|
16326
|
+
const benchmark = await benchmarkHookLatency();
|
|
16327
|
+
const storage = auditStorageHealth();
|
|
16328
|
+
const pricing = auditPricingSync();
|
|
16329
|
+
const activeAgents = agents.filter((a) => a.status === "active").length;
|
|
16330
|
+
let overallStatus = "healthy";
|
|
16331
|
+
if (!storage.healthy || !hooks.isGitRepo) {
|
|
16332
|
+
overallStatus = "error";
|
|
16333
|
+
} else if (!hooks.markerFound || activeAgents === 0) {
|
|
16334
|
+
overallStatus = "warning";
|
|
16335
|
+
}
|
|
16336
|
+
return {
|
|
16337
|
+
overallStatus,
|
|
16338
|
+
version: "0.10.0",
|
|
16339
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16340
|
+
repoPath,
|
|
16341
|
+
agents,
|
|
16342
|
+
hooks,
|
|
16343
|
+
benchmark,
|
|
16344
|
+
storage,
|
|
16345
|
+
pricing
|
|
16346
|
+
};
|
|
16347
|
+
}
|
|
16348
|
+
|
|
16066
16349
|
// ../core/dist/index.js
|
|
16067
16350
|
function sanitizeReceiptForShare(receipt) {
|
|
16068
16351
|
const sessions = receipt.ai.sessions?.map((s) => ({
|
|
@@ -16194,7 +16477,7 @@ async function generateReceipt(options = {}) {
|
|
|
16194
16477
|
}
|
|
16195
16478
|
|
|
16196
16479
|
// src/receipt-view.ts
|
|
16197
|
-
var
|
|
16480
|
+
var fs13 = __toESM(require("fs"), 1);
|
|
16198
16481
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
16199
16482
|
|
|
16200
16483
|
// src/barcode.ts
|
|
@@ -16608,7 +16891,7 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
16608
16891
|
}
|
|
16609
16892
|
if (options.out) {
|
|
16610
16893
|
const fileContent = format === "terminal" ? stripAnsi(content) : content;
|
|
16611
|
-
|
|
16894
|
+
fs13.writeFileSync(options.out, fileContent.endsWith("\n") ? fileContent : fileContent + "\n", "utf-8");
|
|
16612
16895
|
console.log(import_picocolors.default.green(`\u2713 Receipt written to ${options.out}`));
|
|
16613
16896
|
}
|
|
16614
16897
|
if (!options.out) {
|
|
@@ -16621,12 +16904,12 @@ async function outputReceipt(receipt, options, publicUrl) {
|
|
|
16621
16904
|
}
|
|
16622
16905
|
|
|
16623
16906
|
// src/hooks.ts
|
|
16624
|
-
var
|
|
16625
|
-
var
|
|
16626
|
-
var
|
|
16907
|
+
var fs14 = __toESM(require("fs"), 1);
|
|
16908
|
+
var path14 = __toESM(require("path"), 1);
|
|
16909
|
+
var HOOK_MARKER_BEGIN2 = "# --- BEGIN QODEWK HOOK ---";
|
|
16627
16910
|
var HOOK_MARKER_END = "# --- END QODEWK HOOK ---";
|
|
16628
16911
|
var HOOK_SNIPPET = `
|
|
16629
|
-
${
|
|
16912
|
+
${HOOK_MARKER_BEGIN2}
|
|
16630
16913
|
# Non-blocking Qodewk background recorder (< 5ms)
|
|
16631
16914
|
if command -v qodewk >/dev/null 2>&1 || command -v pnpm >/dev/null 2>&1 || [ -f "./node_modules/.bin/qodewk" ]; then
|
|
16632
16915
|
( ( qodewk record || pnpm qodewk record || npx qodewk record ) >/dev/null 2>&1 & )
|
|
@@ -16634,37 +16917,37 @@ fi
|
|
|
16634
16917
|
${HOOK_MARKER_END}
|
|
16635
16918
|
`;
|
|
16636
16919
|
function resolveGitHooksDir(cwd = process.cwd()) {
|
|
16637
|
-
const gitPath =
|
|
16638
|
-
if (!
|
|
16920
|
+
const gitPath = path14.join(cwd, ".git");
|
|
16921
|
+
if (!fs14.existsSync(gitPath)) return null;
|
|
16639
16922
|
let gitCommonDir;
|
|
16640
|
-
const stat =
|
|
16923
|
+
const stat = fs14.statSync(gitPath);
|
|
16641
16924
|
if (stat.isDirectory()) {
|
|
16642
16925
|
gitCommonDir = gitPath;
|
|
16643
16926
|
} else {
|
|
16644
|
-
const content =
|
|
16927
|
+
const content = fs14.readFileSync(gitPath, "utf-8");
|
|
16645
16928
|
const match = content.match(/gitdir:\s*(.+)/i);
|
|
16646
16929
|
if (!match?.[1]) return null;
|
|
16647
16930
|
let gitDir = match[1].trim();
|
|
16648
|
-
if (!
|
|
16649
|
-
gitDir =
|
|
16931
|
+
if (!path14.isAbsolute(gitDir)) {
|
|
16932
|
+
gitDir = path14.resolve(cwd, gitDir);
|
|
16650
16933
|
}
|
|
16651
|
-
const commonFile =
|
|
16652
|
-
if (
|
|
16653
|
-
let common =
|
|
16654
|
-
if (!
|
|
16655
|
-
common =
|
|
16934
|
+
const commonFile = path14.join(gitDir, "commondir");
|
|
16935
|
+
if (fs14.existsSync(commonFile)) {
|
|
16936
|
+
let common = fs14.readFileSync(commonFile, "utf-8").trim();
|
|
16937
|
+
if (!path14.isAbsolute(common)) {
|
|
16938
|
+
common = path14.resolve(gitDir, common);
|
|
16656
16939
|
}
|
|
16657
16940
|
gitCommonDir = common;
|
|
16658
|
-
} else if (
|
|
16659
|
-
gitCommonDir =
|
|
16941
|
+
} else if (path14.basename(path14.dirname(gitDir)) === "worktrees") {
|
|
16942
|
+
gitCommonDir = path14.dirname(path14.dirname(gitDir));
|
|
16660
16943
|
} else {
|
|
16661
16944
|
gitCommonDir = gitDir;
|
|
16662
16945
|
}
|
|
16663
16946
|
}
|
|
16664
|
-
return
|
|
16947
|
+
return path14.join(gitCommonDir, "hooks");
|
|
16665
16948
|
}
|
|
16666
16949
|
function checkHookStatus(hooksDir) {
|
|
16667
|
-
if (!hooksDir || !
|
|
16950
|
+
if (!hooksDir || !fs14.existsSync(hooksDir)) {
|
|
16668
16951
|
return {
|
|
16669
16952
|
isGit: Boolean(hooksDir),
|
|
16670
16953
|
hooksDir,
|
|
@@ -16672,13 +16955,13 @@ function checkHookStatus(hooksDir) {
|
|
|
16672
16955
|
postRewriteInstalled: false
|
|
16673
16956
|
};
|
|
16674
16957
|
}
|
|
16675
|
-
const postCommit =
|
|
16676
|
-
const postRewrite =
|
|
16958
|
+
const postCommit = path14.join(hooksDir, "post-commit");
|
|
16959
|
+
const postRewrite = path14.join(hooksDir, "post-rewrite");
|
|
16677
16960
|
const hasHook = (p2) => {
|
|
16678
|
-
if (!
|
|
16961
|
+
if (!fs14.existsSync(p2)) return false;
|
|
16679
16962
|
try {
|
|
16680
|
-
const content =
|
|
16681
|
-
return content.includes(
|
|
16963
|
+
const content = fs14.readFileSync(p2, "utf-8");
|
|
16964
|
+
return content.includes(HOOK_MARKER_BEGIN2);
|
|
16682
16965
|
} catch {
|
|
16683
16966
|
return false;
|
|
16684
16967
|
}
|
|
@@ -16692,31 +16975,118 @@ function checkHookStatus(hooksDir) {
|
|
|
16692
16975
|
}
|
|
16693
16976
|
function installHookFile(hookFile) {
|
|
16694
16977
|
let content = "";
|
|
16695
|
-
if (
|
|
16696
|
-
content =
|
|
16978
|
+
if (fs14.existsSync(hookFile)) {
|
|
16979
|
+
content = fs14.readFileSync(hookFile, "utf-8");
|
|
16697
16980
|
} else {
|
|
16698
16981
|
content = "#!/bin/sh\n";
|
|
16699
16982
|
}
|
|
16700
|
-
if (content.includes(
|
|
16983
|
+
if (content.includes(HOOK_MARKER_BEGIN2)) {
|
|
16701
16984
|
return "exists";
|
|
16702
16985
|
}
|
|
16703
|
-
|
|
16986
|
+
fs14.writeFileSync(hookFile, content + HOOK_SNIPPET, { mode: 493 });
|
|
16704
16987
|
return "installed";
|
|
16705
16988
|
}
|
|
16706
16989
|
function uninstallHookFile(hookFile) {
|
|
16707
|
-
if (!
|
|
16708
|
-
const content =
|
|
16709
|
-
if (!content.includes(
|
|
16710
|
-
const regex = new RegExp(`\\n?${
|
|
16990
|
+
if (!fs14.existsSync(hookFile)) return "absent";
|
|
16991
|
+
const content = fs14.readFileSync(hookFile, "utf-8");
|
|
16992
|
+
if (!content.includes(HOOK_MARKER_BEGIN2)) return "missing";
|
|
16993
|
+
const regex = new RegExp(`\\n?${HOOK_MARKER_BEGIN2}[\\s\\S]*?${HOOK_MARKER_END}\\n?`, "g");
|
|
16711
16994
|
const updated = content.replace(regex, "");
|
|
16712
|
-
|
|
16995
|
+
fs14.writeFileSync(hookFile, updated, { mode: 493 });
|
|
16713
16996
|
return "removed";
|
|
16714
16997
|
}
|
|
16715
16998
|
|
|
16716
16999
|
// src/menu.ts
|
|
16717
17000
|
var readline = __toESM(require("readline"), 1);
|
|
16718
|
-
var
|
|
17001
|
+
var path15 = __toESM(require("path"), 1);
|
|
17002
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
17003
|
+
|
|
17004
|
+
// src/doctor-view.ts
|
|
16719
17005
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
17006
|
+
function formatDoctorReport(report) {
|
|
17007
|
+
const lines = [];
|
|
17008
|
+
const push = (l) => lines.push(l);
|
|
17009
|
+
push("");
|
|
17010
|
+
const badge = bg.teal(import_picocolors2.default.bold(colors.ink(" qodewk doctor ")));
|
|
17011
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors2.default.dim(`v${report.version}`)}`);
|
|
17012
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17013
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.bold(import_picocolors2.default.white("AI Agent Environment"))}`);
|
|
17014
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17015
|
+
for (const agent of report.agents) {
|
|
17016
|
+
const isAct = agent.status === "active";
|
|
17017
|
+
const icon = isAct ? colors.green("\u2713") : import_picocolors2.default.dim("-");
|
|
17018
|
+
const namePad = agent.name.padEnd(20, ".");
|
|
17019
|
+
const statusText = isAct ? colors.green("Active") : import_picocolors2.default.dim("Not detected");
|
|
17020
|
+
const detail = agent.path ? import_picocolors2.default.dim(` (${agent.path})`) : "";
|
|
17021
|
+
push(` ${colors.mutedSoft("\u2502")} ${icon} ${import_picocolors2.default.white(namePad)} ${statusText}${detail}`);
|
|
17022
|
+
}
|
|
17023
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17024
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.bold(import_picocolors2.default.white("Git Hook Telemetry"))}`);
|
|
17025
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17026
|
+
const hookDirText = report.hooks.hooksDir ? import_picocolors2.default.dim(` (${report.hooks.hooksDir})`) : "";
|
|
17027
|
+
const pcIcon = report.hooks.postCommitInstalled ? colors.green("\u2713") : colors.red("\xD7");
|
|
17028
|
+
const pcStatus = report.hooks.postCommitInstalled ? colors.green("Installed") : colors.red("Missing");
|
|
17029
|
+
push(` ${colors.mutedSoft("\u2502")} ${pcIcon} ${import_picocolors2.default.white("post-commit hook ...")} ${pcStatus}${hookDirText}`);
|
|
17030
|
+
const prIcon = report.hooks.postRewriteInstalled ? colors.green("\u2713") : colors.red("\xD7");
|
|
17031
|
+
const prStatus = report.hooks.postRewriteInstalled ? colors.green("Installed") : colors.red("Missing");
|
|
17032
|
+
push(` ${colors.mutedSoft("\u2502")} ${prIcon} ${import_picocolors2.default.white("post-rewrite hook ..")} ${prStatus}`);
|
|
17033
|
+
const bench = report.benchmark;
|
|
17034
|
+
const benchIcon = bench.status === "pass" ? colors.green("\u2713") : bench.status === "warn" ? colors.amber("!") : colors.red("\xD7");
|
|
17035
|
+
const benchColor = bench.status === "pass" ? colors.green : bench.status === "warn" ? colors.amber : colors.red;
|
|
17036
|
+
push(` ${colors.mutedSoft("\u2502")} ${benchIcon} ${import_picocolors2.default.white("Hook spawn latency .")} ${benchColor(`${bench.executionMs} ms`)} ${import_picocolors2.default.dim(`(${bench.message})`)}`);
|
|
17037
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17038
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors2.default.bold(import_picocolors2.default.white("Local Storage & Pricing"))}`);
|
|
17039
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17040
|
+
const dbIcon = report.storage.healthy ? colors.green("\u2713") : colors.red("\xD7");
|
|
17041
|
+
const dbStatus = report.storage.healthy ? colors.green("Healthy") : colors.red("Failed");
|
|
17042
|
+
const dbDetail = report.storage.healthy ? import_picocolors2.default.dim(` (${report.storage.receiptsCount} receipts, ${report.storage.footprintsCount} footprints)`) : "";
|
|
17043
|
+
push(` ${colors.mutedSoft("\u2502")} ${dbIcon} ${import_picocolors2.default.white("SQLite Database ....")} ${dbStatus}${dbDetail}`);
|
|
17044
|
+
const prcIcon = report.pricing.status === "active" ? colors.green("\u2713") : colors.red("\xD7");
|
|
17045
|
+
const prcStatus = report.pricing.status === "active" ? colors.green("Active") : colors.red("Offline");
|
|
17046
|
+
push(` ${colors.mutedSoft("\u2502")} ${prcIcon} ${import_picocolors2.default.white("Rate Card Registry .")} ${prcStatus} ${import_picocolors2.default.dim(`(${report.pricing.modelsLoaded} model rate cards loaded)`)}`);
|
|
17047
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17048
|
+
if (report.overallStatus === "healthy") {
|
|
17049
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors2.default.bold(colors.green("All Systems Operational \u2014 Telemetry Ready"))}`);
|
|
17050
|
+
} else if (report.overallStatus === "warning") {
|
|
17051
|
+
push(` ${colors.amber("\u25C6")} ${import_picocolors2.default.bold(colors.amber("Operational with Warnings \u2014 Run `qodewk hook install` to enable automatic recording"))}`);
|
|
17052
|
+
} else {
|
|
17053
|
+
push(` ${colors.red("\u25C6")} ${import_picocolors2.default.bold(colors.red("Diagnostic Issues Detected \u2014 Check Git repository or database status"))}`);
|
|
17054
|
+
}
|
|
17055
|
+
push(` ${colors.mutedSoft("\u2514")}`);
|
|
17056
|
+
push("");
|
|
17057
|
+
return lines.join("\n");
|
|
17058
|
+
}
|
|
17059
|
+
function formatHookTestReport(hooks, benchmark) {
|
|
17060
|
+
const lines = [];
|
|
17061
|
+
const push = (l) => lines.push(l);
|
|
17062
|
+
push("");
|
|
17063
|
+
const badge = bg.teal(import_picocolors2.default.bold(colors.ink(" qodewk hook test ")));
|
|
17064
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge}`);
|
|
17065
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17066
|
+
const pcIcon = hooks.postCommitInstalled ? colors.green("\u2713") : colors.red("\xD7");
|
|
17067
|
+
const pcStatus = hooks.postCommitInstalled ? colors.green("Installed") : colors.red("Missing");
|
|
17068
|
+
push(` ${colors.mutedSoft("\u2502")} ${pcIcon} post-commit hook: ${pcStatus}`);
|
|
17069
|
+
const prIcon = hooks.postRewriteInstalled ? colors.green("\u2713") : colors.red("\xD7");
|
|
17070
|
+
const prStatus = hooks.postRewriteInstalled ? colors.green("Installed") : colors.red("Missing");
|
|
17071
|
+
push(` ${colors.mutedSoft("\u2502")} ${prIcon} post-rewrite hook: ${prStatus}`);
|
|
17072
|
+
const benchIcon = benchmark.status === "pass" ? colors.green("\u2713") : benchmark.status === "warn" ? colors.amber("!") : colors.red("\xD7");
|
|
17073
|
+
const benchColor = benchmark.status === "pass" ? colors.green : benchmark.status === "warn" ? colors.amber : colors.red;
|
|
17074
|
+
push(` ${colors.mutedSoft("\u2502")} ${benchIcon} Detachment Latency: ${benchColor(`${benchmark.executionMs} ms`)}`);
|
|
17075
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors2.default.dim(benchmark.message)}`);
|
|
17076
|
+
push(` ${colors.mutedSoft("\u2502")}`);
|
|
17077
|
+
if (benchmark.passedInvariant && hooks.markerFound) {
|
|
17078
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors2.default.bold(colors.green("Non-blocking Hook Verified (< 5ms Invariant Passed)"))}`);
|
|
17079
|
+
} else if (!hooks.markerFound) {
|
|
17080
|
+
push(` ${colors.amber("\u25C6")} ${import_picocolors2.default.bold(colors.amber("Hooks Not Installed \u2014 Run `qodewk hook install`"))}`);
|
|
17081
|
+
} else {
|
|
17082
|
+
push(` ${colors.red("\u25C6")} ${import_picocolors2.default.bold(colors.red("Latency Threshold Exceeded \u2014 Reinstall recommended"))}`);
|
|
17083
|
+
}
|
|
17084
|
+
push(` ${colors.mutedSoft("\u2514")}`);
|
|
17085
|
+
push("");
|
|
17086
|
+
return lines.join("\n");
|
|
17087
|
+
}
|
|
17088
|
+
|
|
17089
|
+
// src/menu.ts
|
|
16720
17090
|
var SHARE_PAYLOAD_MAX_BYTES = 5e4;
|
|
16721
17091
|
var BANNER_LINES = [
|
|
16722
17092
|
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
@@ -16763,6 +17133,12 @@ var MENU_ITEMS = [
|
|
|
16763
17133
|
label: "Git Notes Management",
|
|
16764
17134
|
description: "Inspect & attach receipts to refs/notes/qodewk"
|
|
16765
17135
|
},
|
|
17136
|
+
{
|
|
17137
|
+
id: "doctor",
|
|
17138
|
+
key: "7",
|
|
17139
|
+
label: "System Health & Diagnostics",
|
|
17140
|
+
description: "Audit AI agents, Git hooks, SQLite & pricing registry (doctor)"
|
|
17141
|
+
},
|
|
16766
17142
|
{
|
|
16767
17143
|
id: "exit",
|
|
16768
17144
|
key: "0",
|
|
@@ -16808,7 +17184,7 @@ var RECEIPT_HORIZON_ITEMS = [
|
|
|
16808
17184
|
description: "Return to previous screen"
|
|
16809
17185
|
}
|
|
16810
17186
|
];
|
|
16811
|
-
function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Control Panel", subtitle = "\u2191\u2193 move \xB7 enter select \xB7 0-
|
|
17187
|
+
function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Control Panel", subtitle = "\u2191\u2193 move \xB7 enter select \xB7 0-7 quick jump \xB7 q quit", options = {}) {
|
|
16812
17188
|
const lines = [];
|
|
16813
17189
|
const push = (line) => lines.push(line);
|
|
16814
17190
|
if (options.showBanner ?? true) {
|
|
@@ -16819,21 +17195,21 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
16819
17195
|
}
|
|
16820
17196
|
}
|
|
16821
17197
|
push("");
|
|
16822
|
-
const badge = bg.teal(
|
|
16823
|
-
push(` ${colors.mutedSoft("\u250C")} ${badge} ${
|
|
17198
|
+
const badge = bg.teal(import_picocolors3.default.bold(colors.ink(" qodewk ")));
|
|
17199
|
+
push(` ${colors.mutedSoft("\u250C")} ${badge} ${import_picocolors3.default.dim("v0.10.0")}`);
|
|
16824
17200
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16825
17201
|
if (options.actionContext) {
|
|
16826
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17202
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors3.default.dim("Action:")} ${import_picocolors3.default.white(options.actionContext)}`);
|
|
16827
17203
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16828
17204
|
} else {
|
|
16829
17205
|
const repo = options.repoContext?.alias || "Qodewk";
|
|
16830
17206
|
const branch = options.repoContext?.branch ? `(${options.repoContext.branch})` : "";
|
|
16831
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17207
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors3.default.dim("Repository:")} ${import_picocolors3.default.white(repo)} ${import_picocolors3.default.dim(branch)}`);
|
|
16832
17208
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16833
|
-
push(` ${colors.teal("\u25C7")} ${
|
|
17209
|
+
push(` ${colors.teal("\u25C7")} ${import_picocolors3.default.dim("Telemetry:")} ${import_picocolors3.default.white("Claude Warm Editorial Rate Cards")}`);
|
|
16834
17210
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16835
17211
|
}
|
|
16836
|
-
push(` ${colors.coral("\u25C6")} ${
|
|
17212
|
+
push(` ${colors.coral("\u25C6")} ${import_picocolors3.default.bold(import_picocolors3.default.white(title))}`);
|
|
16837
17213
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16838
17214
|
const selectedItem = items[selectedIndex] || items[0];
|
|
16839
17215
|
for (let i2 = 0; i2 < items.length; i2++) {
|
|
@@ -16841,44 +17217,44 @@ function buildMenuFrame(selectedIndex, items = MENU_ITEMS, title = "Telemetry Co
|
|
|
16841
17217
|
const isSelected = i2 === selectedIndex;
|
|
16842
17218
|
if (isSelected) {
|
|
16843
17219
|
push(
|
|
16844
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17220
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors3.default.bold(colors.coral("\u203A"))} ${import_picocolors3.default.bold(colors.coral(item.key))} ${import_picocolors3.default.bold(import_picocolors3.default.white(item.label))}`
|
|
16845
17221
|
);
|
|
16846
17222
|
} else {
|
|
16847
17223
|
push(
|
|
16848
|
-
` ${colors.mutedSoft("\u2502")} ${
|
|
17224
|
+
` ${colors.mutedSoft("\u2502")} ${import_picocolors3.default.dim(item.key)} ${import_picocolors3.default.dim(import_picocolors3.default.white(item.label))}`
|
|
16849
17225
|
);
|
|
16850
17226
|
}
|
|
16851
17227
|
}
|
|
16852
17228
|
const divider = colors.mutedSoft("\u2500".repeat(58));
|
|
16853
17229
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16854
17230
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16855
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
17231
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors3.default.bold(import_picocolors3.default.dim("Description"))}`);
|
|
16856
17232
|
push(` ${colors.mutedSoft("\u2502")} ${colors.amber(selectedItem.description)}`);
|
|
16857
17233
|
push(` ${colors.mutedSoft("\u2502")} ${divider}`);
|
|
16858
17234
|
push(` ${colors.mutedSoft("\u2502")}`);
|
|
16859
|
-
push(` ${colors.mutedSoft("\u2502")} ${
|
|
16860
|
-
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${
|
|
17235
|
+
push(` ${colors.mutedSoft("\u2502")} ${import_picocolors3.default.dim(subtitle)}`);
|
|
17236
|
+
push(` ${colors.mutedSoft("\u2502")} ${colors.green("[\u2713]")} ${import_picocolors3.default.dim("Source code was never uploaded to Qodewk")}`);
|
|
16861
17237
|
push(` ${colors.mutedSoft("\u2514")}`);
|
|
16862
17238
|
push("");
|
|
16863
17239
|
return lines.join("\n");
|
|
16864
17240
|
}
|
|
16865
17241
|
function askLine(promptText) {
|
|
16866
|
-
return new Promise((
|
|
17242
|
+
return new Promise((resolve6) => {
|
|
16867
17243
|
const rl = readline.createInterface({
|
|
16868
17244
|
input: process.stdin,
|
|
16869
17245
|
output: process.stdout
|
|
16870
17246
|
});
|
|
16871
17247
|
rl.question(promptText, (answer) => {
|
|
16872
17248
|
rl.close();
|
|
16873
|
-
|
|
17249
|
+
resolve6(answer.trim());
|
|
16874
17250
|
});
|
|
16875
17251
|
});
|
|
16876
17252
|
}
|
|
16877
17253
|
function waitForKeyToReturn() {
|
|
16878
|
-
return new Promise((
|
|
16879
|
-
console.log(
|
|
17254
|
+
return new Promise((resolve6) => {
|
|
17255
|
+
console.log(import_picocolors3.default.dim("\n Press any key or Enter to return to menu..."));
|
|
16880
17256
|
if (!process.stdin.isTTY) {
|
|
16881
|
-
|
|
17257
|
+
resolve6();
|
|
16882
17258
|
return;
|
|
16883
17259
|
}
|
|
16884
17260
|
const wasRaw = process.stdin.isRaw;
|
|
@@ -16887,7 +17263,7 @@ function waitForKeyToReturn() {
|
|
|
16887
17263
|
const onKey = () => {
|
|
16888
17264
|
process.stdin.removeListener("data", onKey);
|
|
16889
17265
|
if (wasRaw !== void 0) process.stdin.setRawMode(wasRaw);
|
|
16890
|
-
|
|
17266
|
+
resolve6();
|
|
16891
17267
|
};
|
|
16892
17268
|
process.stdin.once("data", onKey);
|
|
16893
17269
|
});
|
|
@@ -16905,7 +17281,7 @@ async function getRepoContext() {
|
|
|
16905
17281
|
}
|
|
16906
17282
|
const branchSummary = await git.branch();
|
|
16907
17283
|
const branch = branchSummary.current || "HEAD";
|
|
16908
|
-
const alias =
|
|
17284
|
+
const alias = path15.basename(process.cwd());
|
|
16909
17285
|
cachedRepoContext = { alias, branch };
|
|
16910
17286
|
return cachedRepoContext;
|
|
16911
17287
|
} catch {
|
|
@@ -16916,7 +17292,7 @@ async function getRepoContext() {
|
|
|
16916
17292
|
async function runInteractiveMenu() {
|
|
16917
17293
|
if (!process.stdin.isTTY) {
|
|
16918
17294
|
console.log(buildMenuFrame(0));
|
|
16919
|
-
console.log(
|
|
17295
|
+
console.log(import_picocolors3.default.yellow("Interactive menu requires a TTY terminal. Use `qodewk --help` for commands."));
|
|
16920
17296
|
return;
|
|
16921
17297
|
}
|
|
16922
17298
|
const repoContext = await getRepoContext();
|
|
@@ -16928,7 +17304,7 @@ async function runInteractiveMenu() {
|
|
|
16928
17304
|
const render = () => {
|
|
16929
17305
|
const items = getActiveItems();
|
|
16930
17306
|
const title = currentScreen === "main" ? "Telemetry Control Panel" : "Generate Local Receipt";
|
|
16931
|
-
const subtitle = currentScreen === "main" ? "\u2191\u2193 move \xB7 enter select \xB7 0-
|
|
17307
|
+
const subtitle = currentScreen === "main" ? "\u2191\u2193 move \xB7 enter select \xB7 0-7 quick jump \xB7 q quit" : "\u2191\u2193 move \xB7 enter select \xB7 0-5 quick jump \xB7 esc / 0 back";
|
|
16932
17308
|
const actionContext = currentScreen === "receipt_horizon" ? "Generate Local Receipt" : void 0;
|
|
16933
17309
|
const showBanner = currentScreen === "main";
|
|
16934
17310
|
const frame = buildMenuFrame(selectedIndex, items, title, subtitle, {
|
|
@@ -16969,15 +17345,15 @@ async function runInteractiveMenu() {
|
|
|
16969
17345
|
since = "7d";
|
|
16970
17346
|
label = "past 7 days weekly sprint (--since 7d)";
|
|
16971
17347
|
} else if (item.id === "custom") {
|
|
16972
|
-
console.log(
|
|
16973
|
-
console.log(
|
|
17348
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white(" Custom Telemetry Horizon")));
|
|
17349
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
16974
17350
|
const input = await askLine(" \u203A Enter duration or date (e.g. 12h, 3d, 2026-10-01): ");
|
|
16975
17351
|
if (input) {
|
|
16976
17352
|
since = input;
|
|
16977
17353
|
label = `custom range: ${input}`;
|
|
16978
17354
|
}
|
|
16979
17355
|
}
|
|
16980
|
-
console.log(
|
|
17356
|
+
console.log(import_picocolors3.default.dim(` [\xB7] Generating local receipt for ${label}...`));
|
|
16981
17357
|
try {
|
|
16982
17358
|
const receipt = await generateReceipt({ since, isPublic: false });
|
|
16983
17359
|
const db = new LocalStateDB();
|
|
@@ -16986,7 +17362,7 @@ async function runInteractiveMenu() {
|
|
|
16986
17362
|
await renderTerminalReceipt(receipt);
|
|
16987
17363
|
} catch (err) {
|
|
16988
17364
|
const message = err instanceof Error ? err.message : String(err);
|
|
16989
|
-
console.error(
|
|
17365
|
+
console.error(import_picocolors3.default.red(`
|
|
16990
17366
|
Failed to generate receipt: ${message}`));
|
|
16991
17367
|
}
|
|
16992
17368
|
await waitForKeyToReturn();
|
|
@@ -17000,8 +17376,8 @@ async function runInteractiveMenu() {
|
|
|
17000
17376
|
const selectedItem = MENU_ITEMS[selectedIndex];
|
|
17001
17377
|
switch (selectedItem.id) {
|
|
17002
17378
|
case "audit": {
|
|
17003
|
-
console.log(
|
|
17004
|
-
console.log(
|
|
17379
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white("\n Audit Branch or Revision Diff")));
|
|
17380
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
17005
17381
|
let defaultBase = "origin/main";
|
|
17006
17382
|
try {
|
|
17007
17383
|
defaultBase = await detectDefaultBaseBranch(process.cwd());
|
|
@@ -17013,7 +17389,7 @@ async function runInteractiveMenu() {
|
|
|
17013
17389
|
const head = await askLine(
|
|
17014
17390
|
` \u203A Head git ref or commit SHA [default: HEAD]: `
|
|
17015
17391
|
);
|
|
17016
|
-
console.log(
|
|
17392
|
+
console.log(import_picocolors3.default.dim("\n [\xB7] Auditing git revision range..."));
|
|
17017
17393
|
try {
|
|
17018
17394
|
const receipt = await generateReceipt({
|
|
17019
17395
|
baseSha: base || defaultBase,
|
|
@@ -17026,18 +17402,18 @@ async function runInteractiveMenu() {
|
|
|
17026
17402
|
await renderTerminalReceipt(receipt);
|
|
17027
17403
|
} catch (err) {
|
|
17028
17404
|
const message = err instanceof Error ? err.message : String(err);
|
|
17029
|
-
console.error(
|
|
17405
|
+
console.error(import_picocolors3.default.red(`
|
|
17030
17406
|
Audit failed: ${message}`));
|
|
17031
17407
|
}
|
|
17032
17408
|
await waitForKeyToReturn();
|
|
17033
17409
|
break;
|
|
17034
17410
|
}
|
|
17035
17411
|
case "share": {
|
|
17036
|
-
console.log(
|
|
17412
|
+
console.log(import_picocolors3.default.dim(" [\xB7] Generating and sanitizing receipt for cloud publishing..."));
|
|
17037
17413
|
try {
|
|
17038
17414
|
const receipt = await generateReceipt({ isPublic: false });
|
|
17039
17415
|
if (process.env.QODEWK_TELEMETRY === "off") {
|
|
17040
|
-
console.log(
|
|
17416
|
+
console.log(import_picocolors3.default.yellow("\n Cloud publishing is disabled by QODEWK_TELEMETRY=off."));
|
|
17041
17417
|
await renderTerminalReceipt(receipt);
|
|
17042
17418
|
await waitForKeyToReturn();
|
|
17043
17419
|
break;
|
|
@@ -17052,7 +17428,7 @@ async function runInteractiveMenu() {
|
|
|
17052
17428
|
body = JSON.stringify(trimmed2);
|
|
17053
17429
|
}
|
|
17054
17430
|
const endpoint = resolveApiUrl();
|
|
17055
|
-
console.log(
|
|
17431
|
+
console.log(import_picocolors3.default.dim(` [\xB7] Uploading metadata to ${endpoint}...`));
|
|
17056
17432
|
const response = await fetch(endpoint, {
|
|
17057
17433
|
method: "POST",
|
|
17058
17434
|
headers: {
|
|
@@ -17064,11 +17440,11 @@ async function runInteractiveMenu() {
|
|
|
17064
17440
|
if (!response.ok) {
|
|
17065
17441
|
const errText = await response.text().catch(() => "");
|
|
17066
17442
|
if (response.status === 503) {
|
|
17067
|
-
console.log(
|
|
17068
|
-
console.log(
|
|
17069
|
-
console.log(
|
|
17443
|
+
console.log(import_picocolors3.default.yellow("\n Notice: Remote server requires durable storage (Supabase or PostgreSQL) in production"));
|
|
17444
|
+
console.log(import_picocolors3.default.dim(" to protect receipts from serverless cold-start data loss."));
|
|
17445
|
+
console.log(import_picocolors3.default.dim(` Endpoint: ${endpoint}`));
|
|
17070
17446
|
console.log(colors.green("\n [\u2713] Your receipt is safely saved locally in: ~/.qodewk/state.db"));
|
|
17071
|
-
console.log(
|
|
17447
|
+
console.log(import_picocolors3.default.dim(" You can also save it as a local Git note: qodewk --notes\n"));
|
|
17072
17448
|
await renderTerminalReceipt(sanitized);
|
|
17073
17449
|
await waitForKeyToReturn();
|
|
17074
17450
|
break;
|
|
@@ -17081,13 +17457,13 @@ async function runInteractiveMenu() {
|
|
|
17081
17457
|
db.close();
|
|
17082
17458
|
console.log("");
|
|
17083
17459
|
console.log(colors.green(" [\u2713] Published successfully."));
|
|
17084
|
-
console.log(` ${
|
|
17085
|
-
console.log(` ${
|
|
17086
|
-
console.log(
|
|
17460
|
+
console.log(` ${import_picocolors3.default.dim("Public URL:")} ${import_picocolors3.default.underline(import_picocolors3.default.cyan(data.url))}`);
|
|
17461
|
+
console.log(` ${import_picocolors3.default.bold(colors.amber("Claim token:"))} ${colors.amber(data.claimToken)}`);
|
|
17462
|
+
console.log(import_picocolors3.default.dim(" (Saved to ~/.qodewk/state.db for future authorship proofs)\n"));
|
|
17087
17463
|
await renderTerminalReceipt(sanitized, data.url);
|
|
17088
17464
|
} catch (err) {
|
|
17089
17465
|
const message = err instanceof Error ? err.message : String(err);
|
|
17090
|
-
console.error(
|
|
17466
|
+
console.error(import_picocolors3.default.red(`
|
|
17091
17467
|
Share failed: ${message}`));
|
|
17092
17468
|
}
|
|
17093
17469
|
await waitForKeyToReturn();
|
|
@@ -17105,10 +17481,14 @@ async function runInteractiveMenu() {
|
|
|
17105
17481
|
await manageGitNotesSubmenu();
|
|
17106
17482
|
break;
|
|
17107
17483
|
}
|
|
17484
|
+
case "doctor": {
|
|
17485
|
+
await runDoctorDiagnosticsAction();
|
|
17486
|
+
break;
|
|
17487
|
+
}
|
|
17108
17488
|
case "exit": {
|
|
17109
17489
|
active = false;
|
|
17110
17490
|
cleanup();
|
|
17111
|
-
console.log(
|
|
17491
|
+
console.log(import_picocolors3.default.dim(" Exited Qodewk.\n"));
|
|
17112
17492
|
process.exit(0);
|
|
17113
17493
|
return;
|
|
17114
17494
|
}
|
|
@@ -17117,31 +17497,32 @@ async function runInteractiveMenu() {
|
|
|
17117
17497
|
const manageHooksSubmenu = async () => {
|
|
17118
17498
|
const hooksDir = resolveGitHooksDir();
|
|
17119
17499
|
const status = checkHookStatus(hooksDir);
|
|
17120
|
-
console.log(
|
|
17121
|
-
console.log(
|
|
17500
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white("\n Qodewk Git Hooks Management")));
|
|
17501
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
17122
17502
|
if (!status.isGit) {
|
|
17123
|
-
console.log(
|
|
17503
|
+
console.log(import_picocolors3.default.yellow(" Not inside a Git repository. Hooks cannot be configured."));
|
|
17124
17504
|
await waitForKeyToReturn();
|
|
17125
17505
|
return;
|
|
17126
17506
|
}
|
|
17127
|
-
console.log(` Hooks directory: ${
|
|
17507
|
+
console.log(` Hooks directory: ${import_picocolors3.default.dim(status.hooksDir || "None")}`);
|
|
17128
17508
|
console.log(
|
|
17129
|
-
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") :
|
|
17509
|
+
` post-commit: ${status.postCommitInstalled ? colors.green("[\u2713 Installed]") : import_picocolors3.default.dim("[\xB7 Not installed]")}`
|
|
17130
17510
|
);
|
|
17131
17511
|
console.log(
|
|
17132
|
-
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") :
|
|
17512
|
+
` post-rewrite: ${status.postRewriteInstalled ? colors.green("[\u2713 Installed]") : import_picocolors3.default.dim("[\xB7 Not installed]")}`
|
|
17133
17513
|
);
|
|
17134
17514
|
console.log("");
|
|
17135
17515
|
console.log(" [1] Install non-blocking hooks (< 5ms background recorder)");
|
|
17136
17516
|
console.log(" [2] Uninstall Qodewk hooks");
|
|
17517
|
+
console.log(" [3] Test & benchmark hook latency (< 5ms invariant)");
|
|
17137
17518
|
console.log(" [0] Back to main menu");
|
|
17138
17519
|
console.log("");
|
|
17139
|
-
const choice = await askLine(" \u203A Select option [0-
|
|
17520
|
+
const choice = await askLine(" \u203A Select option [0-3]: ");
|
|
17140
17521
|
if (choice === "1") {
|
|
17141
17522
|
if (status.hooksDir) {
|
|
17142
17523
|
const targets = ["post-commit", "post-rewrite"];
|
|
17143
17524
|
for (const t2 of targets) {
|
|
17144
|
-
installHookFile(
|
|
17525
|
+
installHookFile(path15.join(status.hooksDir, t2));
|
|
17145
17526
|
}
|
|
17146
17527
|
console.log(colors.green("\n [\u2713] Non-blocking hooks installed successfully."));
|
|
17147
17528
|
}
|
|
@@ -17149,16 +17530,20 @@ async function runInteractiveMenu() {
|
|
|
17149
17530
|
if (status.hooksDir) {
|
|
17150
17531
|
const targets = ["post-commit", "post-rewrite"];
|
|
17151
17532
|
for (const t2 of targets) {
|
|
17152
|
-
uninstallHookFile(
|
|
17533
|
+
uninstallHookFile(path15.join(status.hooksDir, t2));
|
|
17153
17534
|
}
|
|
17154
17535
|
console.log(colors.green("\n [\u2713] Qodewk hooks removed."));
|
|
17155
17536
|
}
|
|
17537
|
+
} else if (choice === "3") {
|
|
17538
|
+
const hooks = auditGitHooks();
|
|
17539
|
+
const bench = await benchmarkHookLatency();
|
|
17540
|
+
console.log(formatHookTestReport(hooks, bench));
|
|
17156
17541
|
}
|
|
17157
17542
|
await waitForKeyToReturn();
|
|
17158
17543
|
};
|
|
17159
17544
|
const manageGitNotesSubmenu = async () => {
|
|
17160
|
-
console.log(
|
|
17161
|
-
console.log(
|
|
17545
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white("\n Qodewk Git Notes Management (refs/notes/qodewk)")));
|
|
17546
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
17162
17547
|
console.log(" [1] List commits with attached Qodewk notes");
|
|
17163
17548
|
console.log(" [2] Show receipt note on a commit (default: HEAD)");
|
|
17164
17549
|
console.log(" [3] Attach receipt note to a Git commit (default: HEAD)");
|
|
@@ -17169,17 +17554,17 @@ async function runInteractiveMenu() {
|
|
|
17169
17554
|
try {
|
|
17170
17555
|
const shas = await listGitReceiptNotes();
|
|
17171
17556
|
if (shas.length === 0) {
|
|
17172
|
-
console.log(
|
|
17557
|
+
console.log(import_picocolors3.default.yellow("\n No Qodewk Git notes found in repository."));
|
|
17173
17558
|
} else {
|
|
17174
|
-
console.log(
|
|
17559
|
+
console.log(import_picocolors3.default.bold(`
|
|
17175
17560
|
Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
17176
17561
|
for (const sha of shas) {
|
|
17177
|
-
console.log(` ${
|
|
17562
|
+
console.log(` ${import_picocolors3.default.cyan(sha.slice(0, 10))} ${import_picocolors3.default.dim(sha)}`);
|
|
17178
17563
|
}
|
|
17179
17564
|
}
|
|
17180
17565
|
} catch (err) {
|
|
17181
17566
|
const message = err instanceof Error ? err.message : String(err);
|
|
17182
|
-
console.error(
|
|
17567
|
+
console.error(import_picocolors3.default.red(`
|
|
17183
17568
|
Error listing Git notes: ${message}`));
|
|
17184
17569
|
}
|
|
17185
17570
|
} else if (choice === "2") {
|
|
@@ -17187,20 +17572,20 @@ async function runInteractiveMenu() {
|
|
|
17187
17572
|
try {
|
|
17188
17573
|
const receipt = await readGitReceiptNote(commit);
|
|
17189
17574
|
if (!receipt) {
|
|
17190
|
-
console.log(
|
|
17575
|
+
console.log(import_picocolors3.default.yellow(`
|
|
17191
17576
|
No Qodewk receipt note found on commit '${commit}'.`));
|
|
17192
17577
|
} else {
|
|
17193
17578
|
await renderTerminalReceipt(receipt);
|
|
17194
17579
|
}
|
|
17195
17580
|
} catch (err) {
|
|
17196
17581
|
const message = err instanceof Error ? err.message : String(err);
|
|
17197
|
-
console.error(
|
|
17582
|
+
console.error(import_picocolors3.default.red(`
|
|
17198
17583
|
Error reading Git note: ${message}`));
|
|
17199
17584
|
}
|
|
17200
17585
|
} else if (choice === "3") {
|
|
17201
17586
|
const commit = await askLine(" \u203A Commit SHA to attach note [default: HEAD]: ") || "HEAD";
|
|
17202
17587
|
try {
|
|
17203
|
-
console.log(
|
|
17588
|
+
console.log(import_picocolors3.default.dim(`
|
|
17204
17589
|
[\xB7] Generating receipt for ${commit}...`));
|
|
17205
17590
|
const receipt = await generateReceipt({ headSha: commit });
|
|
17206
17591
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
@@ -17210,30 +17595,30 @@ async function runInteractiveMenu() {
|
|
|
17210
17595
|
);
|
|
17211
17596
|
} catch (err) {
|
|
17212
17597
|
const message = err instanceof Error ? err.message : String(err);
|
|
17213
|
-
console.error(
|
|
17598
|
+
console.error(import_picocolors3.default.red(`
|
|
17214
17599
|
Error writing Git note: ${message}`));
|
|
17215
17600
|
}
|
|
17216
17601
|
}
|
|
17217
17602
|
await waitForKeyToReturn();
|
|
17218
17603
|
};
|
|
17219
17604
|
const showStorageStatus = async () => {
|
|
17220
|
-
console.log(
|
|
17221
|
-
console.log(
|
|
17605
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white("\n Qodewk Local Database & Storage Status")));
|
|
17606
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
17222
17607
|
try {
|
|
17223
17608
|
const db = new LocalStateDB();
|
|
17224
17609
|
const stats = db.getStats();
|
|
17225
17610
|
const recent = db.getRecentReceipts(5);
|
|
17226
17611
|
db.close();
|
|
17227
|
-
console.log(` Database path: ${
|
|
17228
|
-
console.log(` Total saved receipts: ${
|
|
17229
|
-
console.log(` Total agent footprints: ${
|
|
17612
|
+
console.log(` Database path: ${import_picocolors3.default.dim("~/.qodewk/state.db")}`);
|
|
17613
|
+
console.log(` Total saved receipts: ${import_picocolors3.default.bold(import_picocolors3.default.white(String(stats.totalReceipts)))}`);
|
|
17614
|
+
console.log(` Total agent footprints: ${import_picocolors3.default.bold(import_picocolors3.default.white(String(stats.totalFootprints)))}`);
|
|
17230
17615
|
console.log("");
|
|
17231
17616
|
if (recent.length === 0) {
|
|
17232
|
-
console.log(
|
|
17617
|
+
console.log(import_picocolors3.default.dim(" No stored receipts yet. Run 'Generate Local Receipt' to record your first."));
|
|
17233
17618
|
} else {
|
|
17234
|
-
console.log(
|
|
17235
|
-
console.log(
|
|
17236
|
-
console.log(
|
|
17619
|
+
console.log(import_picocolors3.default.dim(" Recent Receipts:"));
|
|
17620
|
+
console.log(import_picocolors3.default.dim(" " + "ID".padEnd(26) + "DATE".padEnd(12) + "BRANCH".padEnd(18) + "COST"));
|
|
17621
|
+
console.log(import_picocolors3.default.dim(" " + "\u2500".repeat(60)));
|
|
17237
17622
|
for (const item of recent) {
|
|
17238
17623
|
const id = item.receipt.receipt.id.slice(0, 24).padEnd(26);
|
|
17239
17624
|
const date = item.receipt.receipt.createdAt.slice(0, 10).padEnd(12);
|
|
@@ -17243,10 +17628,23 @@ async function runInteractiveMenu() {
|
|
|
17243
17628
|
}
|
|
17244
17629
|
}
|
|
17245
17630
|
console.log("");
|
|
17246
|
-
console.log(` ${colors.green("[\u2713]")} ${
|
|
17631
|
+
console.log(` ${colors.green("[\u2713]")} ${import_picocolors3.default.dim("Privacy guarantee: raw source code is never stored in SQLite")}`);
|
|
17632
|
+
} catch (err) {
|
|
17633
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17634
|
+
console.error(import_picocolors3.default.red(` Failed to inspect storage: ${message}`));
|
|
17635
|
+
}
|
|
17636
|
+
await waitForKeyToReturn();
|
|
17637
|
+
};
|
|
17638
|
+
const runDoctorDiagnosticsAction = async () => {
|
|
17639
|
+
console.log(import_picocolors3.default.bold(import_picocolors3.default.white("\n Qodewk System Health & Diagnostics (Doctor)")));
|
|
17640
|
+
console.log(import_picocolors3.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
17641
|
+
console.log(import_picocolors3.default.dim(" [\xB7] Running diagnostic audit across agents, hooks, storage, and pricing...\n"));
|
|
17642
|
+
try {
|
|
17643
|
+
const report = await runDiagnostics();
|
|
17644
|
+
console.log(formatDoctorReport(report));
|
|
17247
17645
|
} catch (err) {
|
|
17248
17646
|
const message = err instanceof Error ? err.message : String(err);
|
|
17249
|
-
console.error(
|
|
17647
|
+
console.error(import_picocolors3.default.red(` Diagnostic check failed: ${message}`));
|
|
17250
17648
|
}
|
|
17251
17649
|
await waitForKeyToReturn();
|
|
17252
17650
|
};
|
|
@@ -17271,7 +17669,7 @@ async function runInteractiveMenu() {
|
|
|
17271
17669
|
return;
|
|
17272
17670
|
}
|
|
17273
17671
|
cleanup();
|
|
17274
|
-
console.log(
|
|
17672
|
+
console.log(import_picocolors3.default.dim("\n Exited Qodewk.\n"));
|
|
17275
17673
|
process.exit(0);
|
|
17276
17674
|
}
|
|
17277
17675
|
if (key.name === "up" || key.name === "k") {
|
|
@@ -17348,19 +17746,19 @@ loadQodewkEnv();
|
|
|
17348
17746
|
var SHARE_PAYLOAD_MAX_BYTES2 = 5e4;
|
|
17349
17747
|
function resolveCliVersion() {
|
|
17350
17748
|
try {
|
|
17351
|
-
const argv1 = process.argv[1] ?
|
|
17749
|
+
const argv1 = process.argv[1] ? path16.dirname(path16.resolve(process.argv[1])) : process.cwd();
|
|
17352
17750
|
const candidates = [
|
|
17353
|
-
|
|
17354
|
-
|
|
17751
|
+
path16.join(argv1, "..", "package.json"),
|
|
17752
|
+
path16.join(argv1, "package.json")
|
|
17355
17753
|
];
|
|
17356
17754
|
for (const candidate of candidates) {
|
|
17357
|
-
if (!
|
|
17358
|
-
const pkg = JSON.parse(
|
|
17755
|
+
if (!fs15.existsSync(candidate)) continue;
|
|
17756
|
+
const pkg = JSON.parse(fs15.readFileSync(candidate, "utf-8"));
|
|
17359
17757
|
if (pkg.name === "qodewk" && pkg.version) return pkg.version;
|
|
17360
17758
|
}
|
|
17361
17759
|
} catch {
|
|
17362
17760
|
}
|
|
17363
|
-
return "0.
|
|
17761
|
+
return "0.10.0";
|
|
17364
17762
|
}
|
|
17365
17763
|
function resolveSince(options) {
|
|
17366
17764
|
return options.today ? "today" : options.since;
|
|
@@ -17398,21 +17796,39 @@ program2.name("qodewk").description("Universal telemetry and digital receipt gen
|
|
|
17398
17796
|
if (options.notes) {
|
|
17399
17797
|
try {
|
|
17400
17798
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
17401
|
-
console.log(
|
|
17799
|
+
console.log(import_picocolors4.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`));
|
|
17402
17800
|
} catch (noteErr) {
|
|
17403
|
-
console.warn(
|
|
17801
|
+
console.warn(import_picocolors4.default.yellow(`Warning: Could not write Git note: ${noteErr.message}`));
|
|
17404
17802
|
}
|
|
17405
17803
|
}
|
|
17406
17804
|
await outputReceipt(receipt, options);
|
|
17407
17805
|
} catch (err) {
|
|
17408
17806
|
const message = err instanceof Error ? err.message : String(err);
|
|
17409
|
-
console.error(
|
|
17807
|
+
console.error(import_picocolors4.default.red(`Error generating receipt: ${message}`));
|
|
17410
17808
|
process.exit(1);
|
|
17411
17809
|
}
|
|
17412
17810
|
});
|
|
17413
17811
|
program2.command("menu").description("Launch interactive terminal control panel").action(async () => {
|
|
17414
17812
|
await runInteractiveMenu();
|
|
17415
17813
|
});
|
|
17814
|
+
program2.command("doctor").description("Run complete diagnostic health check of AI agents, git hooks, and local telemetry").option("-j, --json", "Output diagnostic report in machine-readable JSON format").action(async (options) => {
|
|
17815
|
+
try {
|
|
17816
|
+
const isJson = Boolean(options.json || program2.opts().json);
|
|
17817
|
+
const report = await runDiagnostics();
|
|
17818
|
+
if (isJson) {
|
|
17819
|
+
console.log(JSON.stringify(report, null, 2));
|
|
17820
|
+
} else {
|
|
17821
|
+
console.log(formatDoctorReport(report));
|
|
17822
|
+
}
|
|
17823
|
+
if (report.overallStatus === "error") {
|
|
17824
|
+
process.exit(1);
|
|
17825
|
+
}
|
|
17826
|
+
} catch (err) {
|
|
17827
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17828
|
+
console.error(import_picocolors4.default.red(`Error running diagnostics: ${message}`));
|
|
17829
|
+
process.exit(1);
|
|
17830
|
+
}
|
|
17831
|
+
});
|
|
17416
17832
|
program2.command("audit").description("Audit PR or branch diff against a target base commit").option("-b, --base <base>", "Base git ref or commit SHA (e.g. origin/main)").option("-H, --head <head>", "Head git ref or commit SHA").option("-f, --format <format>", "Output format (terminal, json, markdown)", "terminal").option("-o, --out <path>", "Write receipt output to specified file path").option("-p, --provider <provider>", "Specify AI provider").option("-m, --model <model>", "Specify AI model").option("-s, --since <duration>", "Harvest agent footprints since duration").option("--today", "Harvest agent footprints for today").option("--platform <platform>", "Filter agent platform").option("--anon", "Anonymize branch name in output").option("--barcode", "Render classic 1D thermal barcode (always on; kept for compatibility)").action(async (options) => {
|
|
17417
17833
|
try {
|
|
17418
17834
|
const receipt = await generateReceipt({
|
|
@@ -17429,7 +17845,7 @@ program2.command("audit").description("Audit PR or branch diff against a target
|
|
|
17429
17845
|
await outputReceipt(receipt, options);
|
|
17430
17846
|
} catch (err) {
|
|
17431
17847
|
const message = err instanceof Error ? err.message : String(err);
|
|
17432
|
-
console.error(
|
|
17848
|
+
console.error(import_picocolors4.default.red(`Error auditing git range: ${message}`));
|
|
17433
17849
|
process.exit(1);
|
|
17434
17850
|
}
|
|
17435
17851
|
});
|
|
@@ -17446,12 +17862,12 @@ program2.command("share").description("Publish privacy-safe receipt to Qodewk cl
|
|
|
17446
17862
|
const localFlag = program2.opts().local === true;
|
|
17447
17863
|
if (process.env.QODEWK_TELEMETRY === "off" || localFlag) {
|
|
17448
17864
|
console.log(
|
|
17449
|
-
|
|
17865
|
+
import_picocolors4.default.yellow(
|
|
17450
17866
|
`
|
|
17451
17867
|
Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"}).`
|
|
17452
17868
|
)
|
|
17453
17869
|
);
|
|
17454
|
-
console.log(
|
|
17870
|
+
console.log(import_picocolors4.default.dim("Telemetry remains strictly stored in local SQLite (~/.qodewk/state.db).\n"));
|
|
17455
17871
|
persistReceipt(receipt);
|
|
17456
17872
|
await renderTerminalReceipt(receipt);
|
|
17457
17873
|
return;
|
|
@@ -17466,11 +17882,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17466
17882
|
body = JSON.stringify(trimmed2);
|
|
17467
17883
|
}
|
|
17468
17884
|
if (Buffer.byteLength(body, "utf-8") > SHARE_PAYLOAD_MAX_BYTES2) {
|
|
17469
|
-
console.error(
|
|
17885
|
+
console.error(import_picocolors4.default.red("Sanitized receipt still exceeds the 50 KB cloud payload limit."));
|
|
17470
17886
|
process.exit(1);
|
|
17471
17887
|
}
|
|
17472
17888
|
const endpoint = resolveApiUrl();
|
|
17473
|
-
console.log(
|
|
17889
|
+
console.log(import_picocolors4.default.dim(`Publishing receipt ${sanitized.receipt.id} to ${endpoint}...`));
|
|
17474
17890
|
try {
|
|
17475
17891
|
const response = await fetch(endpoint, {
|
|
17476
17892
|
method: "POST",
|
|
@@ -17487,11 +17903,11 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17487
17903
|
const data = await response.json();
|
|
17488
17904
|
persistReceipt(sanitized, data.claimToken);
|
|
17489
17905
|
console.log("");
|
|
17490
|
-
console.log(
|
|
17491
|
-
console.log(` ${
|
|
17492
|
-
console.log(` ${
|
|
17493
|
-
console.log(` ${
|
|
17494
|
-
console.log(
|
|
17906
|
+
console.log(import_picocolors4.default.green(" Published successfully."));
|
|
17907
|
+
console.log(` ${import_picocolors4.default.dim("Public URL:")} ${import_picocolors4.default.underline(import_picocolors4.default.cyan(data.url))}`);
|
|
17908
|
+
console.log(` ${import_picocolors4.default.bold(import_picocolors4.default.yellow(" Claim token (store securely \u2014 shown once):"))}`);
|
|
17909
|
+
console.log(` ${import_picocolors4.default.yellow(data.claimToken)}`);
|
|
17910
|
+
console.log(import_picocolors4.default.dim(" Saved to ~/.qodewk/state.db \u2014 required to prove authorship later."));
|
|
17495
17911
|
console.log("");
|
|
17496
17912
|
await renderTerminalReceipt(sanitized, data.url);
|
|
17497
17913
|
if (options.json) {
|
|
@@ -17499,14 +17915,14 @@ Cloud publishing is disabled (${localFlag ? "--local" : "QODEWK_TELEMETRY=off"})
|
|
|
17499
17915
|
}
|
|
17500
17916
|
} catch (networkErr) {
|
|
17501
17917
|
const message = networkErr instanceof Error ? networkErr.message : String(networkErr);
|
|
17502
|
-
console.log(
|
|
17918
|
+
console.log(import_picocolors4.default.yellow(`
|
|
17503
17919
|
Could not reach cloud API (${message}). Rendered locally:`));
|
|
17504
17920
|
persistReceipt(receipt);
|
|
17505
17921
|
await renderTerminalReceipt(receipt);
|
|
17506
17922
|
}
|
|
17507
17923
|
} catch (err) {
|
|
17508
17924
|
const message = err instanceof Error ? err.message : String(err);
|
|
17509
|
-
console.error(
|
|
17925
|
+
console.error(import_picocolors4.default.red(`Error sharing receipt: ${message}`));
|
|
17510
17926
|
process.exit(1);
|
|
17511
17927
|
}
|
|
17512
17928
|
});
|
|
@@ -17524,35 +17940,35 @@ hookCommand.command("install").description("Install non-blocking post-commit and
|
|
|
17524
17940
|
try {
|
|
17525
17941
|
const hooksDir = resolveGitHooksDir();
|
|
17526
17942
|
if (!hooksDir) {
|
|
17527
|
-
console.error(
|
|
17943
|
+
console.error(import_picocolors4.default.red("Error: Current directory is not a Git repository (.git not found)."));
|
|
17528
17944
|
process.exit(1);
|
|
17529
17945
|
}
|
|
17530
|
-
if (!
|
|
17531
|
-
|
|
17946
|
+
if (!fs15.existsSync(hooksDir)) {
|
|
17947
|
+
fs15.mkdirSync(hooksDir, { recursive: true });
|
|
17532
17948
|
}
|
|
17533
17949
|
const targets = ["post-commit", "post-rewrite"];
|
|
17534
17950
|
let installed = 0;
|
|
17535
17951
|
let existing = 0;
|
|
17536
17952
|
for (const name of targets) {
|
|
17537
|
-
const result = installHookFile(
|
|
17953
|
+
const result = installHookFile(path16.join(hooksDir, name));
|
|
17538
17954
|
if (result === "installed") installed++;
|
|
17539
17955
|
else existing++;
|
|
17540
17956
|
}
|
|
17541
17957
|
if (installed === 0 && existing > 0) {
|
|
17542
|
-
console.log(
|
|
17958
|
+
console.log(import_picocolors4.default.yellow("Qodewk Git hooks are already installed (post-commit, post-rewrite)."));
|
|
17543
17959
|
return;
|
|
17544
17960
|
}
|
|
17545
17961
|
console.log(
|
|
17546
|
-
|
|
17962
|
+
import_picocolors4.default.green(
|
|
17547
17963
|
`\u2713 Non-blocking Qodewk hooks installed in ${hooksDir} (post-commit${installed > 1 || existing > 0 ? ", post-rewrite" : installed === 1 && targets.length === 2 ? " + post-rewrite" : ""})`
|
|
17548
17964
|
)
|
|
17549
17965
|
);
|
|
17550
17966
|
if (existing > 0) {
|
|
17551
|
-
console.log(
|
|
17967
|
+
console.log(import_picocolors4.default.dim(` (${existing} hook file(s) already contained the Qodewk marker)`));
|
|
17552
17968
|
}
|
|
17553
17969
|
} catch (err) {
|
|
17554
17970
|
const message = err instanceof Error ? err.message : String(err);
|
|
17555
|
-
console.error(
|
|
17971
|
+
console.error(import_picocolors4.default.red(`Failed to install Git hook: ${message}`));
|
|
17556
17972
|
process.exit(1);
|
|
17557
17973
|
}
|
|
17558
17974
|
});
|
|
@@ -17560,23 +17976,42 @@ hookCommand.command("uninstall").description("Remove Qodewk post-commit and post
|
|
|
17560
17976
|
try {
|
|
17561
17977
|
const hooksDir = resolveGitHooksDir();
|
|
17562
17978
|
if (!hooksDir) {
|
|
17563
|
-
console.log(
|
|
17979
|
+
console.log(import_picocolors4.default.yellow("No Git repository found."));
|
|
17564
17980
|
return;
|
|
17565
17981
|
}
|
|
17566
17982
|
const targets = ["post-commit", "post-rewrite"];
|
|
17567
17983
|
let removed = 0;
|
|
17568
17984
|
for (const name of targets) {
|
|
17569
|
-
const result = uninstallHookFile(
|
|
17985
|
+
const result = uninstallHookFile(path16.join(hooksDir, name));
|
|
17570
17986
|
if (result === "removed") removed++;
|
|
17571
17987
|
}
|
|
17572
17988
|
if (removed === 0) {
|
|
17573
|
-
console.log(
|
|
17989
|
+
console.log(import_picocolors4.default.yellow("Qodewk hooks are not installed."));
|
|
17574
17990
|
return;
|
|
17575
17991
|
}
|
|
17576
|
-
console.log(
|
|
17992
|
+
console.log(import_picocolors4.default.green(`\u2713 Qodewk hook markers removed from ${removed} file(s).`));
|
|
17993
|
+
} catch (err) {
|
|
17994
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17995
|
+
console.error(import_picocolors4.default.red(`Failed to uninstall hook: ${message}`));
|
|
17996
|
+
process.exit(1);
|
|
17997
|
+
}
|
|
17998
|
+
});
|
|
17999
|
+
hookCommand.command("test").aliases(["verify", "check"]).description("Verify non-blocking Git hook installation and benchmark latency (< 5ms invariant)").option("-j, --json", "Output benchmark in JSON format").action(async (options) => {
|
|
18000
|
+
try {
|
|
18001
|
+
const hooks = auditGitHooks();
|
|
18002
|
+
const benchmark = await benchmarkHookLatency();
|
|
18003
|
+
const isJson = Boolean(options.json || program2.opts().json);
|
|
18004
|
+
if (isJson) {
|
|
18005
|
+
console.log(JSON.stringify({ hooks, benchmark }, null, 2));
|
|
18006
|
+
} else {
|
|
18007
|
+
console.log(formatHookTestReport(hooks, benchmark));
|
|
18008
|
+
}
|
|
18009
|
+
if (!benchmark.passedInvariant) {
|
|
18010
|
+
process.exit(1);
|
|
18011
|
+
}
|
|
17577
18012
|
} catch (err) {
|
|
17578
18013
|
const message = err instanceof Error ? err.message : String(err);
|
|
17579
|
-
console.error(
|
|
18014
|
+
console.error(import_picocolors4.default.red(`Error testing hooks: ${message}`));
|
|
17580
18015
|
process.exit(1);
|
|
17581
18016
|
}
|
|
17582
18017
|
});
|
|
@@ -17585,7 +18020,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
17585
18020
|
try {
|
|
17586
18021
|
const receipt = await readGitReceiptNote(commit);
|
|
17587
18022
|
if (!receipt) {
|
|
17588
|
-
console.log(
|
|
18023
|
+
console.log(import_picocolors4.default.yellow(`No Qodewk receipt note found on commit '${commit}'.`));
|
|
17589
18024
|
return;
|
|
17590
18025
|
}
|
|
17591
18026
|
if (opts.json) {
|
|
@@ -17595,7 +18030,7 @@ notesCmd.command("show [commit]").description("Display Qodewk receipt attached t
|
|
|
17595
18030
|
}
|
|
17596
18031
|
} catch (err) {
|
|
17597
18032
|
const message = err instanceof Error ? err.message : String(err);
|
|
17598
|
-
console.error(
|
|
18033
|
+
console.error(import_picocolors4.default.red(`Error reading Git note: ${message}`));
|
|
17599
18034
|
process.exit(1);
|
|
17600
18035
|
}
|
|
17601
18036
|
});
|
|
@@ -17604,11 +18039,11 @@ notesCmd.command("write [commit]").description("Generate and attach receipt to a
|
|
|
17604
18039
|
const receipt = await generateReceipt({ headSha: commit });
|
|
17605
18040
|
await writeGitReceiptNote(receipt.repository.headSha, receipt);
|
|
17606
18041
|
console.log(
|
|
17607
|
-
|
|
18042
|
+
import_picocolors4.default.green(`\u2713 Attached receipt note to ${receipt.repository.headSha.slice(0, 7)} (refs/notes/qodewk)`)
|
|
17608
18043
|
);
|
|
17609
18044
|
} catch (err) {
|
|
17610
18045
|
const message = err instanceof Error ? err.message : String(err);
|
|
17611
|
-
console.error(
|
|
18046
|
+
console.error(import_picocolors4.default.red(`Error writing Git note: ${message}`));
|
|
17612
18047
|
process.exit(1);
|
|
17613
18048
|
}
|
|
17614
18049
|
});
|
|
@@ -17616,16 +18051,16 @@ notesCmd.command("list").description("List all commits with attached Qodewk rece
|
|
|
17616
18051
|
try {
|
|
17617
18052
|
const shas = await listGitReceiptNotes();
|
|
17618
18053
|
if (shas.length === 0) {
|
|
17619
|
-
console.log(
|
|
18054
|
+
console.log(import_picocolors4.default.yellow("No Qodewk Git notes found in repository."));
|
|
17620
18055
|
return;
|
|
17621
18056
|
}
|
|
17622
|
-
console.log(
|
|
18057
|
+
console.log(import_picocolors4.default.bold(`Found ${shas.length} commit note(s) in refs/notes/qodewk:`));
|
|
17623
18058
|
for (const sha of shas) {
|
|
17624
|
-
console.log(` ${
|
|
18059
|
+
console.log(` ${import_picocolors4.default.cyan(sha.slice(0, 10))} ${import_picocolors4.default.dim(sha)}`);
|
|
17625
18060
|
}
|
|
17626
18061
|
} catch (err) {
|
|
17627
18062
|
const message = err instanceof Error ? err.message : String(err);
|
|
17628
|
-
console.error(
|
|
18063
|
+
console.error(import_picocolors4.default.red(`Error listing Git notes: ${message}`));
|
|
17629
18064
|
process.exit(1);
|
|
17630
18065
|
}
|
|
17631
18066
|
});
|