skillwiki 0.9.21 → 0.9.23

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/cli.js CHANGED
@@ -8,10 +8,6 @@ import {
8
8
  normalizeDistTag,
9
9
  semverGt
10
10
  } from "./chunk-E6UWZ3S3.js";
11
- import {
12
- git,
13
- gitStrict
14
- } from "./chunk-TPS5XD2J.js";
15
11
 
16
12
  // src/cli.ts
17
13
  import { join as join49 } from "path";
@@ -3529,6 +3525,7 @@ function buildCliSurface() {
3529
3525
  memoryCmd2.command("topics").option("--project <slug>").option("--limit <n>").option("--wiki <name>");
3530
3526
  memoryCmd2.command("index").requiredOption("--project <slug>").option("--check").option("--if-stale").option("--wiki <name>");
3531
3527
  memoryCmd2.command("recall").requiredOption("--project <slug>").requiredOption("--topic <slug>").option("--scope <scope>").option("--limit <n>").option("--wiki <name>");
3528
+ memoryCmd2.command("review").requiredOption("--project <slug>").option("--dry-run").option("--wiki <name>");
3532
3529
  memoryCmd2.command("import").requiredOption("--from <path>").requiredOption("--project <slug>").option("--dry-run").option("--apply").option("--max-bytes <n>").option("--wiki <name>");
3533
3530
  const fleetCmd2 = program2.commands.find((c) => c.name() === "fleet");
3534
3531
  fleetCmd2.command("validate");
@@ -9142,6 +9139,41 @@ async function runMemoryRecall(input) {
9142
9139
  })
9143
9140
  };
9144
9141
  }
9142
+ async function runMemoryReview(input) {
9143
+ const scan = await scanVault(input.vault);
9144
+ if (!scan.ok) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: scan };
9145
+ const state = await buildMemoryIndexState(scan.data.allMarkdown, input.project);
9146
+ const checked = await checkMemoryIndex(input.vault, input.project, state);
9147
+ if (!checked.ok) {
9148
+ return {
9149
+ exitCode: checked.error.exitCode,
9150
+ result: checked.error.result
9151
+ };
9152
+ }
9153
+ const findings = buildMemoryReviewFindings({
9154
+ project: input.project,
9155
+ status: checked.data,
9156
+ indexState: state,
9157
+ reviewPages: state.reviewPages
9158
+ });
9159
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
9160
+ return {
9161
+ exitCode: ExitCode.OK,
9162
+ result: ok({
9163
+ project: input.project,
9164
+ generated_at: generatedAt,
9165
+ cache: {
9166
+ present: checked.data.cache_present,
9167
+ ...checked.data.generated_at ? { generated_at: checked.data.generated_at } : {},
9168
+ stale: checked.data.stale,
9169
+ source_hash_mismatches: checked.data.drift.changed_sources
9170
+ },
9171
+ findings,
9172
+ files_written: [],
9173
+ humanHint: renderMemoryReviewHint(input.project, checked.data, findings)
9174
+ })
9175
+ };
9176
+ }
9145
9177
  async function runMemoryImport(input) {
9146
9178
  const scan = await scanVault(input.vault);
9147
9179
  if (!scan.ok) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: scan };
@@ -9201,14 +9233,18 @@ async function buildMemoryIndexState(pages, project) {
9201
9233
  const warnings = [];
9202
9234
  const sourcePages = dedupePages(pages);
9203
9235
  const sources = [];
9236
+ const reviewPages = [];
9204
9237
  for (const page of sourcePages) {
9205
- const source = await readMemorySource(page, project, warnings);
9206
- if (source) sources.push(source);
9238
+ const memoryPage = await readMemoryPage(page, project, warnings);
9239
+ if (!memoryPage) continue;
9240
+ sources.push(memoryPage.source);
9241
+ if (memoryPage.reviewPage) reviewPages.push(memoryPage.reviewPage);
9207
9242
  }
9208
9243
  return {
9209
9244
  sources,
9210
9245
  topics: buildTopics(project, sources),
9211
- warnings
9246
+ warnings,
9247
+ reviewPages
9212
9248
  };
9213
9249
  }
