@useorgx/wizard 0.1.27 → 0.1.28

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
@@ -6908,6 +6908,10 @@ function shortHash(value, length = 16) {
6908
6908
  function sortedUnique(values) {
6909
6909
  return [...new Set(values)].sort();
6910
6910
  }
6911
+ function slugPart(value) {
6912
+ const normalized = normalizeFingerprintText(value).replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 64);
6913
+ return normalized || "unknown";
6914
+ }
6911
6915
  function sourceClientForImport(source) {
6912
6916
  const raw = `${source.sourceId} ${source.sourceLabel}`.toLowerCase();
6913
6917
  if (raw.includes("codex")) return "codex";
@@ -7169,6 +7173,491 @@ function buildKickoffs(findings, missed, score) {
7169
7173
  }
7170
7174
  return kickoffs.slice(0, 3);
7171
7175
  }
7176
+ function entityTypeForFinding(finding) {
7177
+ switch (finding.type) {
7178
+ case "decision":
7179
+ return "decision";
7180
+ case "artifact":
7181
+ return "artifact";
7182
+ case "blocker":
7183
+ return "blocker";
7184
+ case "person":
7185
+ return "person";
7186
+ case "business":
7187
+ return "business";
7188
+ case "product_surface":
7189
+ return "surface";
7190
+ case "goal":
7191
+ case "initiative_candidate":
7192
+ return "initiative";
7193
+ case "action":
7194
+ return /\b(outcome|shipped|completed|verified)\b/i.test(finding.summary) ? "outcome" : "task";
7195
+ case "missed_orchestration_opportunity":
7196
+ return "source";
7197
+ }
7198
+ }
7199
+ function trailKindForEntity(entityType) {
7200
+ switch (entityType) {
7201
+ case "decision":
7202
+ return "decision_trail";
7203
+ case "artifact":
7204
+ return "artifact_trail";
7205
+ case "person":
7206
+ return "person_trail";
7207
+ case "business":
7208
+ return "business_trail";
7209
+ case "blocker":
7210
+ return "blocker_trail";
7211
+ case "agent":
7212
+ return "agent_trail";
7213
+ case "tool":
7214
+ case "source":
7215
+ return "source_trail";
7216
+ case "outcome":
7217
+ return "outcome_trail";
7218
+ case "idea":
7219
+ return "idea_trail";
7220
+ case "initiative":
7221
+ case "workstream":
7222
+ case "milestone":
7223
+ case "task":
7224
+ case "surface":
7225
+ return "initiative_trail";
7226
+ }
7227
+ }
7228
+ function eventTypeForFinding(finding) {
7229
+ switch (finding.type) {
7230
+ case "decision":
7231
+ return "decision_inferred";
7232
+ case "artifact":
7233
+ return /\b(verified|proof|tested|passed)\b/i.test(finding.summary) ? "artifact_verified" : "artifact_created";
7234
+ case "blocker":
7235
+ return "blocker_detected";
7236
+ case "person":
7237
+ return "owner_assigned";
7238
+ case "business":
7239
+ return "signal_detected";
7240
+ case "product_surface":
7241
+ return "signal_detected";
7242
+ case "goal":
7243
+ case "initiative_candidate":
7244
+ return "initiative_created";
7245
+ case "action":
7246
+ return /\b(outcome|result|impact|roi)\b/i.test(finding.summary) ? "outcome_recorded" : "recommendation_generated";
7247
+ case "missed_orchestration_opportunity":
7248
+ return "source_connected";
7249
+ }
7250
+ }
7251
+ function trailStateForFindings(findings) {
7252
+ if (findings.some((finding) => finding.type === "blocker")) return "blocked";
7253
+ if (findings.some((finding) => finding.type === "missed_orchestration_opportunity")) return "missing_evidence";
7254
+ if (findings.some((finding) => /\b(contradict|conflict)\b/i.test(finding.summary))) return "contradicted";
7255
+ if (findings.some((finding) => /\b(verified|proof|passed|complete_with_proof)\b/i.test(finding.summary))) return "verified";
7256
+ if (findings.some((finding) => finding.type === "decision")) return "inferred";
7257
+ return "observed";
7258
+ }
7259
+ function trailValenceForFindings(findings, recurrence) {
7260
+ if (findings.some((finding) => finding.type === "blocker")) return recurrence > 1 ? "escalating" : "risk";
7261
+ if (findings.some((finding) => finding.type === "missed_orchestration_opportunity")) return "leak";
7262
+ if (findings.some((finding) => finding.type === "decision") && recurrence > 1) return "wasteful_recurrence";
7263
+ if (findings.some((finding) => finding.type === "business")) return "opportunity";
7264
+ if (findings.some((finding) => finding.type === "artifact")) return "healthy";
7265
+ return recurrence > 1 ? "useful_recurrence" : "opportunity";
7266
+ }
7267
+ function trailShapeForFindings(findings, recurrence) {
7268
+ const decisions = findings.filter((finding) => finding.type === "decision").length;
7269
+ const artifacts = findings.filter((finding) => finding.type === "artifact").length;
7270
+ if (decisions > artifacts && decisions > 0) return "decision_heavy_artifact_light";
7271
+ if (artifacts > decisions && artifacts > 0 && decisions === 0) return "artifact_heavy_decision_light";
7272
+ if (findings.some((finding) => finding.type === "blocker")) return "accelerating_issue";
7273
+ if (recurrence >= 3) return "chronic_recurrence";
7274
+ if (findings.some((finding) => /\b(resurface|again|back|revived|reappeared)\b/i.test(finding.summary))) return "zombie_revival";
7275
+ if (findings.some((finding) => /\b(verified|passed|shipped|completed)\b/i.test(finding.summary))) return "healthy_execution";
7276
+ return "dense_recent_cluster";
7277
+ }
7278
+ function buildWorkGraphTrails(findings, generatedAt) {
7279
+ const grouped = /* @__PURE__ */ new Map();
7280
+ for (const finding of findings) {
7281
+ const entityType = entityTypeForFinding(finding);
7282
+ const key = `${entityType}:${slugPart(finding.title)}`;
7283
+ grouped.set(key, [...grouped.get(key) ?? [], finding]);
7284
+ }
7285
+ return [...grouped.entries()].map(([key, group], index) => {
7286
+ const first = group[0];
7287
+ const entityType = entityTypeForFinding(first);
7288
+ const entityId = `${entityType}:${shortHash(key, 12)}`;
7289
+ const trailId = `trail:${shortHash({ key, evidence: group.map((finding) => finding.evidence_ref) }, 14)}`;
7290
+ const recurrence = group.length;
7291
+ const evidenceRefs = sortedUnique(group.map((finding) => finding.evidence_ref));
7292
+ const events = group.map((finding, eventIndex) => ({
7293
+ id: `${trailId}:event:${eventIndex + 1}`,
7294
+ trail_id: trailId,
7295
+ event_type: eventTypeForFinding(finding),
7296
+ entity_id: entityId,
7297
+ entity_type: entityType,
7298
+ timestamp: generatedAt,
7299
+ source_id: finding.source_id,
7300
+ source_type: finding.source_client,
7301
+ redacted_verbatim: finding.summary.slice(0, 320),
7302
+ confidence: finding.confidence,
7303
+ evidence_refs: [finding.evidence_ref],
7304
+ privacy_state: "redacted"
7305
+ }));
7306
+ const edges = events.slice(1).map((event, edgeIndex) => ({
7307
+ id: `${trailId}:edge:${edgeIndex + 1}`,
7308
+ from_event_id: events[edgeIndex].id,
7309
+ to_event_id: event.id,
7310
+ relation: group.some((finding) => finding.type === "blocker") ? "blocked" : "informed",
7311
+ state: recurrence > 1 ? "captured" : "inferred",
7312
+ confidence: Math.min(0.92, Math.max(0.58, event.confidence - 0.04)),
7313
+ evidence_refs: event.evidence_refs
7314
+ }));
7315
+ const confidence = group.reduce((total, finding) => total + finding.confidence, 0) / group.length;
7316
+ return {
7317
+ id: trailId,
7318
+ kind: trailKindForEntity(entityType),
7319
+ title: first.title,
7320
+ summary: first.summary,
7321
+ subject_entity_id: entityId,
7322
+ subject_entity_type: entityType,
7323
+ state: trailStateForFindings(group),
7324
+ valence: trailValenceForFindings(group, recurrence),
7325
+ confidence: Number(confidence.toFixed(2)),
7326
+ recurrence_score: Math.min(100, recurrence * 28 + evidenceRefs.length * 6),
7327
+ impact_score: Math.min(100, Math.round(first.confidence * 70) + recurrence * 8 + (index < 4 ? 10 : 0)),
7328
+ privacy_state: "redacted",
7329
+ events,
7330
+ edges,
7331
+ evidence_refs: evidenceRefs,
7332
+ blocker_ids: group.filter((finding) => finding.type === "blocker").map((finding) => finding.evidence_ref),
7333
+ recommendation_ids: [],
7334
+ created_at: generatedAt,
7335
+ updated_at: generatedAt,
7336
+ shape: trailShapeForFindings(group, recurrence)
7337
+ };
7338
+ });
7339
+ }
7340
+ function severityFor(count) {
7341
+ if (count >= 6) return "critical";
7342
+ if (count >= 3) return "high";
7343
+ if (count >= 2) return "medium";
7344
+ return "low";
7345
+ }
7346
+ function trailsForType(trails, entityType) {
7347
+ return trails.filter((trail) => trail.subject_entity_type === entityType);
7348
+ }
7349
+ function buildRecurringPatterns(coverage, findings, trails) {
7350
+ const patterns = [];
7351
+ const decisionTrails = trailsForType(trails, "decision");
7352
+ const artifactTrails = trailsForType(trails, "artifact");
7353
+ const blockerTrails = trailsForType(trails, "blocker");
7354
+ const personTrails = trailsForType(trails, "person");
7355
+ const businessTrails = trailsForType(trails, "business");
7356
+ const highRecurrence = trails.filter((trail) => trail.recurrence_score >= 56);
7357
+ if (decisionTrails.length > 0 && !coverage.orgxMcpCalled) {
7358
+ patterns.push({
7359
+ id: "pattern:trapped-decision",
7360
+ title: "Decisions are being made without durable OrgX writeback",
7361
+ description: `${decisionTrails.length} decision trail${decisionTrails.length === 1 ? "" : "s"} appeared while no OrgX MCP write was detected.`,
7362
+ pattern_type: "trapped_decision",
7363
+ affected_trail_ids: decisionTrails.map((trail) => trail.id),
7364
+ affected_entity_ids: decisionTrails.map((trail) => trail.subject_entity_id),
7365
+ recurrence_count: decisionTrails.length,
7366
+ severity: severityFor(decisionTrails.length + 1),
7367
+ confidence: coverage.orgxObserved ? 0.82 : 0.74,
7368
+ valence: "leak",
7369
+ root_cause_hypothesis: "Agents and humans are making useful choices, but the runtime is not promoting those choices into organizational memory.",
7370
+ recommended_runtime_action_id: "recommendation:promote-decisions"
7371
+ });
7372
+ }
7373
+ if (artifactTrails.length > 0 && personTrails.length === 0) {
7374
+ patterns.push({
7375
+ id: "pattern:orphaned-artifact",
7376
+ title: "Artifacts do not have visible ownership",
7377
+ description: `${artifactTrails.length} artifact trail${artifactTrails.length === 1 ? "" : "s"} appeared without a clear owner trail.`,
7378
+ pattern_type: "orphaned_artifact",
7379
+ affected_trail_ids: artifactTrails.map((trail) => trail.id),
7380
+ affected_entity_ids: artifactTrails.map((trail) => trail.subject_entity_id),
7381
+ recurrence_count: artifactTrails.length,
7382
+ severity: severityFor(artifactTrails.length),
7383
+ confidence: 0.72,
7384
+ valence: "risk",
7385
+ root_cause_hypothesis: "Work is becoming concrete, but downstream accountability is not being attached at creation time.",
7386
+ recommended_runtime_action_id: "recommendation:assign-owner"
7387
+ });
7388
+ }
7389
+ if (coverage.missing.length > 0) {
7390
+ const sourceTrails = trailsForType(trails, "source");
7391
+ patterns.push({
7392
+ id: "pattern:missing-source",
7393
+ title: "Important source coverage is missing",
7394
+ description: `Missing sources: ${coverage.missing.join(", ")}.`,
7395
+ pattern_type: "missing_source",
7396
+ affected_trail_ids: sourceTrails.map((trail) => trail.id),
7397
+ affected_entity_ids: sourceTrails.map((trail) => trail.subject_entity_id),
7398
+ recurrence_count: coverage.missing.length,
7399
+ severity: severityFor(coverage.missing.length),
7400
+ confidence: 0.78,
7401
+ valence: "leak",
7402
+ root_cause_hypothesis: "The scan can see work happening, but coordination and proof sources are not fully connected.",
7403
+ recommended_runtime_action_id: "recommendation:connect-source"
7404
+ });
7405
+ }
7406
+ if (coverage.mcpObserved && !coverage.orgxMcpCalled) {
7407
+ patterns.push({
7408
+ id: "pattern:tooling-mismatch",
7409
+ title: "MCP was present, but OrgX was not called",
7410
+ description: "The session mentions MCP/tooling activity, but no durable OrgX MCP call was detected.",
7411
+ pattern_type: "tooling_mismatch",
7412
+ affected_trail_ids: trails.map((trail) => trail.id).slice(0, 6),
7413
+ affected_entity_ids: trails.map((trail) => trail.subject_entity_id).slice(0, 6),
7414
+ recurrence_count: findings.filter((finding) => /\bmcp|tool\b/i.test(finding.summary)).length || 1,
7415
+ severity: "high",
7416
+ confidence: 0.8,
7417
+ valence: "leak",
7418
+ root_cause_hypothesis: "The available tool layer is not automatically closing the loop when work finishes.",
7419
+ recommended_runtime_action_id: "recommendation:install-runtime-hooks"
7420
+ });
7421
+ }
7422
+ if (highRecurrence.length > 0) {
7423
+ patterns.push({
7424
+ id: "pattern:repeated-work",
7425
+ title: "The same work shape is recurring",
7426
+ description: `${highRecurrence.length} trail${highRecurrence.length === 1 ? "" : "s"} repeat strongly enough to deserve durable operating memory.`,
7427
+ pattern_type: "repeated_work",
7428
+ affected_trail_ids: highRecurrence.map((trail) => trail.id),
7429
+ affected_entity_ids: highRecurrence.map((trail) => trail.subject_entity_id),
7430
+ recurrence_count: highRecurrence.reduce((total, trail) => total + trail.events.length, 0),
7431
+ severity: severityFor(highRecurrence.length),
7432
+ confidence: 0.7,
7433
+ valence: "useful_recurrence",
7434
+ root_cause_hypothesis: "Repeated work is creating a reusable operating pattern, but it is still only implicit.",
7435
+ recommended_runtime_action_id: "recommendation:launch-initiative"
7436
+ });
7437
+ }
7438
+ if (businessTrails.length > 0 && findings.every((finding) => finding.type !== "initiative_candidate")) {
7439
+ patterns.push({
7440
+ id: "pattern:business-signal-unclaimed",
7441
+ title: "Business signal has not become a launchable initiative",
7442
+ description: `${businessTrails.length} business trail${businessTrails.length === 1 ? "" : "s"} appeared without a matching initiative candidate.`,
7443
+ pattern_type: "business_signal_unclaimed",
7444
+ affected_trail_ids: businessTrails.map((trail) => trail.id),
7445
+ affected_entity_ids: businessTrails.map((trail) => trail.subject_entity_id),
7446
+ recurrence_count: businessTrails.length,
7447
+ severity: severityFor(businessTrails.length),
7448
+ confidence: 0.68,
7449
+ valence: "opportunity",
7450
+ root_cause_hypothesis: "Revenue or ROI signal exists, but the operating graph has not turned it into an account or initiative loop.",
7451
+ recommended_runtime_action_id: "recommendation:launch-initiative"
7452
+ });
7453
+ }
7454
+ if (blockerTrails.length > 0) {
7455
+ patterns.push({
7456
+ id: "pattern:handoff-friction",
7457
+ title: "Blockers are becoming handoff friction",
7458
+ description: `${blockerTrails.length} blocker trail${blockerTrails.length === 1 ? "" : "s"} need owner-visible resolution.`,
7459
+ pattern_type: "handoff_friction",
7460
+ affected_trail_ids: blockerTrails.map((trail) => trail.id),
7461
+ affected_entity_ids: blockerTrails.map((trail) => trail.subject_entity_id),
7462
+ recurrence_count: blockerTrails.length,
7463
+ severity: severityFor(blockerTrails.length + 1),
7464
+ confidence: 0.76,
7465
+ valence: "risk",
7466
+ root_cause_hypothesis: "Execution is producing unresolved edges that need to become assigned decisions or tasks.",
7467
+ recommended_runtime_action_id: "recommendation:assign-owner"
7468
+ });
7469
+ }
7470
+ return patterns.slice(0, 8);
7471
+ }
7472
+ function buildTrailRecommendations(patterns, trails) {
7473
+ const recommendations = [];
7474
+ const add = (recommendation) => {
7475
+ if (!recommendations.some((existing) => existing.id === recommendation.id)) {
7476
+ recommendations.push(recommendation);
7477
+ }
7478
+ };
7479
+ for (const pattern of patterns) {
7480
+ const evidenceRefs = sortedUnique(
7481
+ trails.filter((trail) => pattern.affected_trail_ids.includes(trail.id)).flatMap((trail) => trail.evidence_refs)
7482
+ ).slice(0, 8);
7483
+ if (pattern.pattern_type === "trapped_decision") {
7484
+ add({
7485
+ id: "recommendation:promote-decisions",
7486
+ title: "Promote trapped decisions",
7487
+ summary: "Turn inferred decisions into reviewed OrgX decision records with owners and downstream artifact links.",
7488
+ action_type: "promote_decision",
7489
+ trail_ids: pattern.affected_trail_ids,
7490
+ evidence_refs: evidenceRefs,
7491
+ priority: pattern.severity === "critical" || pattern.severity === "high" ? "p0" : "p1",
7492
+ expected_lift: "+decision durability",
7493
+ confidence: pattern.confidence
7494
+ });
7495
+ } else if (pattern.pattern_type === "orphaned_artifact") {
7496
+ add({
7497
+ id: "recommendation:assign-owner",
7498
+ title: "Assign ownership to orphaned artifacts",
7499
+ summary: "Attach owners and next actions to artifacts before they decay into unqueryable receipts.",
7500
+ action_type: "assign_owner",
7501
+ trail_ids: pattern.affected_trail_ids,
7502
+ evidence_refs: evidenceRefs,
7503
+ priority: "p1",
7504
+ expected_lift: "+owner clarity",
7505
+ confidence: pattern.confidence
7506
+ });
7507
+ } else if (pattern.pattern_type === "missing_source") {
7508
+ add({
7509
+ id: "recommendation:connect-source",
7510
+ title: "Connect missing source coverage",
7511
+ summary: "Close the evidence gap by connecting the coordination or proof sources where trails terminate.",
7512
+ action_type: "connect_source",
7513
+ trail_ids: pattern.affected_trail_ids,
7514
+ evidence_refs: evidenceRefs,
7515
+ priority: "p1",
7516
+ expected_lift: "+source confidence",
7517
+ confidence: pattern.confidence
7518
+ });
7519
+ } else if (pattern.pattern_type === "tooling_mismatch") {
7520
+ add({
7521
+ id: "recommendation:install-runtime-hooks",
7522
+ title: "Install runtime writeback hooks",
7523
+ summary: "Use post-session reconciliation so useful work becomes OrgX activity even when the agent forgets.",
7524
+ action_type: "verify_outcome",
7525
+ trail_ids: pattern.affected_trail_ids,
7526
+ evidence_refs: evidenceRefs,
7527
+ priority: "p0",
7528
+ expected_lift: "+continuous attribution",
7529
+ confidence: pattern.confidence
7530
+ });
7531
+ } else if (pattern.pattern_type === "business_signal_unclaimed" || pattern.pattern_type === "repeated_work") {
7532
+ add({
7533
+ id: "recommendation:launch-initiative",
7534
+ title: "Launch from this trail",
7535
+ summary: "Convert the highest-recurring evidence path into an OrgX initiative with proof requirements.",
7536
+ action_type: "launch_initiative",
7537
+ trail_ids: pattern.affected_trail_ids,
7538
+ evidence_refs: evidenceRefs,
7539
+ priority: pattern.severity === "critical" || pattern.severity === "high" ? "p0" : "p1",
7540
+ expected_lift: "+initiative readiness",
7541
+ confidence: pattern.confidence
7542
+ });
7543
+ }
7544
+ }
7545
+ if (recommendations.length === 0 && trails.length > 0) {
7546
+ const topTrail = [...trails].sort((a, b) => b.impact_score - a.impact_score)[0];
7547
+ add({
7548
+ id: "recommendation:inspect-top-trail",
7549
+ title: "Inspect the strongest trail",
7550
+ summary: "Review the highest-confidence evidence path and decide whether it should become durable OrgX memory.",
7551
+ action_type: "launch_initiative",
7552
+ trail_ids: [topTrail.id],
7553
+ evidence_refs: topTrail.evidence_refs,
7554
+ priority: "p2",
7555
+ expected_lift: "+operating memory",
7556
+ confidence: topTrail.confidence
7557
+ });
7558
+ }
7559
+ return recommendations.slice(0, 5);
7560
+ }
7561
+ function buildWorkGraphMirror(input) {
7562
+ const { coverage, generatedAt, patterns, recommendations, trails } = input;
7563
+ const topTrail = [...trails].sort((a, b) => b.impact_score - a.impact_score)[0];
7564
+ const topPattern = [...patterns].sort((a, b) => b.recurrence_count - a.recurrence_count)[0];
7565
+ const decisionCount = trailsForType(trails, "decision").length;
7566
+ const artifactCount = trailsForType(trails, "artifact").length;
7567
+ const blockerCount = trailsForType(trails, "blocker").length;
7568
+ const sourceGapCount = coverage.missing.length;
7569
+ const headline = topPattern ? topPattern.title : topTrail ? `${topTrail.title} is the clearest work trail` : "Your work is leaving an operating trail";
7570
+ const primaryClaimRefs = topTrail?.evidence_refs ?? [];
7571
+ const claims = [
7572
+ {
7573
+ id: "mirror:trail-count",
7574
+ text: `${trails.length} trails were detected across ${coverage.connected.length} connected source${coverage.connected.length === 1 ? "" : "s"}.`,
7575
+ evidence_refs: trails.flatMap((trail) => trail.evidence_refs).slice(0, 6),
7576
+ confidence: trails.length > 0 ? 0.82 : 0.55
7577
+ },
7578
+ {
7579
+ id: "mirror:decision-artifact-balance",
7580
+ text: `${decisionCount} decision trail${decisionCount === 1 ? "" : "s"} and ${artifactCount} artifact trail${artifactCount === 1 ? "" : "s"} were found.`,
7581
+ evidence_refs: trails.filter((trail) => trail.subject_entity_type === "decision" || trail.subject_entity_type === "artifact").flatMap((trail) => trail.evidence_refs).slice(0, 6),
7582
+ confidence: 0.78
7583
+ },
7584
+ {
7585
+ id: "mirror:missing-sources",
7586
+ text: sourceGapCount > 0 ? `${sourceGapCount} source gap${sourceGapCount === 1 ? "" : "s"} still limit attribution depth.` : "The connected sources are enough for a first operating profile.",
7587
+ evidence_refs: trailsForType(trails, "source").flatMap((trail) => trail.evidence_refs).slice(0, 4),
7588
+ confidence: sourceGapCount > 0 ? 0.76 : 0.66
7589
+ }
7590
+ ];
7591
+ const body = [
7592
+ `OrgX found ${trails.length} evidence trail${trails.length === 1 ? "" : "s"} across ${coverage.connected.join(", ") || "local sources"}.`,
7593
+ `The strongest signal is ${topPattern ? topPattern.title.toLowerCase() : topTrail?.title ?? "still forming"}.`,
7594
+ blockerCount > 0 ? `${blockerCount} blocker trail${blockerCount === 1 ? "" : "s"} need promotion into owner-visible work.` : "The healthiest trails already connect evidence to action.",
7595
+ recommendations[0] ? `The next durable move is: ${recommendations[0].title}.` : "The next move is to inspect the highest-confidence trail before publishing it."
7596
+ ].join(" ");
7597
+ return {
7598
+ headline,
7599
+ body,
7600
+ lens: "all",
7601
+ claims,
7602
+ ...topTrail ? { primary_trail_id: topTrail.id } : {},
7603
+ generated_at: generatedAt
7604
+ };
7605
+ }
7606
+ function buildTensionMetrics(input) {
7607
+ const { coverage, patterns, trails } = input;
7608
+ const decisionTrails = trailsForType(trails, "decision");
7609
+ const blockerTrails = trailsForType(trails, "blocker");
7610
+ const artifactTrails = trailsForType(trails, "artifact");
7611
+ const missingSourceTrails = trailsForType(trails, "source");
7612
+ const topReady = trails.filter((trail) => trail.impact_score >= 70 && trail.confidence >= 0.75);
7613
+ return [
7614
+ {
7615
+ id: "tension:work-leaks",
7616
+ label: "work leaks",
7617
+ value: String(patterns.filter((pattern) => pattern.valence === "leak" || pattern.valence === "risk").length),
7618
+ tone: patterns.some((pattern) => pattern.severity === "critical" || pattern.severity === "high") ? "danger" : "warning",
7619
+ trail_ids: patterns.flatMap((pattern) => pattern.affected_trail_ids).slice(0, 8),
7620
+ evidence_refs: trails.flatMap((trail) => trail.evidence_refs).slice(0, 8),
7621
+ explanation: "Patterns where evidence exists but ownership, source coverage, or writeback is incomplete."
7622
+ },
7623
+ {
7624
+ id: "tension:decisions-decaying",
7625
+ label: "decisions decaying",
7626
+ value: String(decisionTrails.filter((trail) => trail.state === "inferred" || trail.state === "missing_evidence").length),
7627
+ tone: decisionTrails.length > 0 && !coverage.orgxMcpCalled ? "danger" : "muted",
7628
+ trail_ids: decisionTrails.map((trail) => trail.id),
7629
+ evidence_refs: decisionTrails.flatMap((trail) => trail.evidence_refs).slice(0, 8),
7630
+ explanation: "Decision trails that have not been promoted into durable OrgX records."
7631
+ },
7632
+ {
7633
+ id: "tension:artifacts-orphaned",
7634
+ label: "artifacts orphaned",
7635
+ value: String(artifactTrails.filter((trail) => trail.state !== "verified").length),
7636
+ tone: artifactTrails.some((trail) => trail.shape === "artifact_heavy_decision_light") ? "warning" : "muted",
7637
+ trail_ids: artifactTrails.map((trail) => trail.id),
7638
+ evidence_refs: artifactTrails.flatMap((trail) => trail.evidence_refs).slice(0, 8),
7639
+ explanation: "Artifacts that exist without complete decision, verification, or owner context."
7640
+ },
7641
+ {
7642
+ id: "tension:sources-missing",
7643
+ label: "sources missing",
7644
+ value: String(coverage.missing.length),
7645
+ tone: coverage.missing.length > 0 ? "warning" : "good",
7646
+ trail_ids: missingSourceTrails.map((trail) => trail.id),
7647
+ evidence_refs: missingSourceTrails.flatMap((trail) => trail.evidence_refs).slice(0, 6),
7648
+ explanation: "Disconnected coordination or proof sources that limit attribution confidence."
7649
+ },
7650
+ {
7651
+ id: "tension:launch-ready",
7652
+ label: "launch ready",
7653
+ value: String(topReady.length),
7654
+ tone: topReady.length > 0 && blockerTrails.length === 0 ? "good" : "muted",
7655
+ trail_ids: topReady.map((trail) => trail.id).slice(0, 6),
7656
+ evidence_refs: topReady.flatMap((trail) => trail.evidence_refs).slice(0, 8),
7657
+ explanation: "High-confidence trails that can become initiatives, decisions, artifacts, or owner-visible follow-ups."
7658
+ }
7659
+ ];
7660
+ }
7172
7661
  function countFindingsByType(findings) {
7173
7662
  const counts = {};
7174
7663
  for (const finding of findings) {
@@ -7195,6 +7684,24 @@ function buildWorkGraphFingerprint(input) {
7195
7684
  priority: kickoff.priority
7196
7685
  })
7197
7686
  ).sort();
