skillwiki 0.10.35 → 0.10.37

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.
@@ -484,7 +484,7 @@ var MATCHERS = [
484
484
  },
485
485
  {
486
486
  kind: "password",
487
- re: /\b(?:pass(?:word|wd)?)["']?\s*[:=]\s*["']?([^\s`"']{8,})["']?/gi,
487
+ re: /\b(?:password|passwd)["']?\s*[:=]\s*["']?([^\s`"']{8,})["']?/gi,
488
488
  valueGroup: 1
489
489
  },
490
490
  {
@@ -512,7 +512,7 @@ function isSyntheticPlaceholder(value) {
512
512
  }
513
513
  function isNonSecretTokenCapture(value) {
514
514
  if (value.startsWith("//")) return true;
515
- if (/^[a-z]{2,}(?:-[a-z]{2,})+$/.test(value)) return true;
515
+ if (/^[a-z0-9.]+(?:-[a-z0-9.]+)+$/.test(value) && !/^[0-9a-f]+(?:-[0-9a-f]+)+$/.test(value)) return true;
516
516
  return false;
517
517
  }
518
518
  function collectMatches(text) {
@@ -6,7 +6,7 @@ import {
6
6
  readPage,
7
7
  scanSensitiveContent,
8
8
  splitFrontmatter
9
- } from "./chunk-MIQOBEOW.js";
9
+ } from "./chunk-BS556WUE.js";
10
10
 
11
11
  // src/utils/log-events.ts
12
12
  import { mkdir, open, readFile, readdir } from "fs/promises";
@@ -8,7 +8,7 @@ import {
8
8
  ok,
9
9
  scanSensitiveContent,
10
10
  scanVault
11
- } from "./chunk-MIQOBEOW.js";
11
+ } from "./chunk-BS556WUE.js";
12
12
 
13
13
  // src/utils/atomic-write.ts
14
14
  import { randomBytes } from "crypto";
@@ -8,7 +8,7 @@ import {
8
8
  readLogEvents,
9
9
  resolveExistingRegularFileInsideVault,
10
10
  writeLogEvent
11
- } from "./chunk-K4OGG5KJ.js";
11
+ } from "./chunk-E3JBAURS.js";
12
12
  import {
13
13
  ExitCode,
14
14
  RawSourceSchema,
@@ -19,7 +19,7 @@ import {
19
19
  scanSensitiveContent,
20
20
  scanVault,
21
21
  splitFrontmatter
22
- } from "./chunk-MIQOBEOW.js";
22
+ } from "./chunk-BS556WUE.js";
23
23
 
24
24
  // src/utils/source-lifecycle.ts
25
25
  import { basename } from "path";
@@ -22,12 +22,12 @@ import {
22
22
  runSyncLintDelta,
23
23
  runVaultSyncPullHelper,
24
24
  supersedeStaleReviewRequiredJournals
25
- } from "./chunk-JJ654NVJ.js";
25
+ } from "./chunk-XRBUABGE.js";
26
26
  import {
27
27
  ExitCode,
28
28
  err,
29
29
  ok
30
- } from "./chunk-MIQOBEOW.js";
30
+ } from "./chunk-BS556WUE.js";
31
31
 
32
32
  // src/utils/managed-write-preflight.ts
33
33
  import { existsSync as existsSync3 } from "fs";
@@ -3,11 +3,11 @@ import {
3
3
  ROOT_INDEX_SECTION_ORDER,
4
4
  atomicWriteText,
5
5
  buildRootIndexUniverse
6
- } from "./chunk-XYGGDGHR.js";
6
+ } from "./chunk-IFMHQETQ.js";
7
7
  import {
8
8
  err,
9
9
  ok
10
- } from "./chunk-MIQOBEOW.js";
10
+ } from "./chunk-BS556WUE.js";
11
11
 
12
12
  // src/utils/index-projection.ts
13
13
  import { readFile } from "fs/promises";
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  renderRootIndex,
8
8
  writeRootIndexProjection
9
- } from "./chunk-SNCFIJ5E.js";
9
+ } from "./chunk-QVO332CT.js";
10
10
  import {
11
11
  CONFIG_KEYS,
12
12
  acquireOwnedSyncLock,
@@ -34,15 +34,15 @@ import {
34
34
  snapshotterAliasForLocalHost,
35
35
  toUndirectedWeighted,
36
36
  writeDotenv
37
- } from "./chunk-JJ654NVJ.js";
37
+ } from "./chunk-XRBUABGE.js";
38
38
  import {
39
39
  atomicWriteText,
40
40
  prepareTypedPage
41
- } from "./chunk-XYGGDGHR.js";
41
+ } from "./chunk-IFMHQETQ.js";
42
42
  import {
43
43
  eventPathFor,
44
44
  writeLogEvent
45
- } from "./chunk-K4OGG5KJ.js";
45
+ } from "./chunk-E3JBAURS.js";
46
46
  import {
47
47
  CompoundSchema,
48
48
  ExitCode,
@@ -63,7 +63,7 @@ import {
63
63
  scanVault,
64
64
  splitFrontmatter,
65
65
  systemdPropertyFor
66
- } from "./chunk-MIQOBEOW.js";
66
+ } from "./chunk-BS556WUE.js";
67
67
 
68
68
  // src/commands/log-append.ts
69
69
  import { readFile, stat } from "fs/promises";
@@ -4849,7 +4849,7 @@ async function runQuery(input) {
4849
4849
  }).filter((r) => r.score > 0).sort((a, b) => b.score - a.score || a.path.localeCompare(b.path)).slice(0, limit);
4850
4850
  let pendingSources;
4851
4851
  if (input.includePending) {
4852
- const { runSourcesPending } = await import("./sources-FCZCPOYB.js");
4852
+ const { runSourcesPending } = await import("./sources-LIJAUXFU.js");
4853
4853
  const pending = await runSourcesPending({
4854
4854
  vault: input.vault,
4855
4855
  match: input.text,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  atomicWriteText,
4
4
  buildRootIndexUniverse
5
- } from "./chunk-XYGGDGHR.js";
5
+ } from "./chunk-IFMHQETQ.js";
6
6
  import {
7
7
  authorizeRawOperation,
8
8
  buildSourceReferenceIndex,
@@ -22,7 +22,7 @@ import {
22
22
  resolveExistingRegularFileInsideVault,
23
23
  stripFencedBlocks,
24
24
  writeLogEvent
25
- } from "./chunk-K4OGG5KJ.js";
25
+ } from "./chunk-E3JBAURS.js";
26
26
  import {
27
27
  ExitCode,
28
28
  FleetManifestSchema,
@@ -40,7 +40,7 @@ import {
40
40
  scanVault,
41
41
  splitFrontmatter,
42
42
  vaultIoConcurrency
43
- } from "./chunk-MIQOBEOW.js";
43
+ } from "./chunk-BS556WUE.js";
44
44
 
45
45
  // src/utils/sync-lock.ts
46
46
  import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
package/dist/cli.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  scanConflictMarkerBlocksInText,
39
39
  snapshotterHealthChecks,
40
40
  upsertIndexEntry
41
- } from "./chunk-2X2TCLHR.js";
41
+ } from "./chunk-WJVG3DD5.js";
42
42
  import {
43
43
  normalizeDistTag,
44
44
  readCache,
@@ -51,7 +51,7 @@ import {
51
51
  UNMANAGED_START,
52
52
  renderRootIndex,
53
53
  writeRootIndexProjection
54
- } from "./chunk-SNCFIJ5E.js";
54
+ } from "./chunk-QVO332CT.js";
55
55
  import {
56
56
  VAULT_COMMIT_PATHSPEC,
57
57
  runManagedWritePreflight,
@@ -63,7 +63,7 @@ import {
63
63
  runSyncStatus,
64
64
  runSyncUnlock,
65
65
  stageVaultContentChanges
66
- } from "./chunk-BY7V7QPU.js";
66
+ } from "./chunk-LACQJ6RD.js";
67
67
  import {
68
68
  FLEET_REL_PATH,
69
69
  acquireOwnedSyncLock,
@@ -126,12 +126,12 @@ import {
126
126
  supersedeStaleReviewRequiredJournals,
127
127
  taxonomyCommentForPage,
128
128
  writeDotenv
129
- } from "./chunk-JJ654NVJ.js";
129
+ } from "./chunk-XRBUABGE.js";
130
130
  import {
131
131
  assertTargetInsideVault,
132
132
  atomicWriteText,
133
133
  prepareTypedPage
134
- } from "./chunk-XYGGDGHR.js";
134
+ } from "./chunk-IFMHQETQ.js";
135
135
  import {
136
136
  applySourceDisposition,
137
137
  decodeSourceActionApproval,
@@ -139,7 +139,7 @@ import {
139
139
  inventorySources,
140
140
  planSourceDisposition,
141
141
  runSourcesPending
142
- } from "./chunk-GXT5WTSE.js";
142
+ } from "./chunk-JUUZJJIF.js";
143
143
  import {
144
144
  authorizeRawOperation,
145
145
  buildSourceReferenceIndex,
@@ -155,7 +155,7 @@ import {
155
155
  resolveExistingRegularFileInsideVault,
156
156
  validateLogEvent,
157
157
  writeLogEvent
158
- } from "./chunk-K4OGG5KJ.js";
158
+ } from "./chunk-E3JBAURS.js";
159
159
  import {
160
160
  ExitCode,
161
161
  MetaSchema,
@@ -171,7 +171,7 @@ import {
171
171
  scanSensitiveContent,
172
172
  scanVault,
173
173
  splitFrontmatter
174
- } from "./chunk-MIQOBEOW.js";
174
+ } from "./chunk-BS556WUE.js";
175
175
 