9214
9250
  async function checkMemoryIndex(vault, project, current) {
@@ -9294,6 +9330,175 @@ function emptyMemoryIndexDrift() {
9294
9330
  changed_sources: []
9295
9331
  };
9296
9332
  }
9333
+ async function readMemoryPage(page, project, warnings) {
9334
+ const text = await readPage(page);
9335
+ const fm = extractFrontmatter(text);
9336
+ if (!fm.ok) return null;
9337
+ const rawTopics = typeof fm.data.memory_topics === "string" ? [fm.data.memory_topics] : stringArray(fm.data.memory_topics);
9338
+ if (rawTopics.length === 0) return null;
9339
+ const topics = normalizeMemoryTopics(fm.data.memory_topics, page.relPath, warnings);
9340
+ if (topics.length === 0) return null;
9341
+ const scope = stringField2(fm.data.memory_scope);
9342
+ const projects = memoryProjects(page.relPath, fm.data);
9343
+ if (!projects.includes(project) && scope !== "global" && scope !== "cross-agent") return null;
9344
+ const privacy = stringField2(fm.data.memory_privacy) || "local";
9345
+ if (privacy === "secret-blocked") {
9346
+ warnings.push(`${page.relPath}: skipped secret-blocked memory`);
9347
+ return null;
9348
+ }
9349
+ const status = stringField2(fm.data.memory_status) || "active";
9350
+ if (status === "archived" || status === "rejected") return null;
9351
+ const metadataGaps = [];
9352
+ if (!scope) metadataGaps.push("memory_scope");
9353
+ if (!stringField2(fm.data.memory_policy)) metadataGaps.push("memory_policy");
9354
+ if (!stringField2(fm.data.memory_privacy)) metadataGaps.push("memory_privacy");
9355
+ if (!stringField2(fm.data.memory_status)) metadataGaps.push("memory_status");
9356
+ if (!stringField2(fm.data.last_seen) && !stringField2(fm.data.updated) && !stringField2(fm.data.ingested)) {
9357
+ metadataGaps.push("freshness");
9358
+ }
9359
+ const split = splitFrontmatter(text);
9360
+ const body = split.ok ? split.data.body : text;
9361
+ const updated = stringField2(fm.data.last_seen) || stringField2(fm.data.updated) || stringField2(fm.data.ingested) || dateFromPath2(page.relPath);
9362
+ const title = stringField2(fm.data.title) || page.relPath.split("/").pop()?.replace(/\.md$/, "") || page.relPath;
9363
+ return {
9364
+ source: {
9365
+ path: page.relPath,
9366
+ title,
9367
+ summary: summarize2(body),
9368
+ updated,
9369
+ hash: createHash8("sha256").update(Buffer.from(body, "utf8")).digest("hex"),
9370
+ topics,
9371
+ project,
9372
+ ...stringField2(fm.data.memory_kind) ? { memory_kind: stringField2(fm.data.memory_kind) } : {},
9373
+ ...scope ? { memory_scope: scope } : {},
9374
+ ...stringField2(fm.data.memory_policy) ? { memory_policy: stringField2(fm.data.memory_policy) } : {},
9375
+ memory_privacy: privacy,
9376
+ memory_status: status
9377
+ },
9378
+ ...metadataGaps.length > 0 ? {
9379
+ reviewPage: {
9380
+ path: page.relPath,
9381
+ metadataGaps
9382
+ }
9383
+ } : {}
9384
+ };
9385
+ }
9386
+ function buildMemoryReviewFindings(input) {
9387
+ const findings = [];
9388
+ if (!input.status.cache_present) {
9389
+ findings.push({
9390
+ id: `cache_missing:${input.project}`,
9391
+ severity: "warn",
9392
+ kind: "cache_missing",
9393
+ message: `memory cache for ${input.project} is missing`,
9394
+ suggested_action: `Run skillwiki memory index --project ${input.project} to build the local cache.`
9395
+ });
9396
+ } else if (input.status.stale) {
9397
+ findings.push({
9398
+ id: `cache_stale:${input.project}`,
9399
+ severity: "warn",
9400
+ kind: "cache_stale",
9401
+ message: `memory cache for ${input.project} is stale: ${input.status.drift.missing_sources.length} missing, ${input.status.drift.removed_sources.length} removed, ${input.status.drift.changed_sources.length} changed source(s)`,
9402
+ suggested_action: `Run skillwiki memory index --project ${input.project} or --if-stale to refresh the local cache.`
9403
+ });
9404
+ }
9405
+ for (const path of input.status.drift.changed_sources) {
9406
+ findings.push({
9407
+ id: `source_hash_drift:${path}`,
9408
+ severity: "warn",
9409
+ kind: "source_hash_drift",
9410
+ path,
9411
+ message: `${path} changed since the last cache build`,
9412
+ suggested_action: `Refresh the cache for ${input.project} and review whether the source summary still matches.`
9413
+ });
9414
+ }
9415
+ for (const warning of input.indexState.warnings) {
9416
+ const parsed = parseInvalidTopicWarning(warning);
9417
+ if (!parsed) continue;
9418
+ findings.push({
9419
+ id: `invalid_topic_slug:${parsed.path}:${parsed.topic}`,
9420
+ severity: "warn",
9421
+ kind: "invalid_topic_slug",
9422
+ path: parsed.path,
9423
+ topic: parsed.topic,
9424
+ message: `${parsed.path} declares invalid memory topic slug ${parsed.topic}`,
9425
+ suggested_action: "Normalize the topic slug to lowercase kebab-case so memory index and review can include it."
9426
+ });
9427
+ }
9428
+ for (const page of input.reviewPages) {
9429
+ if (page.metadataGaps.length === 0) continue;
9430
+ findings.push({
9431
+ id: `metadata_gap:${page.path}`,
9432
+ severity: "warn",
9433
+ kind: "metadata_gap",
9434
+ path: page.path,
9435
+ message: `${page.path} is missing explicit memory metadata: ${page.metadataGaps.join(", ")}`,
9436
+ suggested_action: "Add the missing frontmatter fields before relying on this source for cross-device memory review."
9437
+ });
9438
+ }
9439
+ const byTopic = groupSourcesByTopic(input.indexState.sources);
9440
+ for (const [topic, sources] of byTopic.entries()) {
9441
+ if (sources.length === 1) {
9442
+ findings.push({
9443
+ id: `sparse_topic:${topic}`,
9444
+ severity: "info",
9445
+ kind: "sparse_topic",
9446
+ topic,
9447
+ ...sources[0]?.path ? { path: sources[0].path } : {},
9448
+ message: `topic ${topic} has only one active memory source`,
9449
+ suggested_action: "Decide whether the topic needs more coverage or should stay intentionally narrow."
9450
+ });
9451
+ }
9452
+ const hasProjectSource = sources.some((source) => isProjectMemorySource(source, input.project));
9453
+ const hasNonProjectScope = sources.some((source) => source.memory_scope === "global" || source.memory_scope === "cross-agent");
9454
+ if (hasProjectSource && hasNonProjectScope) {
9455
+ findings.push({
9456
+ id: `scope_gap:${topic}`,
9457
+ severity: "info",
9458
+ kind: "scope_gap",
9459
+ topic,
9460
+ message: `topic ${topic} mixes project and non-project memory scopes`,
9461
+ suggested_action: `Use skillwiki memory recall --project ${input.project} --topic ${topic} --scope <project|global|cross-agent|all> when reviewing this topic.`
9462
+ });
9463
+ }
9464
+ if (sources.length >= 3) {
9465
+ findings.push({
9466
+ id: `consolidation_candidate:${topic}`,
9467
+ severity: "info",
9468
+ kind: "consolidation_candidate",
9469
+ topic,
9470
+ message: `topic ${topic} has ${sources.length} active memory sources and may be ready for consolidation`,
9471
+ suggested_action: "Review this topic in office-hours or proj-distill before promoting or merging related memory pages."
9472
+ });
9473
+ }
9474
+ }
9475
+ return findings.sort(compareMemoryReviewFindings);
9476
+ }
9477
+ function parseInvalidTopicWarning(warning) {
9478
+ const match = warning.match(/^(.*): invalid memory topic slug (.+)$/);
9479
+ if (!match) return null;
9480
+ return {
9481
+ path: match[1] ?? "",
9482
+ topic: match[2] ?? ""
9483
+ };
9484
+ }
9485
+ function groupSourcesByTopic(sources) {
9486
+ const byTopic = /* @__PURE__ */ new Map();
9487
+ for (const source of sources) {
9488
+ for (const topic of source.topics) {
9489
+ const list = byTopic.get(topic) ?? [];
9490
+ list.push(source);
9491
+ byTopic.set(topic, list);
9492
+ }
9493
+ }
9494
+ return byTopic;
9495
+ }
9496
+ function compareMemoryReviewFindings(a, b) {
9497
+ return severityRank(b.severity) - severityRank(a.severity) || a.kind.localeCompare(b.kind) || (a.topic ?? "").localeCompare(b.topic ?? "") || (a.path ?? "").localeCompare(b.path ?? "") || a.id.localeCompare(b.id);
9498
+ }
9499
+ function severityRank(severity) {
9500
+ return severity === "warn" ? 2 : 1;
9501
+ }
9297
9502
  function renderMemoryIndexStatusHint(status) {
9298
9503
  if (!status.cache_present) {
9299
9504
  return `memory index cache missing for ${status.project}; rebuild with memory index --project ${status.project}`;
@@ -9539,6 +9744,9 @@ function normalizeRecallScope(value) {
9539
9744
  if (!value) return void 0;
9540
9745
  return isRecallScope(value) ? value : void 0;
9541
9746
  }
9747
+ function isValidMemoryTopicSlug(value) {
9748
+ return /^[a-z0-9][a-z0-9-]*$/.test(value);
9749
+ }
9542
9750
  function isRecallScope(value) {
9543
9751
  return value === "project" || value === "global" || value === "cross-agent" || value === "all";
9544
9752
  }
@@ -9566,6 +9774,12 @@ function renderRecallHint(topic, sources) {
9566
9774
  if (sources.length === 0) return `no memory sources found for topic ${topic}`;
9567
9775
  return sources.map((source) => `${source.updated} ${source.title} (${source.path}) \u2014 ${source.summary}`).join("\n");
9568
9776
  }
9777
+ function renderMemoryReviewHint(project, status, findings) {
9778
+ const warns = findings.filter((finding) => finding.severity === "warn").length;
9779
+ const infos = findings.length - warns;
9780
+ const cacheStatus = !status.cache_present ? "cache missing" : status.stale ? "cache stale" : "cache current";
9781
+ return `memory review for ${project}: ${findings.length} finding(s) (${warns} warn, ${infos} info); ${cacheStatus}`;
9782
+ }
9569
9783
  function memoryCacheRelPath(project) {
9570
9784
  return `.skillwiki/memory/${project}/topics.json`;
9571
9785
  }
@@ -9586,46 +9800,11 @@ function dedupePages(pages) {
9586
9800
  }
9587
9801
  return out;
9588
9802
  }
9589
- async function readMemorySource(page, project, warnings) {
9590
- const text = await readPage(page);
9591
- const fm = extractFrontmatter(text);
9592
- if (!fm.ok) return null;
9593
- const topics = normalizeMemoryTopics(fm.data.memory_topics, page.relPath, warnings);
9594
- if (topics.length === 0) return null;
9595
- const projects = memoryProjects(page.relPath, fm.data);
9596
- const scope = stringField2(fm.data.memory_scope);
9597
- if (!projects.includes(project) && scope !== "global" && scope !== "cross-agent") return null;
9598
- const privacy = stringField2(fm.data.memory_privacy) || "local";
9599
- if (privacy === "secret-blocked") {
9600
- warnings.push(`${page.relPath}: skipped secret-blocked memory`);
9601
- return null;
9602
- }
9603
- const status = stringField2(fm.data.memory_status) || "active";
9604
- if (status === "archived" || status === "rejected") return null;
9605
- const split = splitFrontmatter(text);
9606
- const body = split.ok ? split.data.body : text;
9607
- const updated = stringField2(fm.data.last_seen) || stringField2(fm.data.updated) || stringField2(fm.data.ingested) || dateFromPath2(page.relPath);
9608
- const title = stringField2(fm.data.title) || page.relPath.split("/").pop()?.replace(/\.md$/, "") || page.relPath;
9609
- return {
9610
- path: page.relPath,
9611
- title,
9612
- summary: summarize2(body),
9613
- updated,
9614
- hash: createHash8("sha256").update(Buffer.from(body, "utf8")).digest("hex"),
9615
- topics,
9616
- project,
9617
- ...stringField2(fm.data.memory_kind) ? { memory_kind: stringField2(fm.data.memory_kind) } : {},
9618
- ...scope ? { memory_scope: scope } : {},
9619
- ...stringField2(fm.data.memory_policy) ? { memory_policy: stringField2(fm.data.memory_policy) } : {},
9620
- memory_privacy: privacy,
9621
- memory_status: status
9622
- };
9623
- }
9624
9803
  function normalizeMemoryTopics(value, path, warnings) {
9625
9804
  const rawTopics = typeof value === "string" ? [value] : stringArray(value);
9626
9805
  const topics = [];
9627
9806
  for (const topic of rawTopics) {
9628
- if (!/^[a-z0-9][a-z0-9-]*$/.test(topic)) {
9807
+ if (!isValidMemoryTopicSlug(topic)) {
9629
9808
  warnings.push(`${path}: invalid memory topic slug ${topic}`);
9630
9809
  continue;
9631
9810
  }
@@ -10154,6 +10333,19 @@ ${body}`;
10154
10333
  import { existsSync as existsSync17 } from "fs";
10155
10334
  import { join as join42 } from "path";
10156
10335
 
10336
+ // src/utils/git.ts
10337
+ import { execFileSync } from "child_process";
10338
+ function git(cwd, args) {
10339
+ try {
10340
+ return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10341
+ } catch {
10342
+ return "";
10343
+ }
10344
+ }
10345
+ function gitStrict(cwd, args) {
10346
+ return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10347
+ }
10348
+
10157
10349
  // src/utils/sync-lock.ts
10158
10350
  import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "fs";
10159
10351
  import { join as join41 } from "path";
@@ -10264,6 +10456,15 @@ var VAULT_GENERATED_COMMIT_EXCLUDES = [
10264
10456
  ...VAULT_GENERATED_COMMIT_PATHS.map((path) => `:!${path}`)
10265
10457
  ];
10266
10458
  var VAULT_COMMIT_PATHSPEC = [".", ...VAULT_GENERATED_COMMIT_EXCLUDES];
10459
+ function stageVaultContentChanges(vault) {
10460
+ gitStrict(vault, ["add", "-A", "--", "."]);
10461
+ for (const generatedPath of VAULT_GENERATED_COMMIT_PATHS) {
10462
+ try {
10463
+ gitStrict(vault, ["reset", "HEAD", "--", generatedPath]);
10464
+ } catch (_e) {
10465
+ }
10466
+ }
10467
+ }
10267
10468
 
10268
10469
  // src/commands/sync.ts
10269
10470
  function runSyncStatus(input) {
@@ -10390,13 +10591,7 @@ async function runSyncPush(input) {
10390
10591
  };
10391
10592
  }
10392
10593
  try {
10393
- gitStrict(vault, ["add", "-A", "--", ...VAULT_COMMIT_PATHSPEC]);
10394
- for (const generatedPath of VAULT_GENERATED_COMMIT_PATHS) {
10395
- try {
10396
- gitStrict(vault, ["reset", "HEAD", "--", generatedPath]);
10397
- } catch (_e) {
10398
- }
10399
- }
10594
+ stageVaultContentChanges(vault);
10400
10595
  } catch (e) {
10401
10596
  return {
10402
10597
  exitCode: ExitCode.SYNC_PUSH_FAILED,
@@ -11383,15 +11578,8 @@ async function postCommit(vault, exitCode) {
11383
11578
  if (lastOps.length === 0) return;
11384
11579
  const porcelain = git(vault, ["status", "--porcelain", "--", ...VAULT_COMMIT_PATHSPEC]);
11385
11580
  if (!porcelain || porcelain.trim().length === 0) return;
11386
- const { gitStrict: gitStrict2 } = await import("./git-M4WGJ5G3.js");
11387
11581
  try {
11388
- gitStrict2(vault, ["add", "-A", "--", "."]);
11389
- for (const generatedPath of VAULT_GENERATED_COMMIT_PATHS) {
11390
- try {
11391
- gitStrict2(vault, ["reset", "HEAD", "--", generatedPath]);
11392
- } catch (_e) {
11393
- }
11394
- }
11582
+ stageVaultContentChanges(vault);
11395
11583
  } catch (e) {
11396
11584
  process.stderr.write(`auto-commit: git add failed: ${String(e)}
11397
11585
  `);
@@ -11399,7 +11587,7 @@ async function postCommit(vault, exitCode) {
11399
11587
  }
11400
11588
  const commitMessage = lastOps.map((op) => `${op.operation}: ${op.summary} (${op.files.length} files)`).join("; ");
11401
11589
  try {
11402
- gitStrict2(vault, ["commit", "-m", commitMessage]);
11590
+ gitStrict(vault, ["commit", "-m", commitMessage]);
11403
11591
  } catch (e) {
11404
11592
  process.stderr.write(`auto-commit: git commit failed: ${String(e)}
11405
11593
  `);
@@ -11831,6 +12019,15 @@ memoryCmd.command("recall [vault]").description("recall bounded source summaries
11831
12019
  limit: opts.limit
11832
12020
  }), v.vault, { postCommit: false });
11833
12021
  });
12022
+ memoryCmd.command("review [vault]").description("review deterministic memory gaps and cache drift without writing").requiredOption("--project <slug>", "project slug").option("--dry-run", "preview only; writes are not supported on this surface", false).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
12023
+ const v = await resolveVaultArg(vault, opts.wiki);
12024
+ if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
12025
+ else emit(await runMemoryReview({
12026
+ vault: v.vault,
12027
+ project: opts.project,
12028
+ dryRun: !!opts.dryRun
12029
+ }), v.vault, { postCommit: false });
12030
+ });
11834
12031
  memoryCmd.command("import [vault]").description("preview or apply local memory imports into raw captures").requiredOption("--from <path>", "source file or directory to scan").requiredOption("--project <slug>", "project slug").option("--dry-run", "preview only; do not write captures", false).option("--apply", "write validated raw captures for ready entries", false).option("--max-bytes <n>", "reject source files above this size", (s) => parseInt(s, 10), 2e5).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
11835
12032
  const v = await resolveVaultArg(vault, opts.wiki);
11836
12033
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.9.21",
3
+ "version": "0.9.23",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "skillwiki": "dist/cli.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.9.21",
3
+ "version": "0.9.23",
4
4
  "skills": "./",
5
5
  "description": "Project-aware Karpathy-style knowledge base for Claude Code: 18 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.9.21",
3
+ "version": "0.9.23",
4
4
  "description": "Project-aware Karpathy-style knowledge base for Codex with 18 prompt-only skills backed by the deterministic skillwiki CLI.",
5
5
  "author": {
6
6
  "name": "karlorz",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.9.21",
3
+ "version": "0.9.23",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/utils/git.ts
4
- import { execFileSync } from "child_process";
5
- function git(cwd, args) {
6
- try {
7
- return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
8
- } catch {
9
- return "";
10
- }
11
- }
12
- function gitStrict(cwd, args) {
13
- return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
14
- }
15
-
16
- export {
17
- git,
18
- gitStrict
19
- };
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- git,
4
- gitStrict
5
- } from "./chunk-TPS5XD2J.js";
6
- export {
7
- git,
8
- gitStrict
9
- };