7687
+ const trailShapeHashes = input.trails.map(
7688
+ (trail) => shortHash({
7689
+ kind: trail.kind,
7690
+ subject_entity_type: trail.subject_entity_type,
7691
+ state: trail.state,
7692
+ valence: trail.valence,
7693
+ shape: trail.shape,
7694
+ title: normalizeFingerprintText(trail.title)
7695
+ })
7696
+ ).sort();
7697
+ const recurringPatternHashes = input.recurringPatterns.map(
7698
+ (pattern) => shortHash({
7699
+ pattern_type: pattern.pattern_type,
7700
+ severity: pattern.severity,
7701
+ title: normalizeFingerprintText(pattern.title),
7702
+ recurrence_count: pattern.recurrence_count
7703
+ })
7704
+ ).sort();
7198
7705
  const basis = {
7199
7706
  schema_version: WORK_GRAPH_SCHEMA_VERSION,
7200
7707
  fingerprint_version: WORK_GRAPH_FINGERPRINT_VERSION,
@@ -7211,6 +7718,8 @@ function buildWorkGraphFingerprint(input) {
7211
7718
  ),
7212
7719
  finding_type_counts: countFindingsByType(input.findings),
7213
7720
  pattern_hashes: patternHashes,
7721
+ trail_shape_hashes: trailShapeHashes,
7722
+ recurring_pattern_hashes: recurringPatternHashes,
7214
7723
  kickoff_hashes: kickoffHashes,
7215
7724
  raw_transcripts_included: false
7216
7725
  };
