@kontextmind/kxm 0.7.92 → 0.7.93
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/workflows/default.yaml +1 -1
- package/CHANGELOG.md +204 -0
- package/README.md +3 -0
- package/docs/README.md +3 -0
- package/docs/agent-skills.md +123 -60
- package/docs/architecture.md +5 -2
- package/docs/cli-reference.md +3527 -0
- package/docs/config-reference.md +1943 -0
- package/docs/configuration.md +29 -3
- package/docs/continuous-improvement.md +122 -10
- package/docs/contracts/routing.md +95 -11
- package/docs/harness-routing.md +616 -0
- package/docs/kxm-handbook.md +106 -19
- package/docs/templates/README.md +1 -1
- package/docs/test-matrix.md +12 -6
- package/docs/troubleshooting.md +2 -2
- package/examples/project/.kxm/workflows/fix.yaml +1 -1
- package/examples/project/.kxm/workflows/improve.yaml +1 -1
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +9 -10
- package/plugins/kxm/README.md +238 -56
- package/plugins/kxm/dist/claude-hook.js +10083 -0
- package/plugins/kxm/dist/cli.js +3068 -2446
- package/plugins/kxm/dist/client.js +64 -0
- package/plugins/kxm/dist/core.js +102 -9
- package/plugins/kxm/dist/extension.js +210 -68
- package/plugins/kxm/dist/mcp-server.js +217 -40
- package/plugins/kxm/dist/runtime-supervisor.js +1628 -157
- package/plugins/kxm/dist/runtime.js +1874 -298
- package/plugins/kxm/dist/server.js +416 -82
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/hints.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +48 -24
- package/plugins/kxm/skills/kxm/references/protocol.md +3 -3
- package/plugins/kxm/skills/kxm-context-memory/SKILL.md +61 -21
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +9 -0
- package/plugins/kxm/skills/kxm-harness-auth/SKILL.md +82 -16
- package/plugins/kxm/skills/kxm-harvest/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-hub-ops/SKILL.md +55 -27
- package/plugins/kxm/skills/kxm-insights/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-mind/SKILL.md +2 -2
- package/plugins/kxm/skills/{kxm-setup → kxm-mind-setup}/SKILL.md +4 -4
- package/plugins/kxm/skills/kxm-peer/SKILL.md +68 -93
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +156 -23
- package/plugins/kxm/skills/kxm-projects/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-protocol/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-query/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-routing-improve/SKILL.md +74 -15
- package/plugins/kxm/skills/kxm-runs/SKILL.md +46 -17
- package/plugins/kxm/skills/kxm-session/SKILL.md +64 -36
- package/plugins/kxm/skills/kxm-skill-lifecycle/SKILL.md +44 -15
- package/plugins/kxm/skills/kxm-tasks/SKILL.md +16 -4
- package/plugins/kxm/skills/kxm-triage/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-work/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +60 -19
- package/plugins/kxm/src/arbiter.ts +67 -22
- package/plugins/kxm/src/autocomplete.ts +1 -1
- package/plugins/kxm/src/claude-hook.ts +192 -0
- package/plugins/kxm/src/cli/project.ts +11 -5
- package/plugins/kxm/src/cli/system.ts +85 -13
- package/plugins/kxm/src/cli/types.ts +4 -1
- package/plugins/kxm/src/cli/workflows.ts +18 -16
- package/plugins/kxm/src/cli.ts +23 -13
- package/plugins/kxm/src/client.ts +15 -4
- package/plugins/kxm/src/commands.ts +19 -9
- package/plugins/kxm/src/config.ts +42 -7
- package/plugins/kxm/src/context-packet.ts +14 -2
- package/plugins/kxm/src/context.ts +16 -5
- package/plugins/kxm/src/dispatch-context.ts +286 -0
- package/plugins/kxm/src/engine-plan.ts +40 -0
- package/plugins/kxm/src/engine.ts +138 -6
- package/plugins/kxm/src/hub-env.ts +17 -1
- package/plugins/kxm/src/hub.ts +92 -29
- package/plugins/kxm/src/improve-sources.ts +228 -0
- package/plugins/kxm/src/improve.ts +325 -140
- package/plugins/kxm/src/local-snapshot.ts +101 -42
- package/plugins/kxm/src/mcp-server.ts +129 -30
- package/plugins/kxm/src/project-config.ts +25 -0
- package/plugins/kxm/src/protocol.ts +11 -0
- package/plugins/kxm/src/relevance.ts +138 -0
- package/plugins/kxm/src/retrospective.ts +16 -10
- package/plugins/kxm/src/runtime-service.ts +8 -1
- package/plugins/kxm/src/runtime-supervisor.ts +16 -2
- package/plugins/kxm/src/session-token-hint.ts +17 -0
- package/plugins/kxm/src/suggest.ts +7 -7
- package/plugins/kxm/src/workflow-manager.ts +80 -78
- package/plugins/kxm/src/workflow.ts +202 -12
- package/scripts/build-runtime.mjs +7 -1
- package/scripts/check-generated.mjs +1 -0
- package/scripts/emit-codex-artifacts.mjs +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import {
|
|
3
|
+
IMPROVEMENT_AREAS,
|
|
3
4
|
MAX_MESSAGE_TTL_MS,
|
|
4
5
|
MIN_MESSAGE_TTL_MS,
|
|
5
6
|
ProtocolError,
|
|
@@ -20,6 +21,8 @@ import {
|
|
|
20
21
|
type WorkflowEvidenceReferenceInput,
|
|
21
22
|
type WorkflowMessageContext,
|
|
22
23
|
} from "./protocol.ts";
|
|
24
|
+
import { redactSecrets } from "./redact.ts";
|
|
25
|
+
import { compareCodeUnitIds } from "./relevance.ts";
|
|
23
26
|
|
|
24
27
|
export type {
|
|
25
28
|
ImprovementArea,
|
|
@@ -350,7 +353,7 @@ export interface WorkflowJournalEntry {
|
|
|
350
353
|
relatedEntryIds: string[];
|
|
351
354
|
createdAt: string;
|
|
352
355
|
/** Stage the entry was recorded against. Optional: v0.4 entries and
|
|
353
|
-
|
|
356
|
+
* run-level entries have no stage binding. */
|
|
354
357
|
stageId?: string;
|
|
355
358
|
/** Attempt the entry was recorded against, when stage-bound. */
|
|
356
359
|
attempt?: number;
|
|
@@ -436,17 +439,8 @@ export interface ImprovementAreaReport {
|
|
|
436
439
|
}
|
|
437
440
|
|
|
438
441
|
export function improvementReport(entries: WorkflowJournalEntry[]): ImprovementAreaReport[] {
|
|
439
|
-
const areas: ImprovementArea[] = [
|
|
440
|
-
"harness",
|
|
441
|
-
"gates",
|
|
442
|
-
"implementation",
|
|
443
|
-
"workflow",
|
|
444
|
-
"documentation",
|
|
445
|
-
"security",
|
|
446
|
-
"other",
|
|
447
|
-
];
|
|
448
442
|
const severityWeight = { error: 3, warning: 2, info: 1 } as const;
|
|
449
|
-
return
|
|
443
|
+
return IMPROVEMENT_AREAS.map((area) => {
|
|
450
444
|
const matching = entries.filter((entry) => entry.area === area);
|
|
451
445
|
const priorities = [...matching]
|
|
452
446
|
.filter((entry) => entry.category === "error" || entry.category === "contradiction" || entry.category === "lesson" || entry.category === "skill-candidate")
|
|
@@ -463,6 +457,184 @@ export function improvementReport(entries: WorkflowJournalEntry[]): ImprovementA
|
|
|
463
457
|
}).filter((report) => report.total > 0);
|
|
464
458
|
}
|
|
465
459
|
|
|
460
|
+
/** Diagnostic classes that put a signal in the security tier regardless of
|
|
461
|
+
* its priority (diagnostics.ts). */
|
|
462
|
+
export const SECURITY_SIGNAL_CLASSES: readonly string[] = ["invalid_auth", "invalid_identity", "signal_mismatch"];
|
|
463
|
+
|
|
464
|
+
const SIGNAL_CATEGORIES: readonly JournalCategory[] = ["error", "contradiction", "lesson", "skill-candidate"];
|
|
465
|
+
const SIGNAL_SEVERITY_WEIGHT = { error: 3, warning: 2, info: 1 } as const;
|
|
466
|
+
const SIGNAL_CLASS = /^[a-z0-9_]{1,64}$/;
|
|
467
|
+
const MAX_SIGNAL_IDS = 16;
|
|
468
|
+
const MAX_SIGNAL_SUMMARY_KEY_CHARS = 160;
|
|
469
|
+
|
|
470
|
+
/** Collapse volatile tokens so the same failure in two runs keys the same.
|
|
471
|
+
* Callers redact first: lowercasing and digit folding would otherwise defeat
|
|
472
|
+
* the secret patterns. */
|
|
473
|
+
export function normalizeSignalSummary(summary: string): string {
|
|
474
|
+
return summary
|
|
475
|
+
.toLowerCase()
|
|
476
|
+
.replace(/\b[a-z]+_[0-9a-f]{8,}\b/g, "<id>")
|
|
477
|
+
.replace(/\b\d{4}-\d{2}-\d{2}t\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:z|[+-]\d{2}:?\d{2})?/g, "<ts>")
|
|
478
|
+
.replace(/\b[0-9a-f]{7,}\b/g, "<hex>")
|
|
479
|
+
.replace(/\d+/g, "#")
|
|
480
|
+
.replace(/\s+/g, " ")
|
|
481
|
+
.trim()
|
|
482
|
+
.slice(0, MAX_SIGNAL_SUMMARY_KEY_CHARS);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/** One improvement signal: journal entries from one or more runs that share
|
|
486
|
+
* a key, scored by frequency x severity x run-attempt cost x evidence
|
|
487
|
+
* confidence. Text is redacted; the key never carries raw summary text. */
|
|
488
|
+
export interface ImprovementSignal {
|
|
489
|
+
key: string;
|
|
490
|
+
/** Which rule produced the key: an evidence class, an error's stage, or the
|
|
491
|
+
* normalized summary. */
|
|
492
|
+
basis: "class" | "stage" | "summary";
|
|
493
|
+
category: JournalCategory;
|
|
494
|
+
/** Modal area of the grouped entries; ties follow IMPROVEMENT_AREAS order. */
|
|
495
|
+
area: ImprovementArea;
|
|
496
|
+
/** Security signals rank ahead of every priority. */
|
|
497
|
+
overrideTier?: "security";
|
|
498
|
+
/** Distinct runs that recorded this signal. */
|
|
499
|
+
frequency: number;
|
|
500
|
+
runIds: string[];
|
|
501
|
+
entryIds: string[];
|
|
502
|
+
severity: WorkflowJournalEntry["severity"];
|
|
503
|
+
severityWeight: number;
|
|
504
|
+
/** Mean run attempts (stage attempts plus transitions) over the known runs;
|
|
505
|
+
* null when none of the runs is known. */
|
|
506
|
+
workflowCost: number | null;
|
|
507
|
+
costBasis: "run-attempts" | "unknown";
|
|
508
|
+
/** 0.5 plus half the fraction of entries that cite evidence. */
|
|
509
|
+
confidence: number;
|
|
510
|
+
priority: number;
|
|
511
|
+
/** Redacted summary of the latest entry. */
|
|
512
|
+
summary: string;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function round3(value: number): number {
|
|
516
|
+
return Math.round(value * 1000) / 1000;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function signalKeyOf(
|
|
520
|
+
entry: WorkflowJournalEntry,
|
|
521
|
+
runs: ReadonlyMap<string, WorkflowRun>,
|
|
522
|
+
): { key: string; basis: ImprovementSignal["basis"]; signalClass?: string } {
|
|
523
|
+
const classRef = entry.evidence.find((ref) => ref.startsWith("class:"));
|
|
524
|
+
const signalClass = classRef?.slice("class:".length);
|
|
525
|
+
if (signalClass !== undefined && SIGNAL_CLASS.test(signalClass) && signalClass !== "unknown") {
|
|
526
|
+
return { key: `${entry.category}|class:${signalClass}`, basis: "class", signalClass };
|
|
527
|
+
}
|
|
528
|
+
const run = runs.get(entry.runId);
|
|
529
|
+
if (entry.category === "error" && entry.stageId !== undefined && run) {
|
|
530
|
+
return { key: `error|stage:${run.definitionId}/${entry.stageId}`, basis: "stage" };
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
key: `${entry.category}|summary:${normalizeSignalSummary(redactSecrets(entry.summary))}`,
|
|
534
|
+
basis: "summary",
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function runAttemptCost(run: WorkflowRun): number {
|
|
539
|
+
let attempts = 0;
|
|
540
|
+
for (const stage of run.stages) attempts += stage.attempts;
|
|
541
|
+
return Math.max(1, attempts + (run.transitions?.length ?? 0));
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** Merge journal learning across runs into ranked, redacted signals. Only
|
|
545
|
+
* errors, open contradictions, lessons and still-proposed skill candidates
|
|
546
|
+
* count. Security signals come first, then priority, frequency and key; no
|
|
547
|
+
* id or insertion order decides a tie. */
|
|
548
|
+
export function rankImprovementSignals(
|
|
549
|
+
entries: readonly WorkflowJournalEntry[],
|
|
550
|
+
runs: ReadonlyMap<string, WorkflowRun>,
|
|
551
|
+
limit = 20,
|
|
552
|
+
): ImprovementSignal[] {
|
|
553
|
+
const resolvedContradictions = new Set<string>();
|
|
554
|
+
for (const entry of entries) {
|
|
555
|
+
if (entry.category !== "decision" && entry.category !== "lesson") continue;
|
|
556
|
+
for (const related of entry.relatedEntryIds) resolvedContradictions.add(`${entry.runId}\u0000${related}`);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const groups = new Map<string, {
|
|
560
|
+
basis: ImprovementSignal["basis"];
|
|
561
|
+
category: JournalCategory;
|
|
562
|
+
signalClass?: string;
|
|
563
|
+
entries: WorkflowJournalEntry[];
|
|
564
|
+
}>();
|
|
565
|
+
for (const entry of entries) {
|
|
566
|
+
if (!SIGNAL_CATEGORIES.includes(entry.category)) continue;
|
|
567
|
+
if (entry.category === "contradiction" && resolvedContradictions.has(`${entry.runId}\u0000${entry.id}`)) continue;
|
|
568
|
+
const promotionState = journalPromotionState(entry);
|
|
569
|
+
if (promotionState !== undefined && promotionState !== "proposed") continue;
|
|
570
|
+
const { key, basis, signalClass } = signalKeyOf(entry, runs);
|
|
571
|
+
const group = groups.get(key);
|
|
572
|
+
if (group) group.entries.push(entry);
|
|
573
|
+
else groups.set(key, { basis, category: entry.category, ...(signalClass !== undefined ? { signalClass } : {}), entries: [entry] });
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const areaRank = (area: string): number => {
|
|
577
|
+
const index = IMPROVEMENT_AREAS.indexOf(area as ImprovementArea);
|
|
578
|
+
return index === -1 ? IMPROVEMENT_AREAS.length : index;
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
const signals: ImprovementSignal[] = [];
|
|
582
|
+
for (const [key, group] of groups) {
|
|
583
|
+
const runIds = [...new Set(group.entries.map((entry) => entry.runId))].sort(compareCodeUnitIds);
|
|
584
|
+
const entryIds = group.entries.map((entry) => entry.id).sort(compareCodeUnitIds);
|
|
585
|
+
|
|
586
|
+
let severity: WorkflowJournalEntry["severity"] = "info";
|
|
587
|
+
for (const entry of group.entries) {
|
|
588
|
+
if ((SIGNAL_SEVERITY_WEIGHT[entry.severity] ?? 0) > SIGNAL_SEVERITY_WEIGHT[severity]) severity = entry.severity;
|
|
589
|
+
}
|
|
590
|
+
const severityWeight = SIGNAL_SEVERITY_WEIGHT[severity];
|
|
591
|
+
|
|
592
|
+
const knownRuns = runIds.map((runId) => runs.get(runId)).filter((run): run is WorkflowRun => run !== undefined);
|
|
593
|
+
const workflowCost = knownRuns.length > 0
|
|
594
|
+
? knownRuns.reduce((total, run) => total + runAttemptCost(run), 0) / knownRuns.length
|
|
595
|
+
: null;
|
|
596
|
+
|
|
597
|
+
const withEvidence = group.entries.filter((entry) => entry.evidence.length > 0).length;
|
|
598
|
+
const confidence = 0.5 + 0.5 * (withEvidence / group.entries.length);
|
|
599
|
+
|
|
600
|
+
const areaCounts = new Map<ImprovementArea, number>();
|
|
601
|
+
for (const entry of group.entries) areaCounts.set(entry.area, (areaCounts.get(entry.area) ?? 0) + 1);
|
|
602
|
+
const area = [...areaCounts].sort((left, right) => right[1] - left[1] || areaRank(left[0]) - areaRank(right[0]))[0]![0];
|
|
603
|
+
|
|
604
|
+
const latest = [...group.entries].sort((left, right) =>
|
|
605
|
+
compareCodeUnitIds(left.createdAt, right.createdAt) || compareCodeUnitIds(left.id, right.id)).at(-1)!;
|
|
606
|
+
|
|
607
|
+
const security = area === "security"
|
|
608
|
+
|| (group.signalClass !== undefined && SECURITY_SIGNAL_CLASSES.includes(group.signalClass));
|
|
609
|
+
|
|
610
|
+
signals.push({
|
|
611
|
+
key,
|
|
612
|
+
basis: group.basis,
|
|
613
|
+
category: group.category,
|
|
614
|
+
area,
|
|
615
|
+
...(security ? { overrideTier: "security" as const } : {}),
|
|
616
|
+
frequency: runIds.length,
|
|
617
|
+
runIds: runIds.slice(0, MAX_SIGNAL_IDS),
|
|
618
|
+
entryIds: entryIds.slice(0, MAX_SIGNAL_IDS),
|
|
619
|
+
severity,
|
|
620
|
+
severityWeight,
|
|
621
|
+
workflowCost,
|
|
622
|
+
costBasis: workflowCost === null ? "unknown" : "run-attempts",
|
|
623
|
+
confidence,
|
|
624
|
+
priority: round3(runIds.length * severityWeight * (workflowCost ?? 1) * confidence),
|
|
625
|
+
summary: redactSecrets(latest.summary),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return signals
|
|
630
|
+
.sort((left, right) =>
|
|
631
|
+
(right.overrideTier === "security" ? 1 : 0) - (left.overrideTier === "security" ? 1 : 0)
|
|
632
|
+
|| right.priority - left.priority
|
|
633
|
+
|| right.frequency - left.frequency
|
|
634
|
+
|| compareCodeUnitIds(left.key, right.key))
|
|
635
|
+
.slice(0, limit);
|
|
636
|
+
}
|
|
637
|
+
|
|
466
638
|
function object(value: unknown, name: string): Record<string, unknown> {
|
|
467
639
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} must be an object`);
|
|
468
640
|
return value as Record<string, unknown>;
|
|
@@ -585,6 +757,24 @@ export function activeWorkflowAttempt(stage: Pick<WorkflowStageState, "attempts"
|
|
|
585
757
|
return stage.attempts + 1;
|
|
586
758
|
}
|
|
587
759
|
|
|
760
|
+
/** The attempt a stage-bound journal entry belongs to. An active or waiting
|
|
761
|
+
* stage is on its next attempt; a finished stage is on the last attempt it
|
|
762
|
+
* consumed; a pending stage that never ran has no attempt yet. The caller
|
|
763
|
+
* never supplies it. */
|
|
764
|
+
export function journalAttemptFor(stage: Pick<WorkflowStageState, "status" | "attempts">): number | undefined {
|
|
765
|
+
switch (stage.status) {
|
|
766
|
+
case "in_progress":
|
|
767
|
+
case "waiting":
|
|
768
|
+
return stage.attempts + 1;
|
|
769
|
+
case "pending":
|
|
770
|
+
return stage.attempts > 0 ? stage.attempts : undefined;
|
|
771
|
+
case "passed":
|
|
772
|
+
case "warning":
|
|
773
|
+
case "failed":
|
|
774
|
+
return Math.max(1, stage.attempts);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
588
778
|
export interface EvidenceLookup {
|
|
589
779
|
getMessage(id: string): MessageRecord | undefined;
|
|
590
780
|
}
|
|
@@ -998,7 +1188,7 @@ export function parseWorkflowDefinitions(
|
|
|
998
1188
|
const area = stage.area
|
|
999
1189
|
? requireString(stage.area, "stage.area", { max: 24 }) as ImprovementArea
|
|
1000
1190
|
: undefined;
|
|
1001
|
-
if (area && !
|
|
1191
|
+
if (area && !IMPROVEMENT_AREAS.includes(area)) {
|
|
1002
1192
|
throw new Error(`stage ${stageId} area is invalid`);
|
|
1003
1193
|
}
|
|
1004
1194
|
const requiredEvidence = stringArray(stage.requiredEvidence ?? [], "stage.requiredEvidence")
|
|
@@ -3,7 +3,12 @@ import { build } from "esbuild";
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
await build({
|
|
6
|
-
entryPoints: [
|
|
6
|
+
entryPoints: [
|
|
7
|
+
"plugins/kxm/src/cli.ts",
|
|
8
|
+
"plugins/kxm/src/server.ts",
|
|
9
|
+
"plugins/kxm/src/runtime-supervisor.ts",
|
|
10
|
+
"plugins/kxm/src/claude-hook.ts",
|
|
11
|
+
],
|
|
7
12
|
bundle: true,
|
|
8
13
|
platform: "node",
|
|
9
14
|
format: "esm",
|
|
@@ -41,6 +46,7 @@ for (const bundlePath of [
|
|
|
41
46
|
"plugins/kxm/dist/cli.js",
|
|
42
47
|
"plugins/kxm/dist/server.js",
|
|
43
48
|
"plugins/kxm/dist/runtime-supervisor.js",
|
|
49
|
+
"plugins/kxm/dist/claude-hook.js",
|
|
44
50
|
]) {
|
|
45
51
|
const bundled = readFileSync(bundlePath, "utf8");
|
|
46
52
|
if (!bundled.startsWith(shebang)) throw new Error(`runtime bundle is missing its executable shebang: ${bundlePath}`);
|
|
@@ -15,6 +15,7 @@ export const STATIC_GENERATED_ARTIFACTS = Object.freeze([
|
|
|
15
15
|
"plugins/kxm/dist/runtime.js",
|
|
16
16
|
"plugins/kxm/dist/client.js",
|
|
17
17
|
"plugins/kxm/dist/extension.js",
|
|
18
|
+
"plugins/kxm/dist/claude-hook.js",
|
|
18
19
|
"packages/core/tui/dist/index.js",
|
|
19
20
|
"AGENTS.md",
|
|
20
21
|
"CLAUDE.md",
|
|
@@ -43,7 +43,7 @@ The \`kxm\` CLI is the unified agent surface for peer collaboration and workflow
|
|
|
43
43
|
| Command | Purpose | Key options |
|
|
44
44
|
|---|---|---|
|
|
45
45
|
| \`kxm workflow checkpoint [runId] [stageId] [status] [summary]\` | Record stage result with verified evidence | \`--run-id\`, \`--stage-id\`, \`--status <passed\\|warning\\|failed>\`, \`--summary\`, \`--evidence <json>\`, \`--evidence-refs <json>\` |
|
|
46
|
-
| \`kxm workflow record [runId] [category] [area] [summary]\` | Record
|
|
46
|
+
| \`kxm workflow record [runId] [category] [area] [summary]\` | Record journal knowledge in one of ten categories; area is optional with \`--stage-id\` | \`--run-id\`, \`--category <plan\\|decision\\|contradiction\\|error\\|lesson\\|observation\\|hypothesis\\|experiment\\|state-change\\|skill-candidate>\`, \`--stage-id\`, \`--area\`, \`--severity <info\\|warning\\|error>\`, \`--details\`, \`--evidence <items...>\` |
|
|
47
47
|
| \`kxm workflow wait [runId] [stageId] [signalKey] [summary]\` | Pause stage until an external signed signal arrives | \`--run-id\`, \`--stage-id\`, \`--signal-key\`, \`--summary\`, \`--evidence <json>\`, \`--evidence-refs <json>\`, \`--timeout-ms\` |
|
|
48
48
|
| \`kxm workflow signal <runId> <signalKey> <status> <summary>\` | Resume or unblock a waiting stage or KXM run | \`[evidence...]\`, \`--delivery-id\` |
|
|
49
49
|
| \`kxm workflow list\` | List local workflow runs | \`--json\` |
|