176
176
  // src/cli.ts
177
177
  import { join as join38 } from "path";
@@ -181,11 +181,19 @@ import { Command } from "commander";
181
181
  function printJson(r) {
182
182
  process.stdout.write(JSON.stringify(r) + "\n");
183
183
  }
184
- function printHuman(r) {
184
+ function printHuman(r, opts = {}) {
185
185
  if (r.ok) {
186
186
  if (typeof r.data === "object" && r.data !== null && "humanHint" in r.data) {
187
- process.stdout.write(`${r.data.humanHint}
187
+ const humanHint = r.data.humanHint;
188
+ if (!opts.detailHints?.length) {
189
+ process.stdout.write(`${humanHint}
188
190
  `);
191
+ } else {
192
+ const existingLines = new Set(humanHint.split("\n"));
193
+ const detailLines2 = opts.detailHints.filter((line) => !existingLines.has(line));
194
+ process.stdout.write(`${[humanHint, ...detailLines2].join("\n")}
195
+ `);
196
+ }
189
197
  } else {
190
198
  process.stdout.write(`OK
191
199
  ${formatData(r.data)}
@@ -202,6 +210,45 @@ function formatData(d) {
202
210
  return JSON.stringify(d, null, 2);
203
211
  }
204
212
 
213
+ // src/utils/lint-detail-hints.ts
214
+ function lintDetailHints(data) {
215
+ const record = asRecord(data);
216
+ if (!record) return [];
217
+ const bySeverity = asRecord(record.by_severity);
218
+ if (bySeverity && Array.isArray(bySeverity.error)) {
219
+ return detailLines(bySeverity.error, false);
220
+ }
221
+ return Array.isArray(record.buckets) ? detailLines(record.buckets, true) : [];
222
+ }
223
+ function healthLintDetailHints(data) {
224
+ const record = asRecord(data);
225
+ const components = asRecord(record?.components);
226
+ const lint = asRecord(components?.lint);
227
+ return Array.isArray(lint?.buckets) ? detailLines(lint.buckets, true) : [];
228
+ }
229
+ function detailLines(buckets, requireErrorSeverity) {
230
+ const seen = /* @__PURE__ */ new Set();
231
+ const lines = [];
232
+ for (const bucket of buckets) {
233
+ const record = asRecord(bucket);
234
+ if (!record || requireErrorSeverity && record.severity !== "error") continue;
235
+ const name = nonEmptyBucketName(record);
236
+ if (!name || seen.has(name)) continue;
237
+ seen.add(name);
238
+ lines.push(`detail: skillwiki lint --only ${name} --examples 3`);
239
+ }
240
+ return lines;
241
+ }
242
+ function nonEmptyBucketName(bucket) {
243
+ if (typeof bucket.kind !== "string" || !/^[a-z0-9_]+$/.test(bucket.kind)) return null;
244
+ if (typeof bucket.count === "number") return bucket.count > 0 ? bucket.kind : null;
245
+ if (Array.isArray(bucket.items)) return bucket.items.length > 0 ? bucket.kind : null;
246
+ return null;
247
+ }
248
+ function asRecord(value) {
249
+ return typeof value === "object" && value !== null ? value : null;
250
+ }
251
+
205
252
  // src/utils/deprecation.ts
206
253
  import { readFileSync } from "fs";
207
254
  import { join } from "path";
@@ -2081,8 +2128,9 @@ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync9, re
2081
2128
  import { join as join15 } from "path";
2082
2129
 
2083
2130
  // src/commands/work-validate.ts
2084
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync8 } from "fs";
2131
+ import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
2085
2132
  import { join as join14 } from "path";
2133
+ var GOAL_PLAN_MODE_FILES = /* @__PURE__ */ new Set(["spec.md", "plan.md", "build-report.md"]);
2086
2134
  function normalizeWorkItemRel(workItem) {
2087
2135
  return workItem.replace(/\\/g, "/").replace(/^\.?\//, "");
2088
2136
  }
@@ -2092,6 +2140,22 @@ function scanFileConflicts(relPath, text) {
2092
2140
  function countUnchecked(text) {
2093
2141
  return [...text.matchAll(/^- \[ \]/gm)].length;
2094
2142
  }
2143
+ function isGoalPlanMode(value) {
2144
+ return typeof value === "string" && ["goal-plan", "goal"].includes(value.trim().toLowerCase());
2145
+ }
2146
+ function isDirectory(path) {
2147
+ try {
2148
+ return statSync2(path).isDirectory();
2149
+ } catch {
2150
+ return false;
2151
+ }
2152
+ }
2153
+ function isCompletedStatus(status) {
2154
+ return status === "completed" || status === "complete" || status === "done";
2155
+ }
2156
+ function planClaimsCompletion(status, goalPlanMode) {
2157
+ return goalPlanMode ? isCompletedStatus(status) : status === "completed" || status === "complete";
2158
+ }
2095
2159
  function extractPrMetadata(fm) {
2096
2160
  const keys = [
2097
2161
  "pr_url",
@@ -2148,21 +2212,31 @@ async function runWorkValidate(input) {
2148
2212
  }
2149
2213
  const findings = [];
2150
2214
  const status = {};
2151
- let evidencePresent = false;
2152
2215
  let unchecked = 0;
2153
2216
  let conflicts = 0;
2154
2217
  let decisionsPresent = false;
2155
2218
  let prMetadata = null;
2156
2219
  const files = readdirSync(workDir).filter((f) => f.endsWith(".md"));
2157
- if (!files.includes("spec.md")) {
2158
- findings.push({ code: "missing_spec", path: `${rel}/spec.md`, message: "spec.md is required" });
2159
- }
2160
- for (const file of files) {
2161
- const abs = join14(workDir, file);
2162
- let text;
2220
+ const markdownFiles = files.map((file) => {
2163
2221
  try {
2164
- text = readFileSync8(abs, "utf8");
2222
+ const text = readFileSync8(join14(workDir, file), "utf8");
2223
+ return { file, text, frontmatter: extractFrontmatter(text) };
2165
2224
  } catch {
2225
+ return { file, text: null, frontmatter: null };
2226
+ }
2227
+ });
2228
+ const goalPlanMode = markdownFiles.some(
2229
+ ({ file, frontmatter }) => GOAL_PLAN_MODE_FILES.has(file) && frontmatter?.ok && isGoalPlanMode(frontmatter.data.mode)
2230
+ );
2231
+ let evidencePresent = goalPlanMode && (files.includes("build-report.md") || isDirectory(join14(workDir, "evidence")));
2232
+ if (!files.includes("spec.md") && !goalPlanMode) {
2233
+ findings.push({ code: "missing_spec", path: `${rel}/spec.md`, message: "spec.md is required" });
2234
+ }
2235
+ if (goalPlanMode && !files.includes("plan.md")) {
2236
+ findings.push({ code: "missing_plan", path: `${rel}/plan.md`, message: "goal-plan mode requires plan.md" });
2237
+ }
2238
+ for (const { file, text, frontmatter } of markdownFiles) {
2239
+ if (text === null || frontmatter === null) {
2166
2240
  findings.push({ code: "unreadable", path: `${rel}/${file}`, message: "cannot read file" });
2167
2241
  continue;
2168
2242
  }
@@ -2176,14 +2250,17 @@ async function runWorkValidate(input) {
2176
2250
  });
2177
2251
  }
2178
2252
  unchecked += countUnchecked(text);
2179
- const fm = extractFrontmatter(text);
2180
- if (file === "spec.md" && fm.ok) {
2181
- status.spec = typeof fm.data.status === "string" ? fm.data.status : void 0;
2182
- prMetadata = extractPrMetadata(fm.data);
2183
- validatePrMetadata(prMetadata, findings);
2184
- }
2185
- if (file === "plan.md" && fm.ok) {
2186
- status.plan = typeof fm.data.status === "string" ? fm.data.status : void 0;
2253
+ if (frontmatter.ok) {
2254
+ if (file === "spec.md") {
2255
+ status.spec = typeof frontmatter.data.status === "string" ? frontmatter.data.status : void 0;
2256
+ }
2257
+ if (file === "plan.md") {
2258
+ status.plan = typeof frontmatter.data.status === "string" ? frontmatter.data.status : void 0;
2259
+ }
2260
+ if (file === (goalPlanMode ? "plan.md" : "spec.md")) {
2261
+ prMetadata = extractPrMetadata(frontmatter.data);
2262
+ validatePrMetadata(prMetadata, findings);
2263
+ }
2187
2264
  }
2188
2265
  if (file === "evidence.md" || file === "retro.md") {
2189
2266
  evidencePresent = true;
@@ -2196,25 +2273,27 @@ async function runWorkValidate(input) {
2196
2273
  }
2197
2274
  }
2198
2275
  if (input.requireComplete) {
2199
- if (status.spec && status.spec !== "completed" && status.spec !== "complete" && status.spec !== "done") {
2276
+ const specSource = goalPlanMode ? "plan" : "spec";
2277
+ const specSourceStatus = goalPlanMode ? status.plan : status.spec;
2278
+ if (specSourceStatus && !isCompletedStatus(specSourceStatus)) {
2200
2279
  findings.push({
2201
2280
  code: "spec_not_completed",
2202
- path: `${rel}/spec.md`,
2203
- message: `spec status is ${status.spec}, expected completed`
2281
+ path: `${rel}/${specSource}.md`,
2282
+ message: `${specSource} status is ${specSourceStatus}, expected completed`
2204
2283
  });
2205
2284
  }
2206
- if (!status.spec) {
2285
+ if (!specSourceStatus) {
2207
2286
  findings.push({
2208
2287
  code: "spec_status_missing",
2209
- path: `${rel}/spec.md`,
2210
- message: "spec frontmatter status missing for completion"
2288
+ path: `${rel}/${specSource}.md`,
2289
+ message: `${specSource} frontmatter status missing for completion`
2211
2290
  });
2212
2291
  }
2213
2292
  if (!evidencePresent) {
2214
2293
  findings.push({
2215
2294
  code: "missing_evidence",
2216
2295
  path: rel,
2217
- message: "completion requires evidence.md or retro.md"
2296
+ message: goalPlanMode ? "completion requires build-report.md, evidence/, evidence.md, or retro.md" : "completion requires evidence.md or retro.md"
2218
2297
  });
2219
2298
  }
2220
2299
  if (unchecked > 0) {
@@ -2225,12 +2304,12 @@ async function runWorkValidate(input) {
2225
2304
  });
2226
2305
  }
2227
2306
  }
2228
- if (status.plan === "completed" || status.plan === "complete") {
2229
- if (!evidencePresent) {
2307
+ if (planClaimsCompletion(status.plan, goalPlanMode)) {
2308
+ if (!evidencePresent && !(goalPlanMode && input.requireComplete)) {
2230
2309
  findings.push({
2231
2310
  code: "missing_evidence",
2232
2311
  path: rel,
2233
- message: "plan is completed but evidence/retro is missing"
2312
+ message: goalPlanMode ? "plan is completed but build-report.md, evidence/, evidence.md, or retro.md is missing" : "plan is completed but evidence/retro is missing"
2234
2313
  });
2235
2314
  }
2236
2315
  }
@@ -3348,7 +3427,7 @@ ${fmRewritten}
3348
3427
  }
3349
3428
  let indexUpdated = false;
3350
3429
  if (!isRaw) {
3351
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-WUAKRTAE.js");
3430
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-ZXFN5DT4.js");
3352
3431
  const before = await readFile7(join18(input.vault, "index.md"), "utf8").catch(() => "");
3353
3432
  const fullTarget = relPath.replace(/\.md$/, "");
3354
3433
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -3468,7 +3547,7 @@ async function runRemove(input) {
3468
3547
  if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
3469
3548
  const { readFile: readFile20 } = await import("fs/promises");
3470
3549
  const { join: pathJoin } = await import("path");
3471
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-WUAKRTAE.js");
3550
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-ZXFN5DT4.js");
3472
3551
  const before = await readFile20(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
3473
3552
  const fullTarget = relPath.replace(/\.md$/, "");
3474
3553
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -8152,7 +8231,7 @@ function releaseSnapshotFlock(handle) {
8152
8231
  }
8153
8232
 
8154
8233
  // src/commands/backup.ts
8155
- import { statSync as statSync2, readdirSync as readdirSync2, readFileSync as readFileSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
8234
+ import { statSync as statSync3, readdirSync as readdirSync2, readFileSync as readFileSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
8156
8235
  import { join as join31, relative as relative3, dirname as dirname10 } from "path";
8157
8236
  import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
8158
8237
 
@@ -8201,7 +8280,7 @@ async function runBackupSync(input) {
8201
8280
  const files = [...walkMarkdown(input.vault, input.vault)];
8202
8281
  for (const relPath of files) {
8203
8282
  const absPath = join31(input.vault, relPath);
8204
- const localStat = statSync2(absPath);
8283
+ const localStat = statSync3(absPath);
8205
8284
  let needsUpload = true;
8206
8285
  try {
8207
8286
  const head = await client.send(new HeadObjectCommand({ Bucket: input.bucket, Key: relPath }));
@@ -8278,7 +8357,7 @@ async function runBackupRestore(input) {
8278
8357
  if (!obj.Key) continue;
8279
8358
  const localPath = join31(target, obj.Key);
8280
8359
  try {
8281
- const localStat = statSync2(localPath);
8360
+ const localStat = statSync3(localPath);
8282
8361
  if (obj.LastModified && localStat.mtime > obj.LastModified) {
8283
8362
  conflicts++;
8284
8363
  continue;
@@ -8322,7 +8401,7 @@ async function runBackupRestore(input) {
8322
8401
  }
8323
8402
 
8324
8403
  // src/commands/status.ts
8325
- import { existsSync as existsSync10, statSync as statSync3 } from "fs";
8404
+ import { existsSync as existsSync10, statSync as statSync4 } from "fs";
8326
8405
  import { readFile as readFile16 } from "fs/promises";
8327
8406
  import { join as join32 } from "path";
8328
8407
  async function runStatus(input) {
@@ -8367,7 +8446,7 @@ async function runStatus(input) {
8367
8446
  let maxTime = 0;
8368
8447
  for (const page of allPages) {
8369
8448
  try {
8370
- const st = statSync3(page.absPath);
8449
+ const st = statSync4(page.absPath);
8371
8450
  if (st.mtimeMs > maxTime) {
8372
8451
  maxTime = st.mtimeMs;
8373
8452
  lastModified = st.mtime.toISOString();
@@ -9256,9 +9335,9 @@ async function postCommit(vault, exitCode) {
9256
9335
  }
9257
9336
 
9258
9337
  // src/commands/write-preflight.ts
9259
- import { existsSync as existsSync14, readFileSync as readFileSync17, statSync as statSync4 } from "fs";
9338
+ import { existsSync as existsSync14, readFileSync as readFileSync17, statSync as statSync5 } from "fs";
9260
9339
  async function runWritePreflightCommand(input) {
9261
- if (!existsSync14(input.vault) || !statSync4(input.vault).isDirectory()) {
9340
+ if (!existsSync14(input.vault) || !statSync5(input.vault).isDirectory()) {
9262
9341
  return {
9263
9342
  exitCode: ExitCode.VAULT_PATH_INVALID,
9264
9343
  result: err(GateError.VAULT_PATH_INVALID, { path: input.vault })
@@ -9322,9 +9401,16 @@ var program = new Command();
9322
9401
  program.name("skillwiki").description("Deterministic helpers for CodeWiki skills").version(pkg.version);
9323
9402
  program.option("--human", "render terminal-readable output instead of JSON");
9324
9403
  async function emit(r, vault, opts) {
9325
- if (program.opts().human) printHuman(r.result);
9326
- else printJson(r.result);
9404
+ if (program.opts().human) {
9405
+ const detailHints = r.result.ok ? opts?.humanDetailHints?.(r.result.data) : void 0;
9406
+ printHuman(r.result, { detailHints });
9407
+ } else {
9408
+ printJson(r.result);
9409
+ }
9327
9410
  if (vault && opts?.postCommit !== false) await postCommit(vault, r.exitCode);
9411
+ await new Promise((resolve6, reject) => {
9412
+ process.stdout.write("", (error) => error ? reject(error) : resolve6());
9413
+ });
9328
9414
  process.exit(r.exitCode);
9329
9415
  }
9330
9416
  function dirtyVolumeBlock(vault, command) {
@@ -9386,7 +9472,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
9386
9472
  if (dirty) {
9387
9473
  return emit(dirty, void 0, { postCommit: false });
9388
9474
  }
9389
- const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-4YCJVF64.js");
9475
+ const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-ANQPMOF4.js");
9390
9476
  const run = await runManagedWriteTransaction2({
9391
9477
  vault,
9392
9478
  command,
@@ -9803,6 +9889,7 @@ projectionsCmd.command("repair-legacy [vault]").description("repair one supporte
9803
9889
  });
9804
9890
  program.command("lint [vault]").description("run all vault health checks").option("--days <n>", "stale threshold", (s) => parseInt(s, 10), 90).option("--lines <n>", "pagesize threshold", (s) => parseInt(s, 10), 200).option("--log-threshold <n>", "log rotation threshold", (s) => parseInt(s, 10), 500).option("--fix", "auto-fix supported lint violations").option("--only <bucket>", "run only the specified lint bucket").option("--summary", "emit bounded bucket counts instead of full item arrays", false).option("--examples <n>", "example count per bucket in summary mode", (s) => parseInt(s, 10), 3).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
9805
9891
  const v = await resolveVaultArg(vault, opts.wiki);
9892
+ const humanDetailHints = opts.only ? void 0 : lintDetailHints;
9806
9893
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
9807
9894
  else if (opts.fix && opts.summary) return emitGuardedVaultWrite(
9808
9895
  v.vault,
@@ -9817,7 +9904,8 @@ program.command("lint [vault]").description("run all vault health checks").optio
9817
9904
  only: opts.only,
9818
9905
  summary: true,
9819
9906
  examplesLimit: opts.examples
9820
- })
9907
+ }),
9908
+ { humanDetailHints }
9821
9909
  );
9822
9910
  else if (opts.fix) return emitGuardedVaultWrite(
9823
9911
  v.vault,
@@ -9831,7 +9919,8 @@ program.command("lint [vault]").description("run all vault health checks").optio
9831
9919
  fix: true,
9832
9920
  only: opts.only,
9833
9921
  summary: false
9834
- })
9922
+ }),
9923
+ { humanDetailHints }
9835
9924
  );
9836
9925
  else if (opts.summary) emit(await runLint({
9837
9926
  vault: v.vault,
@@ -9843,7 +9932,7 @@ program.command("lint [vault]").description("run all vault health checks").optio
9843
9932
  only: opts.only,
9844
9933
  summary: true,
9845
9934
  examplesLimit: opts.examples
9846
- }), v.vault);
9935
+ }), v.vault, { humanDetailHints });
9847
9936
  else emit(await runLint({
9848
9937
  vault: v.vault,
9849
9938
  source: vault ? "flag" : void 0,
@@ -9852,7 +9941,7 @@ program.command("lint [vault]").description("run all vault health checks").optio
9852
9941
  logThreshold: opts.logThreshold,
9853
9942
  fix: false,
9854
9943
  only: opts.only
9855
- }), v.vault);
9944
+ }), v.vault, { humanDetailHints });
9856
9945
  });
9857
9946
  program.command("health [vault]").description("bounded whole-system wiki health report").option("--wiki <name>", "wiki profile name").option("--sync <mode>", "vault-sync policy: optional|required|off", "optional").option("--no-fail", "always exit 0 while reporting status in JSON").option("--out <path>", "write JSON result envelope to this path").option("--examples <n>", "example count per lint bucket", (s) => parseInt(s, 10), 3).action(async (vault, opts) => {
9858
9947
  const sync = String(opts.sync ?? "optional");
@@ -9873,7 +9962,7 @@ program.command("health [vault]").description("bounded whole-system wiki health
9873
9962
  noFail: opts.fail === false,
9874
9963
  out: opts.out,
9875
9964
  examplesLimit: opts.examples
9876
- }), void 0, { postCommit: false });
9965
+ }), void 0, { postCommit: false, humanDetailHints: healthLintDetailHints });
9877
9966
  });
9878
9967
  var configCmd = program.command("config").description("manage skillwiki configuration");
9879
9968
  configCmd.command("get <key>").description("print the value of a config key").action(async (key) => emit(await runConfigGet({ key, home: process.env.HOME ?? "" })));
@@ -4,9 +4,9 @@ import {
4
4
  UNMANAGED_START,
5
5
  renderRootIndex,
6
6
  writeRootIndexProjection
7
- } from "./chunk-SNCFIJ5E.js";
8
- import "./chunk-XYGGDGHR.js";
9
- import "./chunk-MIQOBEOW.js";
7
+ } from "./chunk-QVO332CT.js";
8
+ import "./chunk-IFMHQETQ.js";
9
+ import "./chunk-BS556WUE.js";
10
10
  export {
11
11
  UNMANAGED_END,
12
12
  UNMANAGED_START,
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  runManagedWritePreflight,
4
4
  runManagedWriteTransaction
5
- } from "./chunk-BY7V7QPU.js";
6
- import "./chunk-JJ654NVJ.js";
7
- import "./chunk-XYGGDGHR.js";
8
- import "./chunk-K4OGG5KJ.js";
9
- import "./chunk-MIQOBEOW.js";
5
+ } from "./chunk-LACQJ6RD.js";
6
+ import "./chunk-XRBUABGE.js";
7
+ import "./chunk-IFMHQETQ.js";
8
+ import "./chunk-E3JBAURS.js";
9
+ import "./chunk-BS556WUE.js";
10
10
  export {
11
11
  runManagedWritePreflight,
12
12
  runManagedWriteTransaction
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runSkillwikiMcpStdio
4
- } from "./chunk-2X2TCLHR.js";
4
+ } from "./chunk-WJVG3DD5.js";
5
5
  import "./chunk-7I2TPIV5.js";
6
- import "./chunk-SNCFIJ5E.js";
7
- import "./chunk-JJ654NVJ.js";
8
- import "./chunk-XYGGDGHR.js";
9
- import "./chunk-K4OGG5KJ.js";
10
- import "./chunk-MIQOBEOW.js";
6
+ import "./chunk-QVO332CT.js";
7
+ import "./chunk-XRBUABGE.js";
8
+ import "./chunk-IFMHQETQ.js";
9
+ import "./chunk-E3JBAURS.js";
10
+ import "./chunk-BS556WUE.js";
11
11
 
12
12
  // src/mcp-entry.ts
13
13
  runSkillwikiMcpStdio().catch((error) => {
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runSourcesPending
4
+ } from "./chunk-JUUZJJIF.js";
5
+ import "./chunk-E3JBAURS.js";
6
+ import "./chunk-BS556WUE.js";
7
+ export {
8
+ runSourcesPending
9
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.10.35",
3
+ "version": "0.10.37",
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.10.35",
3
+ "version": "0.10.37",
4
4
  "skills": "./",
5
5
  "description": "Project-aware Karpathy-style knowledge base for Claude Code: 19 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.10.35",
3
+ "version": "0.10.37",
4
4
  "description": "Project-aware Karpathy-style knowledge base for Codex with 19 prompt-only skills backed by the deterministic skillwiki CLI.",
5
5
  "author": {
6
6
  "name": "karlorz",
@@ -1,16 +1,45 @@
1
1
  #!/usr/bin/env bash
2
2
  # Shared SessionStart context helpers for skillwiki hook entrypoints.
3
3
 
4
- read_config_value() {
4
+ read_workflow_config() {
5
5
  local file="$1"
6
- local key="$2"
7
- local line
8
6
 
9
- line=$(grep -E "^[[:space:]]*${key}:" "$file" 2>/dev/null | head -n 1 || true)
10
- [[ -n "$line" ]] || return 0
11
-
12
- printf '%s' "$line" \
13
- | sed -E "s/^[[:space:]]*${key}:[[:space:]]*//; s/[[:space:]]+#.*$//; s/[[:space:]]+$//; s/^['\"]//; s/['\"]$//"
7
+ awk '
8
+ BEGIN {
9
+ count = 6
10
+ keys[1] = "workflow_selection"
11
+ keys[2] = "workflow_profile"
12
+ keys[3] = "workflow_capability"
13
+ keys[4] = "workflow_risk"
14
+ keys[5] = "prd_layer"
15
+ keys[6] = "prd_pipeline"
16
+ for (i = 1; i <= count; i += 1) allowed[keys[i]] = 1
17
+ }
18
+ /^[[:space:]]*```(yaml|yml)[[:space:]]*$/ { in_yaml = 1; next }
19
+ in_yaml && /^[[:space:]]*```[[:space:]]*$/ { in_yaml = 0; next }
20
+ in_yaml && /^[A-Za-z_][A-Za-z0-9_]*[[:space:]]*:/ {
21
+ line = $0
22
+ key = line
23
+ sub(/[[:space:]]*:.*/, "", key)
24
+ if (!(key in allowed)) next
25
+ value = line
26
+ sub(/^[^:]*:[[:space:]]*/, "", value)
27
+ sub(/[[:space:]]+#.*$/, "", value)
28
+ sub(/^[[:space:]]+/, "", value)
29
+ sub(/[[:space:]]+$/, "", value)
30
+ if ((substr(value, 1, 1) == "\"" && substr(value, length(value), 1) == "\"") ||
31
+ (substr(value, 1, 1) == "\047" && substr(value, length(value), 1) == "\047")) {
32
+ value = substr(value, 2, length(value) - 2)
33
+ }
34
+ values[key] = value
35
+ }
36
+ END {
37
+ for (i = 1; i <= count; i += 1) {
38
+ key = keys[i]
39
+ if (key in values) printf "%s\t%s\n", key, values[key]
40
+ }
41
+ }
42
+ ' "$file" 2>/dev/null
14
43
  }
15
44
 
16
45
  find_dev_loop_config() {
@@ -27,29 +56,199 @@ find_dev_loop_config() {
27
56
  return 0
28
57
  }
29
58
 
30
- build_project_prd_context() {
31
- local config_path
59
+ build_project_workflow_context() {
60
+ local config_path=""
32
61
  config_path=$(find_dev_loop_config)
33
- [[ -n "$config_path" ]] || return 0
62
+ local workflow_selection=""
63
+ local configured_profile=""
64
+ local workflow_capability=""
65
+ local workflow_risk=""
66
+ local prd_layer=""
67
+ local prd_pipeline=""
68
+ if [[ -n "$config_path" ]]; then
69
+ while IFS=$'\t' read -r key value; do
70
+ case "$key" in
71
+ workflow_selection) workflow_selection="$value" ;;
72
+ workflow_profile) configured_profile="$value" ;;
73
+ workflow_capability) workflow_capability="$value" ;;
74
+ workflow_risk) workflow_risk="$value" ;;
75
+ prd_layer) prd_layer="$value" ;;
76
+ prd_pipeline) prd_pipeline="$value" ;;
77
+ esac
78
+ done < <(read_workflow_config "$config_path")
79
+ fi
34
80
 
35
- local prd_layer
36
- local prd_pipeline
37
- prd_layer=$(read_config_value "$config_path" "prd_layer")
38
- prd_pipeline=$(read_config_value "$config_path" "prd_pipeline")
81
+ local authority="builtin_adaptive"
82
+ local resolved_profile=""
83
+ local resolved_pipeline=""
84
+ local workflow_status="resolved"
85
+ local reason=""
86
+ local has_policy="false"
87
+ local legacy_profile=""
88
+
89
+ prd_layer="${prd_layer:-manual}"
90
+ workflow_capability="${workflow_capability:-unknown}"
91
+ workflow_risk="${workflow_risk:-routine}"
92
+
93
+ if [[ -n "$prd_pipeline" ]]; then
94
+ case "$prd_pipeline" in
95
+ full) legacy_profile="full" ;;
96
+ tdd-first) legacy_profile="guided" ;;
97
+ single-pass|debug-only|manual) legacy_profile="native" ;;
98
+ *)
99
+ workflow_status="unresolved"
100
+ reason="prd_pipeline must be one of: full, tdd-first, single-pass, debug-only, manual"
101
+ ;;
102
+ esac
103
+ fi
39
104
 
40
- [[ -n "$prd_layer" || -n "$prd_pipeline" ]] || return 0
105
+ if [[ -n "$workflow_selection" || -n "$configured_profile" || \
106
+ "$workflow_capability" != "unknown" || "$workflow_risk" != "routine" ]]; then
107
+ has_policy="true"
108
+ authority="project"
109
+ if [[ -z "$workflow_selection" ]]; then
110
+ if [[ -n "$configured_profile" ]]; then
111
+ workflow_selection="fixed"
112
+ else
113
+ workflow_selection="adaptive"
114
+ fi
115
+ fi
116
+ elif [[ -n "$prd_pipeline" ]]; then
117
+ workflow_selection="fixed"
118
+ authority="project_legacy"
119
+ resolved_profile="$legacy_profile"
120
+ if [[ "$workflow_status" == "resolved" ]]; then
121
+ reason="legacy explicit prd_pipeline ${prd_pipeline} maps to the ${resolved_profile} workflow profile"
122
+ fi
123
+ elif [[ -n "${DEV_LOOP_WORKFLOW_SELECTION:-}" || -n "${DEV_LOOP_WORKFLOW_PROFILE:-}" || \
124
+ -n "${DEV_LOOP_WORKFLOW_CAPABILITY:-}" || -n "${DEV_LOOP_WORKFLOW_RISK:-}" ]]; then
125
+ has_policy="true"
126
+ authority="user_default"
127
+ workflow_selection="${DEV_LOOP_WORKFLOW_SELECTION:-}"
128
+ configured_profile="${DEV_LOOP_WORKFLOW_PROFILE:-}"
129
+ workflow_capability="${DEV_LOOP_WORKFLOW_CAPABILITY:-unknown}"
130
+ workflow_risk="${DEV_LOOP_WORKFLOW_RISK:-routine}"
131
+ if [[ -z "$workflow_selection" ]]; then
132
+ if [[ -n "$configured_profile" ]]; then
133
+ workflow_selection="fixed"
134
+ else
135
+ workflow_selection="adaptive"
136
+ fi
137
+ fi
138
+ else
139
+ workflow_selection="adaptive"
140
+ fi
41
141
 
42
- prd_layer="${prd_layer:-unspecified}"
43
- prd_pipeline="${prd_pipeline:-unspecified}"
142
+ if [[ "$has_policy" == "true" ]]; then
143
+ case "$workflow_selection" in
144
+ fixed|adaptive) ;;
145
+ *)
146
+ workflow_status="unresolved"
147
+ reason="workflow_selection must be one of: fixed, adaptive"
148
+ ;;
149
+ esac
150
+ case "$configured_profile" in
151
+ ""|native|guided|full) ;;
152
+ *)
153
+ workflow_status="unresolved"
154
+ reason="workflow_profile must be one of: native, guided, full"
155
+ ;;
156
+ esac
157
+ case "$workflow_capability" in
158
+ self-directed|needs-guidance|unknown) ;;
159
+ *)
160
+ workflow_status="unresolved"
161
+ reason="workflow_capability must be one of: self-directed, needs-guidance, unknown"
162
+ ;;
163
+ esac
164
+ case "$workflow_risk" in
165
+ routine|elevated) ;;
166
+ *)
167
+ workflow_status="unresolved"
168
+ reason="workflow_risk must be one of: routine, elevated"
169
+ ;;
170
+ esac
171
+
172
+ if [[ "$workflow_status" == "resolved" && "$workflow_selection" == "fixed" && -z "$configured_profile" ]]; then
173
+ workflow_status="unresolved"
174
+ reason="fixed selection requires \`workflow_profile\`"
175
+ elif [[ "$workflow_status" == "resolved" && "$workflow_selection" == "adaptive" && -n "$configured_profile" ]]; then
176
+ workflow_status="unresolved"
177
+ reason="adaptive selection must not set \`workflow_profile\`; use fixed for an explicit profile"
178
+ elif [[ "$workflow_status" == "resolved" && "$workflow_selection" == "fixed" ]]; then
179
+ resolved_profile="$configured_profile"
180
+ reason="${authority} explicitly selected the ${resolved_profile} workflow profile"
181
+ elif [[ "$workflow_status" == "resolved" ]]; then
182
+ if [[ "$workflow_capability" == "needs-guidance" || "$workflow_risk" == "elevated" ]]; then
183
+ resolved_profile="guided"
184
+ else
185
+ resolved_profile="native"
186
+ fi
187
+ reason="adaptive selection chose ${resolved_profile} from capability=${workflow_capability}, risk=${workflow_risk}"
188
+ fi
189
+ elif [[ "$authority" == "builtin_adaptive" ]]; then
190
+ resolved_profile="native"
191
+ reason="built-in adaptive default chose native from capability=unknown, risk=routine"
192
+ fi
44
193
 