@@ -7241,13 +7750,30 @@ function buildSessionReconciliationReport(input) {
7241
7750
  const findings = buildWorkGraphFindings(input.imports);
7242
7751
  const missed = buildMissedOpportunities(coverage, findings);
7243
7752
  const allFindings = [...findings, ...missed];
7753
+ const trails = buildWorkGraphTrails(allFindings, generatedAt);
7754
+ const recurringPatterns = buildRecurringPatterns(coverage, allFindings, trails);
7244
7755
  const opportunityScore = scoreOpportunity(coverage, allFindings);
7245
7756
  const initiativeKickoffs = buildKickoffs(allFindings, missed, opportunityScore);
7757
+ const recommendations = buildTrailRecommendations(recurringPatterns, trails);
7758
+ const mirror = buildWorkGraphMirror({
7759
+ coverage,
7760
+ generatedAt,
7761
+ patterns: recurringPatterns,
7762
+ recommendations,
7763
+ trails
7764
+ });
7765
+ const tensionMetrics = buildTensionMetrics({
7766
+ coverage,
7767
+ patterns: recurringPatterns,
7768
+ trails
7769
+ });
7246
7770
  const fingerprint = buildWorkGraphFingerprint({
7247
7771
  connectedSources,
7248
7772
  findings: allFindings,
7249
7773
  kickoffs: initiativeKickoffs,
7250
7774
  missingSources,
7775
+ recurringPatterns,
7776
+ trails,
7251
7777
  workspace: input.workspace
7252
7778
  });
7253
7779
  const reportSeed = {
@@ -7277,6 +7803,11 @@ function buildSessionReconciliationReport(input) {
7277
7803
  events,
7278
7804
  findings: allFindings,
7279
7805
  missed_orchestration_opportunities: missed,
7806
+ trails,
7807
+ recurring_patterns: recurringPatterns,
7808
+ recommendations,
7809
+ mirror,
7810
+ tension_metrics: tensionMetrics,
7280
7811
  opportunity_score: opportunityScore,
7281
7812
  initiative_kickoffs: initiativeKickoffs,
7282
7813
  redaction_level: "summary_only",
@@ -7312,6 +7843,38 @@ function renderWorkGraphMarkdown(report) {
7312
7843
  lines.push(`OrgX observed: ${report.source_coverage.orgxObserved ? "yes" : "no"}`);
7313
7844
  lines.push(`OrgX MCP called: ${report.source_coverage.orgxMcpCalled ? "yes" : "no"}`);
7314
7845
  lines.push("");
7846
+ lines.push("## Mirror");
7847
+ lines.push("");
7848
+ lines.push(`### ${report.mirror.headline}`);
7849
+ lines.push("");
7850
+ lines.push(report.mirror.body);
7851
+ lines.push("");
7852
+ for (const claim of report.mirror.claims) {
7853
+ lines.push(`- ${claim.text} (${claim.evidence_refs.join(", ") || "no evidence refs"})`);
7854
+ }
7855
+ lines.push("");
7856
+ lines.push("## Live Tension");
7857
+ lines.push("");
7858
+ for (const metric of report.tension_metrics) {
7859
+ lines.push(`- ${metric.value} ${metric.label}: ${metric.explanation}`);
7860
+ }
7861
+ lines.push("");
7862
+ lines.push("## Work Graph Trails");
7863
+ lines.push("");
7864
+ for (const trail of report.trails.slice(0, 12)) {
7865
+ lines.push(`- [${trail.kind}] ${trail.title} \u2014 ${trail.state}, ${trail.valence}, ${trail.shape} (${trail.evidence_refs.join(", ")})`);
7866
+ }
7867
+ lines.push("");
7868
+ lines.push("## Recurring Patterns");
7869
+ lines.push("");
7870
+ if (report.recurring_patterns.length === 0) {
7871
+ lines.push("- No recurring patterns detected yet.");
7872
+ } else {
7873
+ for (const pattern of report.recurring_patterns) {
7874
+ lines.push(`- [${pattern.severity}] ${pattern.title}: ${pattern.root_cause_hypothesis}`);
7875
+ }
7876
+ }
7877
+ lines.push("");
7315
7878
  lines.push("## Top Findings");
7316
7879
  lines.push("");
7317
7880
  for (const finding of report.findings.slice(0, 12)) {
@@ -7334,6 +7897,12 @@ function renderWorkGraphMarkdown(report) {
7334
7897
  lines.push(`- [${kickoff.priority}] ${kickoff.title}: ${kickoff.summary}`);
7335
7898
  }
7336
7899
  lines.push("");
7900
+ lines.push("## Eject Bay Recommendations");
7901
+ lines.push("");
7902
+ for (const recommendation of report.recommendations) {
7903
+ lines.push(`- [${recommendation.priority}] ${recommendation.title}: ${recommendation.summary}`);
7904
+ }
7905
+ lines.push("");
7337
7906
  lines.push("## Signup Hydration");
7338
7907
  lines.push("");
7339
7908
  lines.push(`- Strategy: ${report.signup_hydration.strategy}`);
@@ -7991,7 +8560,11 @@ async function runWorkGraphCommand(options, defaults = {}) {
7991
8560
  finalState: report.final_state,
7992
8561
  opportunityScore: report.opportunity_score,
7993
8562
  missedOrchestration: report.missed_orchestration_opportunities.length,
7994
- kickoffCount: report.initiative_kickoffs.length
8563
+ kickoffCount: report.initiative_kickoffs.length,
8564
+ trailCount: report.trails.length,
8565
+ recurringPatternCount: report.recurring_patterns.length,
8566
+ topTrail: report.mirror.primary_trail_id ?? null,
8567
+ mirrorHeadline: report.mirror.headline
7995
8568
  }, null, 2));
7996
8569
  return;
7997
8570
  }
@@ -8003,6 +8576,12 @@ async function runWorkGraphCommand(options, defaults = {}) {
8003
8576
  const missed = report.missed_orchestration_opportunities.length;
8004
8577
  const missedColor = missed > 0 ? pc3.yellow : pc3.green;
8005
8578
  console.log(` ${missed > 0 ? ICON.warn : ICON.ok} ${missedColor("missed ")} ${pc3.dim(`${missed} orchestration opportunit${missed === 1 ? "y" : "ies"}`)}`);
8579
+ console.log(` ${ICON.ok} ${pc3.green("trails ")} ${pc3.dim(`${report.trails.length} trail${report.trails.length === 1 ? "" : "s"} \xB7 ${report.recurring_patterns.length} recurring pattern${report.recurring_patterns.length === 1 ? "" : "s"}`)}`);
8580
+ console.log(` ${ICON.skip} ${pc3.bold("mirror ")} ${report.mirror.headline}`);
8581
+ for (const metric of report.tension_metrics.slice(0, 4)) {
8582
+ const tone = metric.tone === "danger" ? pc3.red : metric.tone === "warning" ? pc3.yellow : metric.tone === "good" ? pc3.green : pc3.dim;
8583
+ console.log(` ${ICON.skip} ${tone(`${metric.value} ${metric.label}`)} ${pc3.dim(metric.explanation)}`);
8584
+ }
8006
8585
  for (const kickoff of report.initiative_kickoffs) {
8007
8586
  console.log(` ${ICON.skip} ${pc3.bold(kickoff.priority.padEnd(3))} ${kickoff.title}`);
8008
8587
  }
@@ -8965,7 +9544,7 @@ function printDoctorReport(report, assessment) {
8965
9544
  async function main() {
8966
9545
  const program = new Command();
8967
9546
  program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
8968
- const pkgVersion = true ? "0.1.27" : void 0;
9547
+ const pkgVersion = true ? "0.1.28" : void 0;
8969
9548
  program.version(pkgVersion ?? "unknown", "-V, --version");
8970
9549
  program.hook("preAction", () => {
8971
9550
  console.log(renderBanner(pkgVersion));
@@ -9672,6 +10251,13 @@ async function main() {
9672
10251
  });
9673
10252
  await runWorkGraphCommand(options);
9674
10253
  });
10254
+ workGraph.command("profile").description("Build a local OrgX Profile with Work Graph Trails, Mirror, tensions, and launch recommendations.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--from <sources>", "auto-import recent local AI sessions: codex, claude, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "5").option("--session-days <days>", "lookback window for local AI-session imports", "30").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only profiles").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--json", "emit a JSON command summary").action(async (options) => {
10255
+ await safeTrackWizardTelemetry("work_graph_profile_started", {
10256
+ command: "work-graph profile",
10257
+ from: options.from ?? "manual"
10258
+ });
10259
+ await runWorkGraphCommand(options);
10260
+ });
9675
10261
  const sessions = program.command("sessions").description("Inspect and reconcile local AI sessions into OrgX-ready Work Graph reports.");
9676
10262
  sessions.command("reconcile").description("Backfill recent Codex and Claude sessions into a redacted Work Graph report.").option("--from <sources>", "auto-import recent local AI sessions: codex, claude, or all", "all").option("--session-limit <count>", "max recent sessions to import per selected source", "5").option("--session-days <days>", "lookback window for local AI-session imports", "7").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only reconciliation").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--json", "emit a JSON command summary").action(async (options) => {
9677
10263
  await safeTrackWizardTelemetry("sessions_reconcile_started", {