45
- cat <<EOF
46
- ## Project PRD Mode
194
+ if [[ "$workflow_status" == "resolved" ]]; then
195
+ if [[ -n "$prd_pipeline" ]]; then
196
+ resolved_pipeline="$prd_pipeline"
197
+ else
198
+ case "$resolved_profile" in
199
+ native) resolved_pipeline="single-pass" ;;
200
+ guided) resolved_pipeline="tdd-first" ;;
201
+ full) resolved_pipeline="full" ;;
202
+ esac
203
+ fi
204
+ else
205
+ resolved_profile="unresolved"
206
+ resolved_pipeline="unresolved"
207
+ fi
47
208
 
48
- Detected \`.claude/dev-loop.config.md\` for this workspace:
209
+ local config_detection
210
+ if [[ -n "$config_path" ]]; then
211
+ config_detection="Detected \`.claude/dev-loop.config.md\` for this workspace."
212
+ else
213
+ config_detection="No \`.claude/dev-loop.config.md\` was found; using the built-in adaptive default."
214
+ fi
215
+
216
+ cat <<EOF
217
+ ## Project Workflow Profile
218
+
219
+ ${config_detection}
220
+ - workflow status: \`${workflow_status}\`
221
+ - \`workflow_selection\`: \`${workflow_selection}\`
222
+ - \`workflow_profile\`: \`${resolved_profile}\`
223
+ - \`workflow_capability\`: \`${workflow_capability}\`
224
+ - \`workflow_risk\`: \`${workflow_risk}\`
225
+ - authority: \`${authority}\`
226
+ - reason: ${reason}
49
227
  - \`prd_layer\`: \`${prd_layer}\`
50
- - \`prd_pipeline\`: \`${prd_pipeline}\`
228
+ - \`prd_pipeline\`: \`${resolved_pipeline}\`
229
+
230
+ EOF
51
231
 
52
- Use this detected PRD mode as the source of truth. Route generated spec/plan artifacts through \`proj-work\`, and do not write them under \`docs/superpowers/\`. If \`prd_layer\` is \`superpowers\` or \`tdd\`, ensure \`EnterPlanMode\` is gated with \`wiki-gate-plan-mode\`. Do not assume \`superpowers/full\` unless the config says so.
232
+ if [[ "$workflow_status" == "unresolved" ]]; then
233
+ cat <<EOF
234
+ Fail closed for workflow execution until the policy is corrected. Do not infer \`full\`, do not force Superpowers, and do not enable \`EnterPlanMode\` gating from availability evidence.
235
+ EOF
236
+ elif [[ "$resolved_profile" == "full" ]]; then
237
+ cat <<EOF
238
+ Explicit full compatibility workflow is active. If the configured provider uses Superpowers or TDD planning, ensure \`EnterPlanMode\` is gated with \`wiki-gate-plan-mode\`. Run the complete configured provider/pipeline flow.
239
+ EOF
240
+ elif [[ "$resolved_profile" == "guided" ]]; then
241
+ cat <<EOF
242
+ Use only targeted guidance for enabled stages; do not run the complete Superpowers sequence or force \`EnterPlanMode\` gating. Installed providers are optional capability sources.
243
+ EOF
244
+ else
245
+ cat <<EOF
246
+ Use host-native planning, implementation, tools, and subagents. Do not force Superpowers or \`EnterPlanMode\` gating. Installation proves availability, never activation.
247
+ EOF
248
+ fi
249
+
250
+ cat <<EOF
251
+ Route every generated spec/plan artifact through \`proj-work\`, and never write it under \`docs/superpowers/\`. SkillWiki remains the knowledge and provenance layer; workflow selection does not change managed-write authority.
53
252
  EOF
54
253
  }
55
254
 
@@ -254,12 +453,12 @@ resolve_skill_path() {
254
453
 
255
454
  build_skillwiki_session_context() {
256
455
  local skill_content="$1"
257
- local project_prd_context
456
+ local project_workflow_context
258
457
  local dynamic_session_memory
259
458
  local runtime_host_context
260
459
  local session_context
261
460
 
262
- project_prd_context=$(build_project_prd_context)
461
+ project_workflow_context=$(build_project_workflow_context)
263
462
  dynamic_session_memory=$(build_dynamic_session_memory)
264
463
  runtime_host_context=$(build_runtime_host_context)
265
464
 
@@ -272,9 +471,9 @@ build_skillwiki_session_context() {
272
471
  session_context+=$'\n\n'
273
472
  session_context+="$dynamic_session_memory"
274
473
  fi
275
- if [[ -n "$project_prd_context" ]]; then
474
+ if [[ -n "$project_workflow_context" ]]; then
276
475
  session_context+=$'\n\n'
277
- session_context+="$project_prd_context"
476
+ session_context+="$project_workflow_context"
278
477
  fi
279
478
  session_context+=$'\n\n'
280
479
  session_context+="$skill_content"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.10.35",
3
+ "version": "0.10.37",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",
@@ -1,21 +1,30 @@
1
1
  ---
2
2
  name: using-skillwiki
3
- description: Invoke at session start or when knowledge-base tasks arise — maps skillwiki skills, dev-loop alignment, and PRD/TDD routing with plan-mode gate checks
3
+ description: Invoke at session start or when knowledge-base tasks arise — maps skillwiki skills, dev-loop alignment, adaptive workflow profiles, and vault routing
4
4
  ---
5
5
  *Note: If executing as a background subagent, skip this skill section.*
6
6
 
7
7
  # using-skillwiki
8
- You have skillwiki — a project-aware Karpathy-style knowledge base for Claude Code.
8
+ You have skillwiki — a project-aware Karpathy-style knowledge base for agent harnesses.
9
9
 
10
10
  ## Last Hook Gate (SessionStart)
11
11
 
12
- This skill is activated by the plugin during `startup|clear|compact` lifecycle events.
12
+ This skill is activated by the plugin during startup and clear lifecycle
13
+ events, plus the harness-specific resume/compact event where supported.
13
14
  Use this section as procedural planning guidelines:
14
15
 
15
- 1. If the task requires spec/plan work, route through PRD skills (not built-in plan mode).
16
- 2. If `prd_layer` is `superpowers` or `tdd`, ensure `EnterPlanMode` is gated (`wiki-gate-plan-mode on` or `status` if uncertain).
17
- 3. If `prd_layer` is `manual` or `none`, do not force the gate; follow project policy.
18
- 4. Always apply the PRD bridge: spec/plan outputs go to vault work-item paths, never `docs/superpowers/`.
16
+ 1. Read the injected Project Workflow Profile before choosing orchestration or
17
+ provider skills. Installation proves availability, never activation.
18
+ 2. For `native`, use the host agent's built-in planning and execution. For
19
+ `guided`, add only targeted structure. Neither profile forces Superpowers
20
+ or `EnterPlanMode` gating.
21
+ 3. For explicit `full`, run the complete configured provider/pipeline. Gate
22
+ `EnterPlanMode` with `wiki-gate-plan-mode` only when that explicit workflow
23
+ uses Superpowers or TDD planning.
24
+ 4. If workflow status is unresolved, fail closed for workflow execution; do
25
+ not infer `full` from installed skills or provider names.
26
+ 5. Always apply the PRD bridge: spec/plan outputs go to vault work-item paths,
27
+ never `docs/superpowers/`.
19
28
 
20
29
  ## Activation File (Cross-Harness Alternative to SessionStart)
21
30
 
@@ -177,8 +186,9 @@ The vault is shared across hosts, so host-local absolute paths are not durable s
177
186
 
178
187
  ## dev-loop Alignment
179
188
 
180
- Use these skills as the knowledge layer in dev-loop. The loop remains capability-based:
181
- branch on capabilities (`BACKEND_CAPS`, `PRD_CAPS`), not backend names.
189
+ Use these skills as the knowledge layer in dev-loop. The loop remains
190
+ capability-based: resolve `WORKFLOW_PROFILE` first, then branch on capabilities
191
+ (`BACKEND_CAPS`, `PRD_CAPS`), not backend names.
182
192
 
183
193
  Typical sequence with PRD enabled:
184
194
  `REFRESH → QUERY → WORK → SPEC → PLAN → EXECUTE → SIMPLIFY → MERGE → SAVE → RETRO`.
@@ -187,17 +197,33 @@ Typical sequence with PRD enabled:
187
197
  - `SIMPLIFY` is a quality gate before merge; keep it in the loop even for small changes.
188
198
  - For no-work cycles, run maintenance (`wiki-lint`, `wiki-audit`, `proj-distill`, `dev-loop:research`).
189
199
 
190
- ## PRD/TDD Compatibility
191
-
192
- Use `prd_layer` + `prd_pipeline` from `.claude/dev-loop.config.md` as source of truth:
193
-
194
- - `superpowers` + `full`: brainstorming/spec/plan/execute/review; route spec+plan through `proj-work`.
195
- - `tdd` + `tdd-first`: plan-first then test-driven execute; still route artifacts through `proj-work`.
196
- - `single-pass` or `debug-only`: may skip formal spec/plan, but if generated they still belong in vault work items.
197
- - `manual` / `none`: no forced PRD skills; preserve skillwiki logging and provenance discipline.
200
+ ## Workflow Profile Compatibility
201
+
202
+ Use the resolved workflow policy from `.claude/dev-loop.config.md` and the
203
+ SessionStart context as the source of truth:
204
+
205
+ - `native` defaults to `single-pass` and uses host-native planning,
206
+ implementation, tools, and subagents. Installed providers stay inactive
207
+ unless explicitly selected for a stage.
208
+ - `guided` defaults to `tdd-first` and adds only targeted planning, TDD, or
209
+ provider capabilities. It does not imply the complete Superpowers sequence.
210
+ - `full` defaults to `full` and runs the complete compatibility workflow. It
211
+ is explicit-only, including the legacy compatibility signal
212
+ `prd_pipeline: full` when no newer workflow policy overrides it.
213
+ - `workflow_selection: adaptive` may choose `native` or `guided`, never
214
+ `full`. `workflow_selection: fixed` requires `workflow_profile`.
215
+ - Invalid policy is unresolved and fail-closed. Goal, headless, CI, and
216
+ satellite sessions do not prompt for a replacement policy.
217
+
218
+ `prd_layer` remains an independent provider-capability registry and
219
+ `prd_pipeline` remains an independent stage-template override. Provider or
220
+ cache discovery cannot select a workflow profile. Regardless of profile,
221
+ route generated spec and plan artifacts through `proj-work`, preserve
222
+ SkillWiki provenance, and keep the independent `simplify:simplify` review gate
223
+ for code changes.
198
224
 
199
225
  ## CLI Backbone
200
- All skills are backed by the `skillwiki` CLI — a deterministic tool with no LLM calls. It handles path resolution, config management, validation, health reporting, and linting. Skills invoke it via Bash for the mechanical parts and use Claude for the creative parts.
226
+ All skills are backed by the `skillwiki` CLI — a deterministic tool with no LLM calls. It handles path resolution, config management, validation, health reporting, and linting. Skills invoke it via Bash for the mechanical parts and use the active agent for the creative parts.
201
227
  Key CLI subcommands: `init`, `health`, `lint`, `config`, `doctor`, `path`, `lang`, `install`, `fleet context`, `fleet validate`, `graph build`, `query`, `sources pending`, `sources disposition`, `sources dispose`, `archive`, `remove`, `drift`, `dedup`, `compound`, `tag-sync`, `tag reconcile`, `page publish`, `sync status`, `seed`, `stale`, `observe`, `canvas generate`.
202
228
  Run `skillwiki health <vault> --out /tmp/skillwiki-health.json --no-fail` for a bounded whole-system report that includes the nonblocking source-lifecycle backlog. Pending captures are informational and do not make health fail. Run `skillwiki lint <vault> --summary` for lint-only bucket counts with capped examples and details commands. Run `skillwiki doctor` to diagnose setup/runtime issues only. Run `skillwiki config list` to see current configuration.
203
229
 
@@ -39,6 +39,19 @@ Invoke a SkillWiki skill when the user: wants vault/wiki/knowledge-base operatio
39
39
 
40
40
  Route PRD/spec/plan work to `wiki-adapter-prd` and `proj-work`, not `docs/superpowers/`. Spec and plan outputs must land in vault work-item paths. Never create `docs/superpowers/` in any repo.
41
41
 
42
+ ## Workflow Profiles
43
+
44
+ Resolve workflow policy before loading provider skills. Profiles are `native`,
45
+ `guided`, and explicit-only `full`; selection is `adaptive` or `fixed`.
46
+ Adaptive chooses only native or guided. Installation and cache discovery prove
47
+ availability, never activation. Native and guided do not force Superpowers or
48
+ plan-mode gating. Explicit full may use the complete configured provider flow;
49
+ gate plan mode only when that flow actually uses Superpowers/TDD planning.
50
+ Invalid fixed policy is unresolved and fail-closed. Noninteractive sessions do
51
+ not prompt. Keep workflow profile, `prd_layer` provider, `prd_pipeline` stage
52
+ template, SkillWiki provenance, and the independent simplify review gate as
53
+ separate concerns.
54
+
42
55
  ## Fail-Closed Boundary
43
56
 
44
57
  Never write typed pages, `index.md`, or `log.md` directly. Never bare `rm` or `git rm` as a fleet delete (snapshot resurrects from S3). Never auto `npm install -g skillwiki` in headless/goal/satellite sessions. If `skillwiki page publish --help` is unavailable, fail closed.
@@ -1,21 +1,30 @@
1
1
  ---
2
2
  name: using-skillwiki
3
- description: Invoke at session start or when knowledge-base tasks arise — maps skillwiki skills, dev-loop alignment, and PRD/TDD routing with plan-mode gate checks
3
+ description: Invoke at session start or when knowledge-base tasks arise — maps skillwiki skills, dev-loop alignment, adaptive workflow profiles, and vault routing
4
4
  ---
5
5
  *Note: If executing as a background subagent, skip this skill section.*
6
6
 
7
7
  # using-skillwiki
8
- You have skillwiki — a project-aware Karpathy-style knowledge base for Claude Code.
8
+ You have skillwiki — a project-aware Karpathy-style knowledge base for agent harnesses.
9
9
 
10
10
  ## Last Hook Gate (SessionStart)
11
11
 
12
- This skill is activated by the plugin during `startup|clear|compact` lifecycle events.
12
+ This skill is activated by the plugin during startup and clear lifecycle
13
+ events, plus the harness-specific resume/compact event where supported.
13
14
  Use this section as procedural planning guidelines:
14
15
 
15
- 1. If the task requires spec/plan work, route through PRD skills (not built-in plan mode).
16
- 2. If `prd_layer` is `superpowers` or `tdd`, ensure `EnterPlanMode` is gated (`wiki-gate-plan-mode on` or `status` if uncertain).
17
- 3. If `prd_layer` is `manual` or `none`, do not force the gate; follow project policy.
18
- 4. Always apply the PRD bridge: spec/plan outputs go to vault work-item paths, never `docs/superpowers/`.
16
+ 1. Read the injected Project Workflow Profile before choosing orchestration or
17
+ provider skills. Installation proves availability, never activation.
18
+ 2. For `native`, use the host agent's built-in planning and execution. For
19
+ `guided`, add only targeted structure. Neither profile forces Superpowers
20
+ or `EnterPlanMode` gating.
21
+ 3. For explicit `full`, run the complete configured provider/pipeline. Gate
22
+ `EnterPlanMode` with `wiki-gate-plan-mode` only when that explicit workflow
23
+ uses Superpowers or TDD planning.
24
+ 4. If workflow status is unresolved, fail closed for workflow execution; do
25
+ not infer `full` from installed skills or provider names.
26
+ 5. Always apply the PRD bridge: spec/plan outputs go to vault work-item paths,
27
+ never `docs/superpowers/`.
19
28
 
20
29
  ## Activation File (Cross-Harness Alternative to SessionStart)
21
30
 
@@ -177,8 +186,9 @@ The vault is shared across hosts, so host-local absolute paths are not durable s
177
186
 
178
187
  ## dev-loop Alignment
179
188
 
180
- Use these skills as the knowledge layer in dev-loop. The loop remains capability-based:
181
- branch on capabilities (`BACKEND_CAPS`, `PRD_CAPS`), not backend names.
189
+ Use these skills as the knowledge layer in dev-loop. The loop remains
190
+ capability-based: resolve `WORKFLOW_PROFILE` first, then branch on capabilities
191
+ (`BACKEND_CAPS`, `PRD_CAPS`), not backend names.
182
192
 
183
193
  Typical sequence with PRD enabled:
184
194
  `REFRESH → QUERY → WORK → SPEC → PLAN → EXECUTE → SIMPLIFY → MERGE → SAVE → RETRO`.
@@ -187,17 +197,33 @@ Typical sequence with PRD enabled:
187
197
  - `SIMPLIFY` is a quality gate before merge; keep it in the loop even for small changes.
188
198
  - For no-work cycles, run maintenance (`wiki-lint`, `wiki-audit`, `proj-distill`, `dev-loop:research`).
189
199
 
190
- ## PRD/TDD Compatibility
191
-
192
- Use `prd_layer` + `prd_pipeline` from `.claude/dev-loop.config.md` as source of truth:
193
-
194
- - `superpowers` + `full`: brainstorming/spec/plan/execute/review; route spec+plan through `proj-work`.
195
- - `tdd` + `tdd-first`: plan-first then test-driven execute; still route artifacts through `proj-work`.
196
- - `single-pass` or `debug-only`: may skip formal spec/plan, but if generated they still belong in vault work items.
197
- - `manual` / `none`: no forced PRD skills; preserve skillwiki logging and provenance discipline.
200
+ ## Workflow Profile Compatibility
201
+
202
+ Use the resolved workflow policy from `.claude/dev-loop.config.md` and the
203
+ SessionStart context as the source of truth:
204
+
205
+ - `native` defaults to `single-pass` and uses host-native planning,
206
+ implementation, tools, and subagents. Installed providers stay inactive
207
+ unless explicitly selected for a stage.
208
+ - `guided` defaults to `tdd-first` and adds only targeted planning, TDD, or
209
+ provider capabilities. It does not imply the complete Superpowers sequence.
210
+ - `full` defaults to `full` and runs the complete compatibility workflow. It
211
+ is explicit-only, including the legacy compatibility signal
212
+ `prd_pipeline: full` when no newer workflow policy overrides it.
213
+ - `workflow_selection: adaptive` may choose `native` or `guided`, never
214
+ `full`. `workflow_selection: fixed` requires `workflow_profile`.
215
+ - Invalid policy is unresolved and fail-closed. Goal, headless, CI, and
216
+ satellite sessions do not prompt for a replacement policy.
217
+
218
+ `prd_layer` remains an independent provider-capability registry and
219
+ `prd_pipeline` remains an independent stage-template override. Provider or
220
+ cache discovery cannot select a workflow profile. Regardless of profile,
221
+ route generated spec and plan artifacts through `proj-work`, preserve
222
+ SkillWiki provenance, and keep the independent `simplify:simplify` review gate
223
+ for code changes.
198
224
 
199
225
  ## CLI Backbone
200
- All skills are backed by the `skillwiki` CLI — a deterministic tool with no LLM calls. It handles path resolution, config management, validation, health reporting, and linting. Skills invoke it via Bash for the mechanical parts and use Claude for the creative parts.
226
+ All skills are backed by the `skillwiki` CLI — a deterministic tool with no LLM calls. It handles path resolution, config management, validation, health reporting, and linting. Skills invoke it via Bash for the mechanical parts and use the active agent for the creative parts.
201
227
  Key CLI subcommands: `init`, `health`, `lint`, `config`, `doctor`, `path`, `lang`, `install`, `fleet context`, `fleet validate`, `graph build`, `query`, `sources pending`, `sources disposition`, `sources dispose`, `archive`, `remove`, `drift`, `dedup`, `compound`, `tag-sync`, `tag reconcile`, `page publish`, `sync status`, `seed`, `stale`, `observe`, `canvas generate`.
202
228
  Run `skillwiki health <vault> --out /tmp/skillwiki-health.json --no-fail` for a bounded whole-system report that includes the nonblocking source-lifecycle backlog. Pending captures are informational and do not make health fail. Run `skillwiki lint <vault> --summary` for lint-only bucket counts with capped examples and details commands. Run `skillwiki doctor` to diagnose setup/runtime issues only. Run `skillwiki config list` to see current configuration.
203
229
 
@@ -39,6 +39,19 @@ Invoke a SkillWiki skill when the user: wants vault/wiki/knowledge-base operatio
39
39
 
40
40
  Route PRD/spec/plan work to `wiki-adapter-prd` and `proj-work`, not `docs/superpowers/`. Spec and plan outputs must land in vault work-item paths. Never create `docs/superpowers/` in any repo.
41
41
 
42
+ ## Workflow Profiles
43
+
44
+ Resolve workflow policy before loading provider skills. Profiles are `native`,
45
+ `guided`, and explicit-only `full`; selection is `adaptive` or `fixed`.
46
+ Adaptive chooses only native or guided. Installation and cache discovery prove
47
+ availability, never activation. Native and guided do not force Superpowers or
48
+ plan-mode gating. Explicit full may use the complete configured provider flow;
49
+ gate plan mode only when that flow actually uses Superpowers/TDD planning.
50
+ Invalid fixed policy is unresolved and fail-closed. Noninteractive sessions do
51
+ not prompt. Keep workflow profile, `prd_layer` provider, `prd_pipeline` stage
52
+ template, SkillWiki provenance, and the independent simplify review gate as
53
+ separate concerns.
54
+
42
55
  ## Fail-Closed Boundary
43
56
 
44
57
  Never write typed pages, `index.md`, or `log.md` directly. Never bare `rm` or `git rm` as a fleet delete (snapshot resurrects from S3). Never auto `npm install -g skillwiki` in headless/goal/satellite sessions. If `skillwiki page publish --help` is unavailable, fail closed.
@@ -26,6 +26,13 @@ Four shapes: typed-knowledge, raw, work-item, compound. See spec for full Zod sc
26
26
  Work-item statuses are `planned`, `in-progress`, `completed`, and `abandoned`.
27
27
  `status: proposed` is not supported by the current SkillWiki schema. Non-executing queued findings use raw `task` or `bug` captures under `raw/transcripts/` with a `project` wikilink; humans promote them into `planned` work items.
28
28
 
29
+ ### Work Item Validation Shapes
30
+
31
+ - **Standard:** `spec.md` is the specification source. A completed item provides `evidence.md` or `retro.md`.
32
+ - **Goal-plan:** frontmatter `mode: goal-plan` (or the compatibility alias `mode: goal`) makes `plan.md` the specification source. Completion evidence may be `build-report.md`, an `evidence/` directory, `evidence.md`, or `retro.md`; `spec.md` is optional for this shape.
33
+
34
+ `skillwiki work-validate --require-complete` accepts `completed`, `complete`, or `done` on the active specification source. Goal-plan handling does not relax the standard shape: without a goal mode, `spec.md` and the standard completion evidence remain required.
35
+
29
36
  ## Tag Taxonomy
30
37
 
31
38
  ```yaml
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- runSourcesPending
4
- } from "./chunk-GXT5WTSE.js";
5
- import "./chunk-K4OGG5KJ.js";
6
- import "./chunk-MIQOBEOW.js";
7
- export {
8
- runSourcesPending
9
- };