prjct-cli 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9166,10 +9166,52 @@ var init_agents = __esm({
9166
9166
  });
9167
9167
 
9168
9168
  // core/schemas/analysis.ts
9169
- var DEFAULT_ANALYSIS;
9169
+ import { z as z4 } from "zod";
9170
+ var AnalysisStatusSchema, CodePatternSchema, AntiPatternSchema, AnalysisItemSchema, DEFAULT_ANALYSIS;
9170
9171
  var init_analysis = __esm({
9171
9172
  "core/schemas/analysis.ts"() {
9172
9173
  "use strict";
9174
+ init_model();
9175
+ AnalysisStatusSchema = z4.enum(["draft", "verified", "sealed"]);
9176
+ CodePatternSchema = z4.object({
9177
+ name: z4.string(),
9178
+ description: z4.string(),
9179
+ location: z4.string().optional()
9180
+ });
9181
+ AntiPatternSchema = z4.object({
9182
+ issue: z4.string(),
9183
+ file: z4.string(),
9184
+ suggestion: z4.string()
9185
+ });
9186
+ AnalysisItemSchema = z4.object({
9187
+ projectId: z4.string(),
9188
+ languages: z4.array(z4.string()),
9189
+ frameworks: z4.array(z4.string()),
9190
+ packageManager: z4.string().optional(),
9191
+ sourceDir: z4.string().optional(),
9192
+ testDir: z4.string().optional(),
9193
+ configFiles: z4.array(z4.string()),
9194
+ fileCount: z4.number(),
9195
+ patterns: z4.array(CodePatternSchema),
9196
+ antiPatterns: z4.array(AntiPatternSchema),
9197
+ analyzedAt: z4.string(),
9198
+ // ISO8601
9199
+ /** Which AI model was used for this analysis (PRJ-265) */
9200
+ modelMetadata: ModelMetadataSchema.optional(),
9201
+ // Sealable analysis fields (PRJ-263)
9202
+ /** Lifecycle status: draft (regenerable), verified (confirmed correct), sealed (locked) */
9203
+ status: AnalysisStatusSchema.default("draft"),
9204
+ /** Git commit hash at the time of analysis */
9205
+ commitHash: z4.string().optional(),
9206
+ /** SHA-256 signature of analysis content + commit hash */
9207
+ signature: z4.string().optional(),
9208
+ /** When the analysis was sealed */
9209
+ sealedAt: z4.string().optional(),
9210
+ // ISO8601
9211
+ /** When the analysis was verified */
9212
+ verifiedAt: z4.string().optional()
9213
+ // ISO8601
9214
+ });
9173
9215
  DEFAULT_ANALYSIS = {
9174
9216
  languages: [],
9175
9217
  frameworks: [],
@@ -9177,18 +9219,19 @@ var init_analysis = __esm({
9177
9219
  fileCount: 0,
9178
9220
  patterns: [],
9179
9221
  antiPatterns: [],
9180
- analyzedAt: (/* @__PURE__ */ new Date()).toISOString()
9222
+ analyzedAt: (/* @__PURE__ */ new Date()).toISOString(),
9223
+ status: "draft"
9181
9224
  };
9182
9225
  }
9183
9226
  });
9184
9227
 
9185
9228
  // core/schemas/classification.ts
9186
- import { z as z4 } from "zod";
9229
+ import { z as z5 } from "zod";
9187
9230
  var ClassificationDomainSchema, TaskClassificationSchema, ClassificationCacheEntrySchema, ClassificationCacheSchema, DEFAULT_CLASSIFICATION_CACHE, GENERAL_CLASSIFICATION;
9188
9231
  var init_classification = __esm({
9189
9232
  "core/schemas/classification.ts"() {
9190
9233
  "use strict";
9191
- ClassificationDomainSchema = z4.enum([
9234
+ ClassificationDomainSchema = z5.enum([
9192
9235
  "frontend",
9193
9236
  "backend",
9194
9237
  "database",
@@ -9198,40 +9241,40 @@ var init_classification = __esm({
9198
9241
  "uxui",
9199
9242
  "general"
9200
9243
  ]);
9201
- TaskClassificationSchema = z4.object({
9244
+ TaskClassificationSchema = z5.object({
9202
9245
  /** Primary domain for this task */
9203
9246
  primaryDomain: ClassificationDomainSchema,
9204
9247
  /** Secondary domains that are also relevant */
9205
- secondaryDomains: z4.array(ClassificationDomainSchema),
9248
+ secondaryDomains: z5.array(ClassificationDomainSchema),
9206
9249
  /** Confidence in the classification (0-1) */
9207
- confidence: z4.number().min(0).max(1),
9250
+ confidence: z5.number().min(0).max(1),
9208
9251
  /** Glob patterns for relevant files */
9209
- filePatterns: z4.array(z4.string()),
9252
+ filePatterns: z5.array(z5.string()),
9210
9253
  /** Agent names that should handle this task */
9211
- relevantAgents: z4.array(z4.string())
9254
+ relevantAgents: z5.array(z5.string())
9212
9255
  });
9213
- ClassificationCacheEntrySchema = z4.object({
9256
+ ClassificationCacheEntrySchema = z5.object({
9214
9257
  /** The classification result */
9215
9258
  classification: TaskClassificationSchema,
9216
9259
  /** When this was classified */
9217
- classifiedAt: z4.string(),
9260
+ classifiedAt: z5.string(),
9218
9261
  /** How this was classified */
9219
- source: z4.enum(["cache", "history", "llm", "heuristic"]),
9262
+ source: z5.enum(["cache", "history", "llm", "heuristic"]),
9220
9263
  /** Hash of the task description for cache lookup */
9221
- descriptionHash: z4.string(),
9264
+ descriptionHash: z5.string(),
9222
9265
  /** Project ID this classification belongs to */
9223
- projectId: z4.string()
9266
+ projectId: z5.string()
9224
9267
  });
9225
- ClassificationCacheSchema = z4.object({
9268
+ ClassificationCacheSchema = z5.object({
9226
9269
  /** Cached classifications keyed by descriptionHash */
9227
- entries: z4.record(z4.string(), ClassificationCacheEntrySchema),
9270
+ entries: z5.record(z5.string(), ClassificationCacheEntrySchema),
9228
9271
  /** Confirmed patterns from successful task completions */
9229
- confirmedPatterns: z4.array(
9230
- z4.object({
9231
- descriptionHash: z4.string(),
9272
+ confirmedPatterns: z5.array(
9273
+ z5.object({
9274
+ descriptionHash: z5.string(),
9232
9275
  classification: TaskClassificationSchema,
9233
- confirmedAt: z4.string(),
9234
- taskDescription: z4.string()
9276
+ confirmedAt: z5.string(),
9277
+ taskDescription: z5.string()
9235
9278
  })
9236
9279
  )
9237
9280
  });
@@ -9250,74 +9293,74 @@ var init_classification = __esm({
9250
9293
  });
9251
9294
 
9252
9295
  // core/schemas/ideas.ts
9253
- import { z as z5 } from "zod";
9296
+ import { z as z6 } from "zod";
9254
9297
  var IdeaPrioritySchema, IdeaStatusSchema, ImpactLevelSchema, ImpactEffortSchema, TechStackSchema, IdeaModuleSchema, IdeaRoleSchema, IdeaItemSchema, IdeasJsonSchema, DEFAULT_IDEA;
9255
9298
  var init_ideas = __esm({
9256
9299
  "core/schemas/ideas.ts"() {
9257
9300
  "use strict";
9258
- IdeaPrioritySchema = z5.enum(["low", "medium", "high"]);
9259
- IdeaStatusSchema = z5.enum(["pending", "converted", "completed", "archived"]);
9260
- ImpactLevelSchema = z5.enum(["high", "medium", "low"]);
9261
- ImpactEffortSchema = z5.object({
9301
+ IdeaPrioritySchema = z6.enum(["low", "medium", "high"]);
9302
+ IdeaStatusSchema = z6.enum(["pending", "converted", "completed", "archived"]);
9303
+ ImpactLevelSchema = z6.enum(["high", "medium", "low"]);
9304
+ ImpactEffortSchema = z6.object({
9262
9305
  impact: ImpactLevelSchema,
9263
9306
  effort: ImpactLevelSchema
9264
9307
  });
9265
- TechStackSchema = z5.object({
9266
- frontend: z5.string().optional(),
9308
+ TechStackSchema = z6.object({
9309
+ frontend: z6.string().optional(),
9267
9310
  // "Next.js 14, HeroUI"
9268
- backend: z5.string().optional(),
9311
+ backend: z6.string().optional(),
9269
9312
  // "Supabase (Auth, DB, RLS, Realtime)"
9270
- payments: z5.string().optional(),
9313
+ payments: z6.string().optional(),
9271
9314
  // "Stripe Billing"
9272
- ai: z5.string().optional(),
9315
+ ai: z6.string().optional(),
9273
9316
  // "Vercel AI SDK"
9274
- deploy: z5.string().optional(),
9317
+ deploy: z6.string().optional(),
9275
9318
  // "Vercel"
9276
- other: z5.array(z5.string()).optional()
9319
+ other: z6.array(z6.string()).optional()
9277
9320
  });
9278
- IdeaModuleSchema = z5.object({
9279
- name: z5.string(),
9321
+ IdeaModuleSchema = z6.object({
9322
+ name: z6.string(),
9280
9323
  // "Multi-tenant"
9281
- description: z5.string()
9324
+ description: z6.string()
9282
9325
  // "Strict RLS for organizations"
9283
9326
  });
9284
- IdeaRoleSchema = z5.object({
9285
- name: z5.string(),
9327
+ IdeaRoleSchema = z6.object({
9328
+ name: z6.string(),
9286
9329
  // "SUPER_ADMIN"
9287
- description: z5.string().optional()
9330
+ description: z6.string().optional()
9288
9331
  });
9289
- IdeaItemSchema = z5.object({
9290
- id: z5.string(),
9332
+ IdeaItemSchema = z6.object({
9333
+ id: z6.string(),
9291
9334
  // idea_xxxxxxxx
9292
- text: z5.string(),
9335
+ text: z6.string(),
9293
9336
  // Title/summary
9294
- details: z5.string().optional(),
9337
+ details: z6.string().optional(),
9295
9338
  priority: IdeaPrioritySchema,
9296
9339
  status: IdeaStatusSchema,
9297
- tags: z5.array(z5.string()),
9298
- addedAt: z5.string(),
9340
+ tags: z6.array(z6.string()),
9341
+ addedAt: z6.string(),
9299
9342
  // ISO8601
9300
- completedAt: z5.string().optional(),
9301
- convertedTo: z5.string().optional(),
9343
+ completedAt: z6.string().optional(),
9344
+ convertedTo: z6.string().optional(),
9302
9345
  // Source documentation
9303
- source: z5.string().optional(),
9304
- sourceFiles: z5.array(z5.string()).optional(),
9346
+ source: z6.string().optional(),
9347
+ sourceFiles: z6.array(z6.string()).optional(),
9305
9348
  // Enriched fields from MD
9306
- painPoints: z5.array(z5.string()).optional(),
9307
- solutions: z5.array(z5.string()).optional(),
9308
- filesAffected: z5.array(z5.string()).optional(),
9349
+ painPoints: z6.array(z6.string()).optional(),
9350
+ solutions: z6.array(z6.string()).optional(),
9351
+ filesAffected: z6.array(z6.string()).optional(),
9309
9352
  impactEffort: ImpactEffortSchema.optional(),
9310
- implementationNotes: z5.string().optional(),
9353
+ implementationNotes: z6.string().optional(),
9311
9354
  // Technical spec fields for ZERO DATA LOSS
9312
9355
  stack: TechStackSchema.optional(),
9313
- modules: z5.array(IdeaModuleSchema).optional(),
9314
- roles: z5.array(IdeaRoleSchema).optional(),
9315
- risks: z5.array(z5.string()).optional(),
9316
- risksCount: z5.number().optional()
9356
+ modules: z6.array(IdeaModuleSchema).optional(),
9357
+ roles: z6.array(IdeaRoleSchema).optional(),
9358
+ risks: z6.array(z6.string()).optional(),
9359
+ risksCount: z6.number().optional()
9317
9360
  });
9318
- IdeasJsonSchema = z5.object({
9319
- ideas: z5.array(IdeaItemSchema),
9320
- lastUpdated: z5.string()
9361
+ IdeasJsonSchema = z6.object({
9362
+ ideas: z6.array(IdeaItemSchema),
9363
+ lastUpdated: z6.string()
9321
9364
  });
9322
9365
  DEFAULT_IDEA = {
9323
9366
  priority: "medium",
@@ -9329,7 +9372,7 @@ var init_ideas = __esm({
9329
9372
  });
9330
9373
 
9331
9374
  // core/schemas/issues.ts
9332
- import { z as z6 } from "zod";
9375
+ import { z as z7 } from "zod";
9333
9376
  function createEmptyIssues(provider) {
9334
9377
  return {
9335
9378
  provider,
@@ -9342,8 +9385,8 @@ var IssueProviderSchema, IssueStatusSchema, IssuePrioritySchema, IssueTypeSchema
9342
9385
  var init_issues = __esm({
9343
9386
  "core/schemas/issues.ts"() {
9344
9387
  "use strict";
9345
- IssueProviderSchema = z6.enum(["linear", "jira", "github", "monday", "asana", "none"]);
9346
- IssueStatusSchema = z6.enum([
9388
+ IssueProviderSchema = z7.enum(["linear", "jira", "github", "monday", "asana", "none"]);
9389
+ IssueStatusSchema = z7.enum([
9347
9390
  "backlog",
9348
9391
  "todo",
9349
9392
  "in_progress",
@@ -9351,68 +9394,68 @@ var init_issues = __esm({
9351
9394
  "done",
9352
9395
  "cancelled"
9353
9396
  ]);
9354
- IssuePrioritySchema = z6.enum(["none", "urgent", "high", "medium", "low"]);
9355
- IssueTypeSchema = z6.enum(["feature", "bug", "improvement", "task", "chore", "epic"]);
9356
- CachedIssueSchema = z6.object({
9397
+ IssuePrioritySchema = z7.enum(["none", "urgent", "high", "medium", "low"]);
9398
+ IssueTypeSchema = z7.enum(["feature", "bug", "improvement", "task", "chore", "epic"]);
9399
+ CachedIssueSchema = z7.object({
9357
9400
  // Core identifiers
9358
- id: z6.string(),
9401
+ id: z7.string(),
9359
9402
  // Provider UUID
9360
- identifier: z6.string(),
9403
+ identifier: z7.string(),
9361
9404
  // Human-readable ID (e.g., "PRJ-123")
9362
9405
  // Issue content
9363
- title: z6.string(),
9364
- description: z6.string().optional(),
9406
+ title: z7.string(),
9407
+ description: z7.string().optional(),
9365
9408
  // State
9366
9409
  status: IssueStatusSchema,
9367
9410
  priority: IssuePrioritySchema,
9368
9411
  type: IssueTypeSchema.optional(),
9369
9412
  // Metadata
9370
- assignee: z6.object({
9371
- id: z6.string(),
9372
- name: z6.string(),
9373
- email: z6.string().optional()
9413
+ assignee: z7.object({
9414
+ id: z7.string(),
9415
+ name: z7.string(),
9416
+ email: z7.string().optional()
9374
9417
  }).optional(),
9375
- labels: z6.array(z6.string()).default([]),
9376
- team: z6.object({
9377
- id: z6.string(),
9378
- name: z6.string(),
9379
- key: z6.string().optional()
9418
+ labels: z7.array(z7.string()).default([]),
9419
+ team: z7.object({
9420
+ id: z7.string(),
9421
+ name: z7.string(),
9422
+ key: z7.string().optional()
9380
9423
  }).optional(),
9381
- project: z6.object({
9382
- id: z6.string(),
9383
- name: z6.string()
9424
+ project: z7.object({
9425
+ id: z7.string(),
9426
+ name: z7.string()
9384
9427
  }).optional(),
9385
9428
  // URLs and timestamps
9386
- url: z6.string(),
9387
- createdAt: z6.string(),
9429
+ url: z7.string(),
9430
+ createdAt: z7.string(),
9388
9431
  // ISO8601 from provider
9389
- updatedAt: z6.string(),
9432
+ updatedAt: z7.string(),
9390
9433
  // ISO8601 from provider
9391
- fetchedAt: z6.string()
9434
+ fetchedAt: z7.string()
9392
9435
  // ISO8601 when we cached it
9393
9436
  });
9394
- IssuesJsonSchema = z6.object({
9437
+ IssuesJsonSchema = z7.object({
9395
9438
  // Provider info
9396
9439
  provider: IssueProviderSchema,
9397
9440
  // Sync metadata
9398
- lastSync: z6.string(),
9441
+ lastSync: z7.string(),
9399
9442
  // ISO8601 of last full sync
9400
- staleAfter: z6.number().default(18e5),
9443
+ staleAfter: z7.number().default(18e5),
9401
9444
  // 30 minutes in ms
9402
9445
  // Issues map: identifier -> issue
9403
- issues: z6.record(z6.string(), CachedIssueSchema)
9446
+ issues: z7.record(z7.string(), CachedIssueSchema)
9404
9447
  });
9405
- SyncResultSchema = z6.object({
9448
+ SyncResultSchema = z7.object({
9406
9449
  provider: IssueProviderSchema,
9407
- fetched: z6.number(),
9408
- updated: z6.number(),
9409
- errors: z6.array(
9410
- z6.object({
9411
- issueId: z6.string(),
9412
- error: z6.string()
9450
+ fetched: z7.number(),
9451
+ updated: z7.number(),
9452
+ errors: z7.array(
9453
+ z7.object({
9454
+ issueId: z7.string(),
9455
+ error: z7.string()
9413
9456
  })
9414
9457
  ),
9415
- timestamp: z6.string()
9458
+ timestamp: z7.string()
9416
9459
  });
9417
9460
  parseIssues = /* @__PURE__ */ __name((data) => IssuesJsonSchema.parse(data), "parseIssues");
9418
9461
  __name(createEmptyIssues, "createEmptyIssues");
@@ -9428,7 +9471,7 @@ __export(llm_output_exports, {
9428
9471
  TaskClassificationSchema: () => TaskClassificationSchema,
9429
9472
  renderSchemaForPrompt: () => renderSchemaForPrompt
9430
9473
  });
9431
- import { z as z7 } from "zod";
9474
+ import { z as z8 } from "zod";
9432
9475
  function renderSchemaForPrompt(schemaType) {
9433
9476
  const entry = OUTPUT_SCHEMAS[schemaType];
9434
9477
  if (!entry) return null;
@@ -9444,18 +9487,18 @@ Fields:
9444
9487
  ${describeSchema(entry.schema)}`;
9445
9488
  }
9446
9489
  function describeSchema(schema) {
9447
- if (schema instanceof z7.ZodObject) {
9490
+ if (schema instanceof z8.ZodObject) {
9448
9491
  const shape = schema.shape;
9449
9492
  return Object.entries(shape).map(([key, field]) => `- \`${key}\`: ${describeField(field)}`).join("\n");
9450
9493
  }
9451
9494
  return "(see example above)";
9452
9495
  }
9453
9496
  function describeField(field) {
9454
- if (field instanceof z7.ZodString) return "string";
9455
- if (field instanceof z7.ZodNumber) return "number";
9456
- if (field instanceof z7.ZodEnum) return `one of: ${field.options.join(", ")}`;
9457
- if (field instanceof z7.ZodArray) return `array of ${describeField(field.element)}`;
9458
- if (field instanceof z7.ZodObject) return "object";
9497
+ if (field instanceof z8.ZodString) return "string";
9498
+ if (field instanceof z8.ZodNumber) return "number";
9499
+ if (field instanceof z8.ZodEnum) return `one of: ${field.options.join(", ")}`;
9500
+ if (field instanceof z8.ZodArray) return `array of ${describeField(field.element)}`;
9501
+ if (field instanceof z8.ZodObject) return "object";
9459
9502
  return "any";
9460
9503
  }
9461
9504
  var AgentAssignmentSchema, SubtaskBreakdownSchema, OUTPUT_SCHEMAS;
@@ -9464,30 +9507,30 @@ var init_llm_output = __esm({
9464
9507
  "use strict";
9465
9508
  init_classification();
9466
9509
  init_classification();
9467
- AgentAssignmentSchema = z7.object({
9510
+ AgentAssignmentSchema = z8.object({
9468
9511
  /** Agent file name (e.g., "backend.md", "frontend.md") */
9469
- agentName: z7.string(),
9512
+ agentName: z8.string(),
9470
9513
  /** Why this agent was selected */
9471
- reasoning: z7.string(),
9514
+ reasoning: z8.string(),
9472
9515
  /** Confidence in the assignment (0-1) */
9473
- confidence: z7.number().min(0).max(1)
9516
+ confidence: z8.number().min(0).max(1)
9474
9517
  });
9475
- SubtaskBreakdownSchema = z7.object({
9518
+ SubtaskBreakdownSchema = z8.object({
9476
9519
  /** Subtasks in execution order */
9477
- subtasks: z7.array(
9478
- z7.object({
9520
+ subtasks: z8.array(
9521
+ z8.object({
9479
9522
  /** Short description of the subtask */
9480
- description: z7.string(),
9523
+ description: z8.string(),
9481
9524
  /** Domain this subtask belongs to */
9482
9525
  domain: ClassificationDomainSchema,
9483
9526
  /** Suggested agent for this subtask */
9484
- agent: z7.string(),
9527
+ agent: z8.string(),
9485
9528
  /** IDs of subtasks this depends on (by index, 0-based) */
9486
- dependsOn: z7.array(z7.number())
9529
+ dependsOn: z8.array(z8.number())
9487
9530
  })
9488
9531
  ),
9489
9532
  /** Estimated total effort */
9490
- effort: z7.enum(["low", "medium", "high"])
9533
+ effort: z8.enum(["low", "medium", "high"])
9491
9534
  });
9492
9535
  OUTPUT_SCHEMAS = {
9493
9536
  classification: {
@@ -9548,15 +9591,15 @@ var init_llm_output = __esm({
9548
9591
  });
9549
9592
 
9550
9593
  // core/schemas/outcomes.ts
9551
- import { z as z8 } from "zod";
9594
+ import { z as z9 } from "zod";
9552
9595
  var QualityScoreSchema, SuccessLevelSchema, WorthAssessmentSchema, VarianceReasonSchema, EffortComparisonSchema, MetricResultSchema, AcceptanceCriteriaResultSchema, SuccessTrackingSchema, LearningSchema, LearningsSchema, ROIAssessmentSchema, TaskOutcomeSchema, FeatureOutcomeSchema, AggregateMetricsSchema, OutcomesJsonSchema;
9553
9596
  var init_outcomes = __esm({
9554
9597
  "core/schemas/outcomes.ts"() {
9555
9598
  "use strict";
9556
- QualityScoreSchema = z8.number().min(1).max(5);
9557
- SuccessLevelSchema = z8.enum(["exceeded", "met", "partial", "failed"]);
9558
- WorthAssessmentSchema = z8.enum(["definitely", "probably", "maybe", "no"]);
9559
- VarianceReasonSchema = z8.enum([
9599
+ QualityScoreSchema = z9.number().min(1).max(5);
9600
+ SuccessLevelSchema = z9.enum(["exceeded", "met", "partial", "failed"]);
9601
+ WorthAssessmentSchema = z9.enum(["definitely", "probably", "maybe", "no"]);
9602
+ VarianceReasonSchema = z9.enum([
9560
9603
  "scope_creep",
9561
9604
  "underestimated_complexity",
9562
9605
  "technical_debt",
@@ -9567,54 +9610,54 @@ var init_outcomes = __esm({
9567
9610
  "team_changes",
9568
9611
  "other"
9569
9612
  ]);
9570
- EffortComparisonSchema = z8.object({
9571
- estimated: z8.object({
9572
- hours: z8.number(),
9573
- confidence: z8.enum(["low", "medium", "high"]).optional(),
9574
- source: z8.enum(["prd", "manual", "historical"]).optional()
9613
+ EffortComparisonSchema = z9.object({
9614
+ estimated: z9.object({
9615
+ hours: z9.number(),
9616
+ confidence: z9.enum(["low", "medium", "high"]).optional(),
9617
+ source: z9.enum(["prd", "manual", "historical"]).optional()
9575
9618
  }),
9576
- actual: z8.object({
9577
- hours: z8.number(),
9578
- commits: z8.number().optional(),
9579
- linesAdded: z8.number().optional(),
9580
- linesRemoved: z8.number().optional(),
9581
- sessions: z8.number().optional()
9619
+ actual: z9.object({
9620
+ hours: z9.number(),
9621
+ commits: z9.number().optional(),
9622
+ linesAdded: z9.number().optional(),
9623
+ linesRemoved: z9.number().optional(),
9624
+ sessions: z9.number().optional()
9582
9625
  // Number of work sessions
9583
9626
  }),
9584
- variance: z8.object({
9585
- hours: z8.number(),
9627
+ variance: z9.object({
9628
+ hours: z9.number(),
9586
9629
  // actual - estimated
9587
- percentage: z8.number(),
9630
+ percentage: z9.number(),
9588
9631
  // ((actual - estimated) / estimated) * 100
9589
9632
  reason: VarianceReasonSchema.optional(),
9590
- explanation: z8.string().optional()
9633
+ explanation: z9.string().optional()
9591
9634
  })
9592
9635
  });
9593
- MetricResultSchema = z8.object({
9594
- name: z8.string(),
9595
- baseline: z8.number().nullable(),
9596
- target: z8.number(),
9597
- actual: z8.number(),
9598
- unit: z8.string(),
9599
- achieved: z8.boolean(),
9636
+ MetricResultSchema = z9.object({
9637
+ name: z9.string(),
9638
+ baseline: z9.number().nullable(),
9639
+ target: z9.number(),
9640
+ actual: z9.number(),
9641
+ unit: z9.string(),
9642
+ achieved: z9.boolean(),
9600
9643
  // actual >= target (or <= for decrease metrics)
9601
- percentOfTarget: z8.number()
9644
+ percentOfTarget: z9.number()
9602
9645
  // (actual / target) * 100
9603
9646
  });
9604
- AcceptanceCriteriaResultSchema = z8.object({
9605
- criteria: z8.string(),
9606
- met: z8.boolean(),
9607
- notes: z8.string().optional()
9647
+ AcceptanceCriteriaResultSchema = z9.object({
9648
+ criteria: z9.string(),
9649
+ met: z9.boolean(),
9650
+ notes: z9.string().optional()
9608
9651
  });
9609
- SuccessTrackingSchema = z8.object({
9610
- metrics: z8.array(MetricResultSchema),
9611
- acceptanceCriteria: z8.array(AcceptanceCriteriaResultSchema),
9652
+ SuccessTrackingSchema = z9.object({
9653
+ metrics: z9.array(MetricResultSchema),
9654
+ acceptanceCriteria: z9.array(AcceptanceCriteriaResultSchema),
9612
9655
  overallSuccess: SuccessLevelSchema,
9613
- successScore: z8.number().min(0).max(100)
9656
+ successScore: z9.number().min(0).max(100)
9614
9657
  // Percentage of metrics/criteria met
9615
9658
  });
9616
- LearningSchema = z8.object({
9617
- category: z8.enum([
9659
+ LearningSchema = z9.object({
9660
+ category: z9.enum([
9618
9661
  "estimation",
9619
9662
  "technical",
9620
9663
  "process",
@@ -9624,62 +9667,62 @@ var init_outcomes = __esm({
9624
9667
  "testing",
9625
9668
  "other"
9626
9669
  ]),
9627
- insight: z8.string(),
9628
- actionable: z8.boolean(),
9629
- action: z8.string().optional()
9670
+ insight: z9.string(),
9671
+ actionable: z9.boolean(),
9672
+ action: z9.string().optional()
9630
9673
  // What to do differently next time
9631
9674
  });
9632
- LearningsSchema = z8.object({
9633
- whatWorked: z8.array(z8.string()),
9634
- whatDidnt: z8.array(z8.string()),
9635
- surprises: z8.array(z8.string()),
9636
- recommendations: z8.array(LearningSchema)
9675
+ LearningsSchema = z9.object({
9676
+ whatWorked: z9.array(z9.string()),
9677
+ whatDidnt: z9.array(z9.string()),
9678
+ surprises: z9.array(z9.string()),
9679
+ recommendations: z9.array(LearningSchema)
9637
9680
  });
9638
- ROIAssessmentSchema = z8.object({
9639
- valueDelivered: z8.number().min(1).max(10),
9681
+ ROIAssessmentSchema = z9.object({
9682
+ valueDelivered: z9.number().min(1).max(10),
9640
9683
  // Subjective 1-10 score
9641
- userImpact: z8.enum(["none", "low", "medium", "high", "critical"]),
9642
- businessImpact: z8.enum(["none", "low", "medium", "high", "critical"]),
9684
+ userImpact: z9.enum(["none", "low", "medium", "high", "critical"]),
9685
+ businessImpact: z9.enum(["none", "low", "medium", "high", "critical"]),
9643
9686
  // Calculated: (valueDelivered * 10) / (actual hours)
9644
- roiScore: z8.number(),
9687
+ roiScore: z9.number(),
9645
9688
  // Would you build this again knowing what you know now?
9646
9689
  worthIt: WorthAssessmentSchema,
9647
- worthItReason: z8.string().optional(),
9690
+ worthItReason: z9.string().optional(),
9648
9691
  // Comparison to alternatives
9649
- alternativeConsidered: z8.string().optional(),
9650
- betterAlternativeExists: z8.boolean().optional()
9692
+ alternativeConsidered: z9.string().optional(),
9693
+ betterAlternativeExists: z9.boolean().optional()
9651
9694
  });
9652
- TaskOutcomeSchema = z8.object({
9653
- id: z8.string(),
9695
+ TaskOutcomeSchema = z9.object({
9696
+ id: z9.string(),
9654
9697
  // out_task_xxxxxxxx
9655
- taskId: z8.string(),
9656
- description: z8.string(),
9698
+ taskId: z9.string(),
9699
+ description: z9.string(),
9657
9700
  // Time tracking
9658
- estimatedMinutes: z8.number().optional(),
9659
- actualMinutes: z8.number(),
9701
+ estimatedMinutes: z9.number().optional(),
9702
+ actualMinutes: z9.number(),
9660
9703
  // Quality
9661
- completedAsPlanned: z8.boolean(),
9704
+ completedAsPlanned: z9.boolean(),
9662
9705
  qualityScore: QualityScoreSchema,
9663
9706
  // Context
9664
- blockers: z8.array(z8.string()),
9665
- agentUsed: z8.string().optional(),
9666
- skillsUsed: z8.array(z8.string()).optional(),
9707
+ blockers: z9.array(z9.string()),
9708
+ agentUsed: z9.string().optional(),
9709
+ skillsUsed: z9.array(z9.string()).optional(),
9667
9710
  // Timestamps
9668
- startedAt: z8.string(),
9669
- completedAt: z8.string()
9711
+ startedAt: z9.string(),
9712
+ completedAt: z9.string()
9670
9713
  });
9671
- FeatureOutcomeSchema = z8.object({
9672
- id: z8.string(),
9714
+ FeatureOutcomeSchema = z9.object({
9715
+ id: z9.string(),
9673
9716
  // out_feat_xxxxxxxx
9674
9717
  // Links
9675
- featureId: z8.string(),
9676
- featureName: z8.string(),
9677
- prdId: z8.string().nullable(),
9718
+ featureId: z9.string(),
9719
+ featureName: z9.string(),
9720
+ prdId: z9.string().nullable(),
9678
9721
  // null for legacy features
9679
9722
  // Version info
9680
- version: z8.string().optional(),
9681
- branch: z8.string().optional(),
9682
- prUrl: z8.string().optional(),
9723
+ version: z9.string().optional(),
9724
+ branch: z9.string().optional(),
9725
+ prUrl: z9.string().optional(),
9683
9726
  // Effort
9684
9727
  effort: EffortComparisonSchema,
9685
9728
  // Success (only if PRD exists)
@@ -9691,61 +9734,61 @@ var init_outcomes = __esm({
9691
9734
  // Overall rating
9692
9735
  rating: QualityScoreSchema,
9693
9736
  // Task outcomes (sub-tasks)
9694
- taskOutcomes: z8.array(TaskOutcomeSchema).optional(),
9737
+ taskOutcomes: z9.array(TaskOutcomeSchema).optional(),
9695
9738
  // Timestamps
9696
- startedAt: z8.string(),
9697
- shippedAt: z8.string(),
9698
- reviewedAt: z8.string().optional(),
9739
+ startedAt: z9.string(),
9740
+ shippedAt: z9.string(),
9741
+ reviewedAt: z9.string().optional(),
9699
9742
  // When impact was captured
9700
9743
  // Metadata
9701
- reviewedBy: z8.string().optional(),
9744
+ reviewedBy: z9.string().optional(),
9702
9745
  // Who filled out the impact review
9703
- legacy: z8.boolean().optional()
9746
+ legacy: z9.boolean().optional()
9704
9747
  // Legacy feature (no PRD)
9705
9748
  });
9706
- AggregateMetricsSchema = z8.object({
9707
- totalFeatures: z8.number(),
9708
- averageEstimationAccuracy: z8.number(),
9749
+ AggregateMetricsSchema = z9.object({
9750
+ totalFeatures: z9.number(),
9751
+ averageEstimationAccuracy: z9.number(),
9709
9752
  // Percentage
9710
- averageSuccessRate: z8.number(),
9753
+ averageSuccessRate: z9.number(),
9711
9754
  // Percentage
9712
- averageROI: z8.number(),
9755
+ averageROI: z9.number(),
9713
9756
  // By category
9714
- bySuccessLevel: z8.object({
9715
- exceeded: z8.number(),
9716
- met: z8.number(),
9717
- partial: z8.number(),
9718
- failed: z8.number()
9757
+ bySuccessLevel: z9.object({
9758
+ exceeded: z9.number(),
9759
+ met: z9.number(),
9760
+ partial: z9.number(),
9761
+ failed: z9.number()
9719
9762
  }),
9720
9763
  // Variance patterns
9721
- variancePatterns: z8.array(
9722
- z8.object({
9764
+ variancePatterns: z9.array(
9765
+ z9.object({
9723
9766
  reason: VarianceReasonSchema,
9724
- count: z8.number(),
9725
- averageVariance: z8.number()
9767
+ count: z9.number(),
9768
+ averageVariance: z9.number()
9726
9769
  })
9727
9770
  ),
9728
9771
  // Top learnings (aggregated)
9729
- topLearnings: z8.array(
9730
- z8.object({
9731
- insight: z8.string(),
9732
- frequency: z8.number()
9772
+ topLearnings: z9.array(
9773
+ z9.object({
9774
+ insight: z9.string(),
9775
+ frequency: z9.number()
9733
9776
  })
9734
9777
  )
9735
9778
  });
9736
- OutcomesJsonSchema = z8.object({
9737
- outcomes: z8.array(FeatureOutcomeSchema),
9738
- taskOutcomes: z8.array(TaskOutcomeSchema).optional(),
9779
+ OutcomesJsonSchema = z9.object({
9780
+ outcomes: z9.array(FeatureOutcomeSchema),
9781
+ taskOutcomes: z9.array(TaskOutcomeSchema).optional(),
9739
9782
  // Standalone task outcomes
9740
9783
  aggregates: AggregateMetricsSchema.optional(),
9741
- lastUpdated: z8.string(),
9742
- lastAggregated: z8.string().optional()
9784
+ lastUpdated: z9.string(),
9785
+ lastAggregated: z9.string().optional()
9743
9786
  });
9744
9787
  }
9745
9788
  });
9746
9789
 
9747
9790
  // core/schemas/permissions.ts
9748
- import { z as z9 } from "zod";
9791
+ import { z as z10 } from "zod";
9749
9792
  function buildDefaultPermissions() {
9750
9793
  const bash = {};
9751
9794
  for (const pattern of DEFAULT_BASH_ALLOW) {
@@ -9778,20 +9821,20 @@ var PermissionLevelSchema, FileOperationSchema, BashPermissionSchema, FilePermis
9778
9821
  var init_permissions = __esm({
9779
9822
  "core/schemas/permissions.ts"() {
9780
9823
  "use strict";
9781
- PermissionLevelSchema = z9.enum(["allow", "deny", "ask"]);
9782
- FileOperationSchema = z9.enum(["read", "write", "delete", "create"]);
9783
- BashPermissionSchema = z9.record(z9.string(), PermissionLevelSchema);
9784
- FilePermissionSchema = z9.record(z9.string(), PermissionLevelSchema);
9785
- WebPermissionSchema = z9.object({
9786
- enabled: z9.boolean().default(true),
9787
- allowedDomains: z9.array(z9.string()).optional(),
9788
- blockedDomains: z9.array(z9.string()).optional()
9824
+ PermissionLevelSchema = z10.enum(["allow", "deny", "ask"]);
9825
+ FileOperationSchema = z10.enum(["read", "write", "delete", "create"]);
9826
+ BashPermissionSchema = z10.record(z10.string(), PermissionLevelSchema);
9827
+ FilePermissionSchema = z10.record(z10.string(), PermissionLevelSchema);
9828
+ WebPermissionSchema = z10.object({
9829
+ enabled: z10.boolean().default(true),
9830
+ allowedDomains: z10.array(z10.string()).optional(),
9831
+ blockedDomains: z10.array(z10.string()).optional()
9789
9832
  });
9790
- PermissionsConfigSchema = z9.object({
9833
+ PermissionsConfigSchema = z10.object({
9791
9834
  /** Bash command permissions - glob patterns */
9792
9835
  bash: BashPermissionSchema.optional(),
9793
9836
  /** File operation permissions - glob patterns */
9794
- files: z9.object({
9837
+ files: z10.object({
9795
9838
  read: FilePermissionSchema.optional(),
9796
9839
  write: FilePermissionSchema.optional(),
9797
9840
  delete: FilePermissionSchema.optional()
@@ -9799,11 +9842,11 @@ var init_permissions = __esm({
9799
9842
  /** Web fetch permissions */
9800
9843
  web: WebPermissionSchema.optional(),
9801
9844
  /** Skill invocation permissions */
9802
- skills: z9.record(z9.string(), PermissionLevelSchema).optional(),
9845
+ skills: z10.record(z10.string(), PermissionLevelSchema).optional(),
9803
9846
  /** Doom loop protection - prevent infinite retries */
9804
- doomLoop: z9.object({
9805
- enabled: z9.boolean().default(true),
9806
- maxRetries: z9.number().default(3)
9847
+ doomLoop: z10.object({
9848
+ enabled: z10.boolean().default(true),
9849
+ maxRetries: z10.number().default(3)
9807
9850
  }).optional(),
9808
9851
  /** External directory access */
9809
9852
  externalDirectories: PermissionLevelSchema.default("ask")
@@ -9856,30 +9899,30 @@ var init_permissions = __esm({
9856
9899
  });
9857
9900
 
9858
9901
  // core/schemas/project.ts
9859
- import { z as z10 } from "zod";
9902
+ import { z as z11 } from "zod";
9860
9903
  var ProjectItemSchema, DEFAULT_PROJECT;
9861
9904
  var init_project = __esm({
9862
9905
  "core/schemas/project.ts"() {
9863
9906
  "use strict";
9864
- ProjectItemSchema = z10.object({
9865
- projectId: z10.string(),
9866
- name: z10.string(),
9867
- repoPath: z10.string(),
9868
- description: z10.string().optional(),
9869
- version: z10.string().optional(),
9870
- cliVersion: z10.string().optional(),
9907
+ ProjectItemSchema = z11.object({
9908
+ projectId: z11.string(),
9909
+ name: z11.string(),
9910
+ repoPath: z11.string(),
9911
+ description: z11.string().optional(),
9912
+ version: z11.string().optional(),
9913
+ cliVersion: z11.string().optional(),
9871
9914
  // prjct-cli version used to sync
9872
- techStack: z10.array(z10.string()),
9873
- fileCount: z10.number(),
9874
- commitCount: z10.number(),
9875
- createdAt: z10.string(),
9915
+ techStack: z11.array(z11.string()),
9916
+ fileCount: z11.number(),
9917
+ commitCount: z11.number(),
9918
+ createdAt: z11.string(),
9876
9919
  // ISO8601
9877
- lastSync: z10.string(),
9920
+ lastSync: z11.string(),
9878
9921
  // ISO8601
9879
9922
  // Staleness tracking (PRJ-120)
9880
- lastSyncCommit: z10.string().optional(),
9923
+ lastSyncCommit: z11.string().optional(),
9881
9924
  // Git commit hash at last sync
9882
- lastSyncBranch: z10.string().optional()
9925
+ lastSyncBranch: z11.string().optional()
9883
9926
  // Git branch at last sync
9884
9927
  });
9885
9928
  DEFAULT_PROJECT = {
@@ -9893,181 +9936,181 @@ var init_project = __esm({
9893
9936
  });
9894
9937
 
9895
9938
  // core/schemas/roadmap.ts
9896
- import { z as z11 } from "zod";
9939
+ import { z as z12 } from "zod";
9897
9940
  var FeatureStatusSchema, FeatureImpactSchema, FeatureTypeSchema, PhaseStatusSchema, QuarterStatusSchema, InferredFromSchema, FeatureTaskSchema, RoadmapPhaseSchema, RoadmapStrategySchema, FeatureDurationSchema, GitCommitSchema, EffortEstimateSchema, EffortActualSchema, FeatureEffortSchema, QuarterCapacitySchema, QuarterSchema, FeatureItemSchema, BacklogItemSchema, RoadmapJsonSchema, DEFAULT_FEATURE;
9898
9941
  var init_roadmap = __esm({
9899
9942
  "core/schemas/roadmap.ts"() {
9900
9943
  "use strict";
9901
- FeatureStatusSchema = z11.enum(["planned", "active", "completed", "shipped"]);
9902
- FeatureImpactSchema = z11.enum(["low", "medium", "high"]);
9903
- FeatureTypeSchema = z11.enum([
9944
+ FeatureStatusSchema = z12.enum(["planned", "active", "completed", "shipped"]);
9945
+ FeatureImpactSchema = z12.enum(["low", "medium", "high"]);
9946
+ FeatureTypeSchema = z12.enum([
9904
9947
  "feature",
9905
9948
  "breaking_change",
9906
9949
  "refactor",
9907
9950
  "infrastructure"
9908
9951
  ]);
9909
- PhaseStatusSchema = z11.enum(["completed", "active", "planned"]);
9910
- QuarterStatusSchema = z11.enum(["planned", "active", "completed"]);
9911
- InferredFromSchema = z11.enum(["git", "git-branch", "manual", "prd"]);
9912
- FeatureTaskSchema = z11.object({
9913
- id: z11.string(),
9952
+ PhaseStatusSchema = z12.enum(["completed", "active", "planned"]);
9953
+ QuarterStatusSchema = z12.enum(["planned", "active", "completed"]);
9954
+ InferredFromSchema = z12.enum(["git", "git-branch", "manual", "prd"]);
9955
+ FeatureTaskSchema = z12.object({
9956
+ id: z12.string(),
9914
9957
  // task_xxxxxxxx
9915
- description: z11.string(),
9916
- completed: z11.boolean(),
9917
- completedAt: z11.string().optional()
9958
+ description: z12.string(),
9959
+ completed: z12.boolean(),
9960
+ completedAt: z12.string().optional()
9918
9961
  });
9919
- RoadmapPhaseSchema = z11.object({
9920
- id: z11.string(),
9962
+ RoadmapPhaseSchema = z12.object({
9963
+ id: z12.string(),
9921
9964
  // P0, P1, etc.
9922
- name: z11.string(),
9965
+ name: z12.string(),
9923
9966
  status: PhaseStatusSchema,
9924
- completedAt: z11.string().optional()
9967
+ completedAt: z12.string().optional()
9925
9968
  });
9926
- RoadmapStrategySchema = z11.object({
9927
- goal: z11.string(),
9928
- phases: z11.array(RoadmapPhaseSchema),
9929
- successMetrics: z11.array(z11.string()).optional()
9969
+ RoadmapStrategySchema = z12.object({
9970
+ goal: z12.string(),
9971
+ phases: z12.array(RoadmapPhaseSchema),
9972
+ successMetrics: z12.array(z12.string()).optional()
9930
9973
  });
9931
- FeatureDurationSchema = z11.object({
9932
- hours: z11.number(),
9933
- minutes: z11.number(),
9934
- totalMinutes: z11.number(),
9935
- display: z11.string().optional()
9974
+ FeatureDurationSchema = z12.object({
9975
+ hours: z12.number(),
9976
+ minutes: z12.number(),
9977
+ totalMinutes: z12.number(),
9978
+ display: z12.string().optional()
9936
9979
  });
9937
- GitCommitSchema = z11.object({
9938
- hash: z11.string(),
9939
- message: z11.string(),
9940
- date: z11.string(),
9941
- author: z11.string().optional()
9980
+ GitCommitSchema = z12.object({
9981
+ hash: z12.string(),
9982
+ message: z12.string(),
9983
+ date: z12.string(),
9984
+ author: z12.string().optional()
9942
9985
  });
9943
- EffortEstimateSchema = z11.object({
9944
- hours: z11.number(),
9945
- confidence: z11.enum(["low", "medium", "high"]).optional(),
9946
- breakdown: z11.array(
9947
- z11.object({
9948
- area: z11.string(),
9949
- hours: z11.number()
9986
+ EffortEstimateSchema = z12.object({
9987
+ hours: z12.number(),
9988
+ confidence: z12.enum(["low", "medium", "high"]).optional(),
9989
+ breakdown: z12.array(
9990
+ z12.object({
9991
+ area: z12.string(),
9992
+ hours: z12.number()
9950
9993
  })
9951
9994
  ).optional()
9952
9995
  });
9953
- EffortActualSchema = z11.object({
9954
- hours: z11.number().optional(),
9955
- commits: z11.number().optional(),
9956
- linesAdded: z11.number().optional(),
9957
- linesRemoved: z11.number().optional()
9996
+ EffortActualSchema = z12.object({
9997
+ hours: z12.number().optional(),
9998
+ commits: z12.number().optional(),
9999
+ linesAdded: z12.number().optional(),
10000
+ linesRemoved: z12.number().optional()
9958
10001
  });
9959
- FeatureEffortSchema = z11.object({
10002
+ FeatureEffortSchema = z12.object({
9960
10003
  estimated: EffortEstimateSchema.nullable(),
9961
10004
  actual: EffortActualSchema.nullable()
9962
10005
  });
9963
- QuarterCapacitySchema = z11.object({
9964
- totalHours: z11.number(),
9965
- allocatedHours: z11.number(),
9966
- bufferPercent: z11.number().optional()
10006
+ QuarterCapacitySchema = z12.object({
10007
+ totalHours: z12.number(),
10008
+ allocatedHours: z12.number(),
10009
+ bufferPercent: z12.number().optional()
9967
10010
  // % reserved for unknowns
9968
10011
  });
9969
- QuarterSchema = z11.object({
9970
- id: z11.string(),
10012
+ QuarterSchema = z12.object({
10013
+ id: z12.string(),
9971
10014
  // Q1-2026
9972
- name: z11.string(),
10015
+ name: z12.string(),
9973
10016
  // "Q1 2026"
9974
- theme: z11.string().optional(),
10017
+ theme: z12.string().optional(),
9975
10018
  // "Foundation"
9976
- goals: z11.array(z11.string()).optional(),
9977
- features: z11.array(z11.string()),
10019
+ goals: z12.array(z12.string()).optional(),
10020
+ features: z12.array(z12.string()),
9978
10021
  // Feature IDs
9979
10022
  capacity: QuarterCapacitySchema.optional(),
9980
10023
  status: QuarterStatusSchema,
9981
- startDate: z11.string().optional(),
10024
+ startDate: z12.string().optional(),
9982
10025
  // ISO8601
9983
- endDate: z11.string().optional()
10026
+ endDate: z12.string().optional()
9984
10027
  // ISO8601
9985
10028
  });
9986
- FeatureItemSchema = z11.object({
9987
- id: z11.string(),
10029
+ FeatureItemSchema = z12.object({
10030
+ id: z12.string(),
9988
10031
  // feat_xxxxxxxx
9989
- name: z11.string(),
9990
- description: z11.string().optional(),
9991
- date: z11.string(),
10032
+ name: z12.string(),
10033
+ description: z12.string().optional(),
10034
+ date: z12.string(),
9992
10035
  // YYYY-MM-DD creation date
9993
10036
  status: FeatureStatusSchema,
9994
10037
  impact: FeatureImpactSchema,
9995
- effort: z11.string().optional(),
9996
- progress: z11.number(),
10038
+ effort: z12.string().optional(),
10039
+ progress: z12.number(),
9997
10040
  // 0-100
9998
10041
  // Enriched fields from MD
9999
10042
  type: FeatureTypeSchema.optional(),
10000
- roi: z11.number().optional(),
10043
+ roi: z12.number().optional(),
10001
10044
  // 1-5 from star count
10002
- why: z11.array(z11.string()).optional(),
10003
- technicalNotes: z11.array(z11.string()).optional(),
10004
- compatibility: z11.string().optional(),
10005
- phase: z11.string().optional(),
10045
+ why: z12.array(z12.string()).optional(),
10046
+ technicalNotes: z12.array(z12.string()).optional(),
10047
+ compatibility: z12.string().optional(),
10048
+ phase: z12.string().optional(),
10006
10049
  // P0, P1, etc.
10007
- tasks: z11.array(FeatureTaskSchema),
10008
- createdAt: z11.string(),
10050
+ tasks: z12.array(FeatureTaskSchema),
10051
+ createdAt: z12.string(),
10009
10052
  // ISO8601
10010
- shippedAt: z11.string().optional(),
10011
- version: z11.string().optional(),
10053
+ shippedAt: z12.string().optional(),
10054
+ version: z12.string().optional(),
10012
10055
  // ZERO DATA LOSS - additional fields
10013
10056
  duration: FeatureDurationSchema.optional(),
10014
- taskCount: z11.number().optional(),
10015
- agent: z11.string().optional(),
10057
+ taskCount: z12.number().optional(),
10058
+ agent: z12.string().optional(),
10016
10059
  // "fe+be", "fe", "be"
10017
- sprintName: z11.string().optional(),
10018
- completedDate: z11.string().optional(),
10060
+ sprintName: z12.string().optional(),
10061
+ completedDate: z12.string().optional(),
10019
10062
  // =========================================================================
10020
10063
  // AI ORCHESTRATION FIELDS (v0.29.0)
10021
10064
  // =========================================================================
10022
10065
  // PRD Integration
10023
- prdId: z11.string().nullable().optional(),
10066
+ prdId: z12.string().nullable().optional(),
10024
10067
  // Link to PRD (prd_xxxxxxxx)
10025
10068
  // Legacy Support (for existing projects)
10026
- legacy: z11.boolean().optional(),
10069
+ legacy: z12.boolean().optional(),
10027
10070
  // true = no PRD required
10028
10071
  inferredFrom: InferredFromSchema.optional(),
10029
10072
  // git, git-branch, manual, prd
10030
10073
  // Quarter Planning
10031
- quarter: z11.string().nullable().optional(),
10074
+ quarter: z12.string().nullable().optional(),
10032
10075
  // Q1-2026, etc.
10033
10076
  // Dependency Tracking
10034
- dependencies: z11.array(z11.string()).optional(),
10077
+ dependencies: z12.array(z12.string()).optional(),
10035
10078
  // Feature IDs this depends on
10036
- blockedBy: z11.array(z11.string()).optional(),
10079
+ blockedBy: z12.array(z12.string()).optional(),
10037
10080
  // Feature IDs blocking this
10038
10081
  // Effort Tracking (for PRD comparison)
10039
10082
  effortTracking: FeatureEffortSchema.optional(),
10040
10083
  // Value Scoring (calculated from PRD)
10041
- valueScore: z11.number().optional(),
10084
+ valueScore: z12.number().optional(),
10042
10085
  // Calculated priority score
10043
10086
  // Git Data (for legacy features)
10044
- commits: z11.array(GitCommitSchema).optional(),
10087
+ commits: z12.array(GitCommitSchema).optional(),
10045
10088
  // Commits for this feature
10046
- branch: z11.string().optional(),
10089
+ branch: z12.string().optional(),
10047
10090
  // Branch name (for active)
10048
- commitsAhead: z11.number().optional()
10091
+ commitsAhead: z12.number().optional()
10049
10092
  // Commits ahead of main
10050
10093
  });
10051
- BacklogItemSchema = z11.object({
10052
- id: z11.string(),
10053
- title: z11.string(),
10054
- prdId: z11.string().nullable().optional(),
10055
- valueScore: z11.number().optional(),
10056
- effortEstimate: z11.number().optional(),
10057
- reason: z11.string().optional()
10094
+ BacklogItemSchema = z12.object({
10095
+ id: z12.string(),
10096
+ title: z12.string(),
10097
+ prdId: z12.string().nullable().optional(),
10098
+ valueScore: z12.number().optional(),
10099
+ effortEstimate: z12.number().optional(),
10100
+ reason: z12.string().optional()
10058
10101
  // Why in backlog
10059
10102
  });
10060
- RoadmapJsonSchema = z11.object({
10103
+ RoadmapJsonSchema = z12.object({
10061
10104
  strategy: RoadmapStrategySchema.nullable().optional(),
10062
- features: z11.array(FeatureItemSchema),
10063
- backlog: z11.array(z11.union([z11.string(), BacklogItemSchema])),
10105
+ features: z12.array(FeatureItemSchema),
10106
+ backlog: z12.array(z12.union([z12.string(), BacklogItemSchema])),
10064
10107
  // Support both formats
10065
- lastUpdated: z11.string(),
10108
+ lastUpdated: z12.string(),
10066
10109
  // AI ORCHESTRATION FIELDS (v0.29.0)
10067
- quarters: z11.array(QuarterSchema).optional(),
10110
+ quarters: z12.array(QuarterSchema).optional(),
10068
10111
  // Metadata (for git-inferred roadmaps)
10069
- generatedFrom: z11.enum(["git-history", "manual", "prd"]).optional(),
10070
- generatedAt: z11.string().optional()
10112
+ generatedFrom: z12.enum(["git-history", "manual", "prd"]).optional(),
10113
+ generatedAt: z12.string().optional()
10071
10114
  });
10072
10115
  DEFAULT_FEATURE = {
10073
10116
  date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
@@ -10105,79 +10148,79 @@ var init_schemas = __esm({
10105
10148
  });
10106
10149
 
10107
10150
  // core/schemas/shipped.ts
10108
- import { z as z12 } from "zod";
10151
+ import { z as z13 } from "zod";
10109
10152
  var ShipTypeSchema, CheckStatusSchema, ChangeTypeSchema, DurationSchema, CodeMetricsSchema, ShipChangeSchema, QualityMetricsSchema, CommitInfoSchema, ShippedItemSchema, ShippedJsonSchema;
10110
10153
  var init_shipped = __esm({
10111
10154
  "core/schemas/shipped.ts"() {
10112
10155
  "use strict";
10113
- ShipTypeSchema = z12.enum(["feature", "fix", "improvement", "refactor"]);
10114
- CheckStatusSchema = z12.enum(["pass", "warning", "fail", "skipped"]);
10115
- ChangeTypeSchema = z12.enum(["added", "changed", "fixed", "removed"]);
10116
- DurationSchema = z12.object({
10117
- hours: z12.number(),
10118
- minutes: z12.number(),
10119
- totalMinutes: z12.number()
10156
+ ShipTypeSchema = z13.enum(["feature", "fix", "improvement", "refactor"]);
10157
+ CheckStatusSchema = z13.enum(["pass", "warning", "fail", "skipped"]);
10158
+ ChangeTypeSchema = z13.enum(["added", "changed", "fixed", "removed"]);
10159
+ DurationSchema = z13.object({
10160
+ hours: z13.number(),
10161
+ minutes: z13.number(),
10162
+ totalMinutes: z13.number()
10120
10163
  });
10121
- CodeMetricsSchema = z12.object({
10122
- filesChanged: z12.number().nullable().optional(),
10123
- linesAdded: z12.number().nullable().optional(),
10124
- linesRemoved: z12.number().nullable().optional(),
10125
- commits: z12.number().nullable().optional()
10164
+ CodeMetricsSchema = z13.object({
10165
+ filesChanged: z13.number().nullable().optional(),
10166
+ linesAdded: z13.number().nullable().optional(),
10167
+ linesRemoved: z13.number().nullable().optional(),
10168
+ commits: z13.number().nullable().optional()
10126
10169
  });
10127
- ShipChangeSchema = z12.object({
10128
- description: z12.string(),
10170
+ ShipChangeSchema = z13.object({
10171
+ description: z13.string(),
10129
10172
  type: ChangeTypeSchema.optional()
10130
10173
  });
10131
- QualityMetricsSchema = z12.object({
10174
+ QualityMetricsSchema = z13.object({
10132
10175
  lintStatus: CheckStatusSchema.nullable().optional(),
10133
- lintDetails: z12.string().optional(),
10176
+ lintDetails: z13.string().optional(),
10134
10177
  testStatus: CheckStatusSchema.nullable().optional(),
10135
- testDetails: z12.string().optional()
10178
+ testDetails: z13.string().optional()
10136
10179
  });
10137
- CommitInfoSchema = z12.object({
10138
- hash: z12.string().optional(),
10139
- message: z12.string().optional(),
10140
- branch: z12.string().optional()
10180
+ CommitInfoSchema = z13.object({
10181
+ hash: z13.string().optional(),
10182
+ message: z13.string().optional(),
10183
+ branch: z13.string().optional()
10141
10184
  });
10142
- ShippedItemSchema = z12.object({
10143
- id: z12.string(),
10185
+ ShippedItemSchema = z13.object({
10186
+ id: z13.string(),
10144
10187
  // ship_xxxxxxxx
10145
- name: z12.string(),
10146
- version: z12.string().nullable().optional(),
10188
+ name: z13.string(),
10189
+ version: z13.string().nullable().optional(),
10147
10190
  type: ShipTypeSchema,
10148
- agent: z12.string().optional(),
10191
+ agent: z13.string().optional(),
10149
10192
  // "fe+be", "be", "fe"
10150
- description: z12.string().optional(),
10151
- changes: z12.array(ShipChangeSchema).optional(),
10152
- codeSnippets: z12.array(z12.string()).optional(),
10193
+ description: z13.string().optional(),
10194
+ changes: z13.array(ShipChangeSchema).optional(),
10195
+ codeSnippets: z13.array(z13.string()).optional(),
10153
10196
  commit: CommitInfoSchema.optional(),
10154
10197
  codeMetrics: CodeMetricsSchema.optional(),
10155
10198
  qualityMetrics: QualityMetricsSchema.optional(),
10156
- quantitativeImpact: z12.string().optional(),
10199
+ quantitativeImpact: z13.string().optional(),
10157
10200
  duration: DurationSchema.optional(),
10158
- tasksCompleted: z12.number().nullable().optional(),
10159
- shippedAt: z12.string(),
10201
+ tasksCompleted: z13.number().nullable().optional(),
10202
+ shippedAt: z13.string(),
10160
10203
  // ISO8601
10161
- featureId: z12.string().optional()
10204
+ featureId: z13.string().optional()
10162
10205
  });
10163
- ShippedJsonSchema = z12.object({
10164
- shipped: z12.array(ShippedItemSchema),
10165
- lastUpdated: z12.string()
10206
+ ShippedJsonSchema = z13.object({
10207
+ shipped: z13.array(ShippedItemSchema),
10208
+ lastUpdated: z13.string()
10166
10209
  });
10167
10210
  }
10168
10211
  });
10169
10212
 
10170
10213
  // core/schemas/state.ts
10171
- import { z as z13 } from "zod";
10214
+ import { z as z14 } from "zod";
10172
10215
  var PrioritySchema, TaskTypeSchema, TaskSectionSchema, TaskStatusSchema, ActivityTypeSchema, SubtaskSummarySchema, SubtaskSchema, SubtaskProgressSchema, CurrentTaskSchema, PreviousTaskSchema, StateJsonSchema, QueueTaskSchema, QueueJsonSchema, StatsSchema, RecentActivitySchema, StateSchemaFull;
10173
10216
  var init_state = __esm({
10174
10217
  "core/schemas/state.ts"() {
10175
10218
  "use strict";
10176
10219
  init_model();
10177
- PrioritySchema = z13.enum(["low", "medium", "high", "critical"]);
10178
- TaskTypeSchema = z13.enum(["feature", "bug", "improvement", "chore"]);
10179
- TaskSectionSchema = z13.enum(["active", "backlog", "previously_active"]);
10180
- TaskStatusSchema = z13.enum([
10220
+ PrioritySchema = z14.enum(["low", "medium", "high", "critical"]);
10221
+ TaskTypeSchema = z14.enum(["feature", "bug", "improvement", "chore"]);
10222
+ TaskSectionSchema = z14.enum(["active", "backlog", "previously_active"]);
10223
+ TaskStatusSchema = z14.enum([
10181
10224
  "pending",
10182
10225
  "in_progress",
10183
10226
  "completed",
@@ -10186,151 +10229,151 @@ var init_state = __esm({
10186
10229
  "failed",
10187
10230
  "skipped"
10188
10231
  ]);
10189
- ActivityTypeSchema = z13.enum([
10232
+ ActivityTypeSchema = z14.enum([
10190
10233
  "task_completed",
10191
10234
  "feature_shipped",
10192
10235
  "idea_captured",
10193
10236
  "session_started"
10194
10237
  ]);
10195
- SubtaskSummarySchema = z13.object({
10196
- title: z13.string(),
10197
- description: z13.string(),
10198
- filesChanged: z13.array(
10199
- z13.object({
10200
- path: z13.string(),
10201
- action: z13.enum(["created", "modified", "deleted"])
10238
+ SubtaskSummarySchema = z14.object({
10239
+ title: z14.string(),
10240
+ description: z14.string(),
10241
+ filesChanged: z14.array(
10242
+ z14.object({
10243
+ path: z14.string(),
10244
+ action: z14.enum(["created", "modified", "deleted"])
10202
10245
  })
10203
10246
  ),
10204
- whatWasDone: z13.array(z13.string()),
10205
- outputForNextAgent: z13.string().optional(),
10206
- notes: z13.string().optional()
10247
+ whatWasDone: z14.array(z14.string()),
10248
+ outputForNextAgent: z14.string().optional(),
10249
+ notes: z14.string().optional()
10207
10250
  });
10208
- SubtaskSchema = z13.object({
10209
- id: z13.string(),
10251
+ SubtaskSchema = z14.object({
10252
+ id: z14.string(),
10210
10253
  // subtask-xxx
10211
- description: z13.string(),
10212
- domain: z13.string(),
10254
+ description: z14.string(),
10255
+ domain: z14.string(),
10213
10256
  // frontend, backend, database, testing, etc.
10214
- agent: z13.string(),
10257
+ agent: z14.string(),
10215
10258
  // agent file name (e.g., "frontend.md")
10216
10259
  status: TaskStatusSchema,
10217
- dependsOn: z13.array(z13.string()),
10260
+ dependsOn: z14.array(z14.string()),
10218
10261
  // IDs of dependent subtasks
10219
- startedAt: z13.string().optional(),
10262
+ startedAt: z14.string().optional(),
10220
10263
  // ISO8601
10221
- completedAt: z13.string().optional(),
10264
+ completedAt: z14.string().optional(),
10222
10265
  // ISO8601
10223
- output: z13.string().optional(),
10266
+ output: z14.string().optional(),
10224
10267
  // Brief output description
10225
10268
  summary: SubtaskSummarySchema.optional(),
10226
10269
  // Full summary for context handoff
10227
- skipReason: z13.string().optional(),
10270
+ skipReason: z14.string().optional(),
10228
10271
  // Why this subtask was skipped
10229
- blockReason: z13.string().optional(),
10272
+ blockReason: z14.string().optional(),
10230
10273
  // What is blocking this subtask
10231
10274
  // Fibonacci estimation
10232
- estimatedPoints: z13.number().optional(),
10275
+ estimatedPoints: z14.number().optional(),
10233
10276
  // Fibonacci: 1,2,3,5,8,13,21
10234
- estimatedMinutes: z13.number().optional()
10277
+ estimatedMinutes: z14.number().optional()
10235
10278
  // Derived from points
10236
10279
  });
10237
- SubtaskProgressSchema = z13.object({
10238
- completed: z13.number(),
10239
- total: z13.number(),
10240
- percentage: z13.number()
10280
+ SubtaskProgressSchema = z14.object({
10281
+ completed: z14.number(),
10282
+ total: z14.number(),
10283
+ percentage: z14.number()
10241
10284
  });
10242
- CurrentTaskSchema = z13.object({
10243
- id: z13.string(),
10285
+ CurrentTaskSchema = z14.object({
10286
+ id: z14.string(),
10244
10287
  // task_xxxxxxxx
10245
- description: z13.string(),
10246
- startedAt: z13.string(),
10288
+ description: z14.string(),
10289
+ startedAt: z14.string(),
10247
10290
  // ISO8601
10248
- sessionId: z13.string(),
10291
+ sessionId: z14.string(),
10249
10292
  // sess_xxxxxxxx
10250
- featureId: z13.string().optional(),
10293
+ featureId: z14.string().optional(),
10251
10294
  // feat_xxxxxxxx
10252
10295
  // Subtask tracking for fragmented tasks
10253
- subtasks: z13.array(SubtaskSchema).optional(),
10254
- currentSubtaskIndex: z13.number().optional(),
10296
+ subtasks: z14.array(SubtaskSchema).optional(),
10297
+ currentSubtaskIndex: z14.number().optional(),
10255
10298
  subtaskProgress: SubtaskProgressSchema.optional(),
10256
10299
  // Linear integration - bidirectional sync
10257
- linearId: z13.string().optional(),
10300
+ linearId: z14.string().optional(),
10258
10301
  // "PRJ-123" - Linear identifier
10259
- linearUuid: z13.string().optional(),
10302
+ linearUuid: z14.string().optional(),
10260
10303
  // Linear internal UUID for API calls
10261
10304
  // Fibonacci estimation
10262
- estimatedPoints: z13.number().optional(),
10305
+ estimatedPoints: z14.number().optional(),
10263
10306
  // Fibonacci: 1,2,3,5,8,13,21
10264
- estimatedMinutes: z13.number().optional(),
10307
+ estimatedMinutes: z14.number().optional(),
10265
10308
  // Derived from points
10266
10309
  // Model specification - which AI model was used (PRJ-265)
10267
10310
  modelMetadata: ModelMetadataSchema.optional()
10268
10311
  });
10269
- PreviousTaskSchema = z13.object({
10270
- id: z13.string(),
10271
- description: z13.string(),
10272
- status: z13.literal("paused"),
10273
- startedAt: z13.string(),
10312
+ PreviousTaskSchema = z14.object({
10313
+ id: z14.string(),
10314
+ description: z14.string(),
10315
+ status: z14.literal("paused"),
10316
+ startedAt: z14.string(),
10274
10317
  // ISO8601
10275
- pausedAt: z13.string(),
10318
+ pausedAt: z14.string(),
10276
10319
  // ISO8601
10277
- pauseReason: z13.string().optional()
10320
+ pauseReason: z14.string().optional()
10278
10321
  });
10279
- StateJsonSchema = z13.object({
10322
+ StateJsonSchema = z14.object({
10280
10323
  currentTask: CurrentTaskSchema.nullable(),
10281
10324
  previousTask: PreviousTaskSchema.nullable().optional(),
10282
10325
  // deprecated: use pausedTasks
10283
- pausedTasks: z13.array(PreviousTaskSchema).optional(),
10326
+ pausedTasks: z14.array(PreviousTaskSchema).optional(),
10284
10327
  // replaces previousTask
10285
- lastUpdated: z13.string()
10328
+ lastUpdated: z14.string()
10286
10329
  });
10287
- QueueTaskSchema = z13.object({
10288
- id: z13.string(),
10330
+ QueueTaskSchema = z14.object({
10331
+ id: z14.string(),
10289
10332
  // task_xxxxxxxx
10290
- description: z13.string(),
10333
+ description: z14.string(),
10291
10334
  priority: PrioritySchema,
10292
10335
  type: TaskTypeSchema,
10293
10336
  // detect from emoji 🐛=bug
10294
- featureId: z13.string().optional(),
10295
- originFeature: z13.string().optional(),
10296
- completed: z13.boolean(),
10297
- completedAt: z13.string().optional(),
10298
- createdAt: z13.string(),
10337
+ featureId: z14.string().optional(),
10338
+ originFeature: z14.string().optional(),
10339
+ completed: z14.boolean(),
10340
+ completedAt: z14.string().optional(),
10341
+ createdAt: z14.string(),
10299
10342
  // ISO8601
10300
10343
  section: TaskSectionSchema,
10301
10344
  // Additional fields for ZERO DATA LOSS
10302
- agent: z13.string().optional(),
10345
+ agent: z14.string().optional(),
10303
10346
  // "fe", "be", "fe + be"
10304
- groupName: z13.string().optional(),
10347
+ groupName: z14.string().optional(),
10305
10348
  // "Sales Reports", "Stock Audits"
10306
- groupId: z13.string().optional()
10349
+ groupId: z14.string().optional()
10307
10350
  // For grouping related tasks
10308
10351
  });
10309
- QueueJsonSchema = z13.object({
10310
- tasks: z13.array(QueueTaskSchema),
10311
- lastUpdated: z13.string()
10352
+ QueueJsonSchema = z14.object({
10353
+ tasks: z14.array(QueueTaskSchema),
10354
+ lastUpdated: z14.string()
10312
10355
  });
10313
- StatsSchema = z13.object({
10314
- tasksToday: z13.number(),
10315
- tasksThisWeek: z13.number(),
10316
- streak: z13.number(),
10317
- velocity: z13.string(),
10318
- avgDuration: z13.string()
10356
+ StatsSchema = z14.object({
10357
+ tasksToday: z14.number(),
10358
+ tasksThisWeek: z14.number(),
10359
+ streak: z14.number(),
10360
+ velocity: z14.string(),
10361
+ avgDuration: z14.string()
10319
10362
  });
10320
- RecentActivitySchema = z13.object({
10363
+ RecentActivitySchema = z14.object({
10321
10364
  type: ActivityTypeSchema,
10322
- description: z13.string(),
10323
- timestamp: z13.string(),
10365
+ description: z14.string(),
10366
+ timestamp: z14.string(),
10324
10367
  // ISO8601
10325
- duration: z13.string().optional()
10368
+ duration: z14.string().optional()
10326
10369
  });
10327
- StateSchemaFull = z13.object({
10328
- projectId: z13.string(),
10370
+ StateSchemaFull = z14.object({
10371
+ projectId: z14.string(),
10329
10372
  currentTask: CurrentTaskSchema.nullable(),
10330
- queue: z13.array(QueueTaskSchema),
10373
+ queue: z14.array(QueueTaskSchema),
10331
10374
  stats: StatsSchema,
10332
- recentActivity: z13.array(RecentActivitySchema),
10333
- lastSync: z13.string()
10375
+ recentActivity: z14.array(RecentActivitySchema),
10376
+ lastSync: z14.string()
10334
10377
  // ISO8601
10335
10378
  });
10336
10379
  }
@@ -11327,6 +11370,250 @@ Context: ${context2}` : ""}`,
11327
11370
  }
11328
11371
  });
11329
11372
 
11373
+ // core/storage/analysis-storage.ts
11374
+ import { createHash } from "node:crypto";
11375
+ var AnalysisStorage, analysisStorage;
11376
+ var init_analysis_storage = __esm({
11377
+ "core/storage/analysis-storage.ts"() {
11378
+ "use strict";
11379
+ init_analysis();
11380
+ init_date_helper();
11381
+ init_storage_manager();
11382
+ AnalysisStorage = class extends StorageManager {
11383
+ static {
11384
+ __name(this, "AnalysisStorage");
11385
+ }
11386
+ constructor() {
11387
+ super("analysis.json");
11388
+ }
11389
+ getDefault() {
11390
+ return {
11391
+ draft: null,
11392
+ sealed: null,
11393
+ lastUpdated: ""
11394
+ };
11395
+ }
11396
+ getMdFilename() {
11397
+ return "analysis.md";
11398
+ }
11399
+ getLayer() {
11400
+ return "analysis";
11401
+ }
11402
+ getEventType(action) {
11403
+ return `analysis.${action}d`;
11404
+ }
11405
+ toMarkdown(data) {
11406
+ const lines = ["# Analysis Status", ""];
11407
+ if (data.sealed) {
11408
+ lines.push("## Sealed Analysis");
11409
+ lines.push(`- **Status**: sealed`);
11410
+ lines.push(`- **Commit**: \`${data.sealed.commitHash || "unknown"}\``);
11411
+ lines.push(`- **Sealed at**: ${data.sealed.sealedAt || "unknown"}`);
11412
+ lines.push(`- **Languages**: ${data.sealed.languages.join(", ") || "none"}`);
11413
+ lines.push(`- **Frameworks**: ${data.sealed.frameworks.join(", ") || "none"}`);
11414
+ lines.push(`- **Files**: ${data.sealed.fileCount}`);
11415
+ if (data.sealed.patterns.length > 0) {
11416
+ lines.push(`- **Patterns**: ${data.sealed.patterns.map((p) => p.name).join(", ")}`);
11417
+ }
11418
+ lines.push("");
11419
+ }
11420
+ if (data.draft && data.draft.status === "draft") {
11421
+ lines.push("## Draft Analysis");
11422
+ lines.push(`- **Status**: draft (not yet sealed)`);
11423
+ lines.push(`- **Commit**: \`${data.draft.commitHash || "unknown"}\``);
11424
+ lines.push(`- **Analyzed at**: ${data.draft.analyzedAt}`);
11425
+ lines.push(`- **Languages**: ${data.draft.languages.join(", ") || "none"}`);
11426
+ lines.push(`- **Frameworks**: ${data.draft.frameworks.join(", ") || "none"}`);
11427
+ lines.push(`- **Files**: ${data.draft.fileCount}`);
11428
+ lines.push("");
11429
+ }
11430
+ if (!data.sealed && !data.draft) {
11431
+ lines.push("_No analysis available. Run `p. sync` to generate._");
11432
+ lines.push("");
11433
+ }
11434
+ return lines.join("\n");
11435
+ }
11436
+ // ===========================================================================
11437
+ // Domain Methods
11438
+ // ===========================================================================
11439
+ /**
11440
+ * Save a new draft analysis (called by sync-service).
11441
+ * Preserves existing sealed analysis.
11442
+ */
11443
+ async saveDraft(projectId, analysis2) {
11444
+ const draft = {
11445
+ ...analysis2,
11446
+ status: "draft"
11447
+ };
11448
+ AnalysisItemSchema.parse(draft);
11449
+ await this.update(projectId, (data) => ({
11450
+ ...data,
11451
+ draft,
11452
+ lastUpdated: getTimestamp()
11453
+ }));
11454
+ await this.publishEntityEvent(projectId, "analysis", "drafted", {
11455
+ commitHash: draft.commitHash,
11456
+ fileCount: draft.fileCount
11457
+ });
11458
+ }
11459
+ /**
11460
+ * Seal the current draft analysis.
11461
+ * Computes SHA-256 signature and locks the analysis.
11462
+ */
11463
+ async seal(projectId) {
11464
+ const data = await this.read(projectId);
11465
+ if (!data.draft) {
11466
+ return { success: false, error: "No draft analysis to seal. Run `p. sync` first." };
11467
+ }
11468
+ if (data.draft.status === "sealed") {
11469
+ return { success: false, error: "Draft is already sealed." };
11470
+ }
11471
+ const signature = this.computeSignature(data.draft);
11472
+ const now = getTimestamp();
11473
+ const sealed = {
11474
+ ...data.draft,
11475
+ status: "sealed",
11476
+ signature,
11477
+ sealedAt: now
11478
+ };
11479
+ AnalysisItemSchema.parse(sealed);
11480
+ await this.write(projectId, {
11481
+ draft: null,
11482
+ // Clear draft — it's now sealed
11483
+ sealed,
11484
+ lastUpdated: now
11485
+ });
11486
+ await this.publishEntityEvent(projectId, "analysis", "sealed", {
11487
+ commitHash: sealed.commitHash,
11488
+ signature
11489
+ });
11490
+ return { success: true, signature };
11491
+ }
11492
+ /**
11493
+ * Get the sealed analysis (for task context injection).
11494
+ * Returns null if no sealed analysis exists.
11495
+ */
11496
+ async getSealed(projectId) {
11497
+ const data = await this.read(projectId);
11498
+ return data.sealed;
11499
+ }
11500
+ /**
11501
+ * Get the current draft analysis.
11502
+ */
11503
+ async getDraft(projectId) {
11504
+ const data = await this.read(projectId);
11505
+ return data.draft;
11506
+ }
11507
+ /**
11508
+ * Get the active analysis (sealed if available, otherwise draft).
11509
+ * This is what tasks should consume.
11510
+ */
11511
+ async getActive(projectId) {
11512
+ const data = await this.read(projectId);
11513
+ return data.sealed ?? data.draft;
11514
+ }
11515
+ /**
11516
+ * Get the current analysis status.
11517
+ */
11518
+ async getStatus(projectId) {
11519
+ const data = await this.read(projectId);
11520
+ return {
11521
+ hasSealed: data.sealed !== null,
11522
+ hasDraft: data.draft !== null,
11523
+ sealedCommit: data.sealed?.commitHash ?? null,
11524
+ draftCommit: data.draft?.commitHash ?? null,
11525
+ sealedAt: data.sealed?.sealedAt ?? null
11526
+ };
11527
+ }
11528
+ /**
11529
+ * Check if sealed analysis is stale (commit hash differs from current HEAD).
11530
+ */
11531
+ checkStaleness(sealedCommit, currentCommit) {
11532
+ if (!sealedCommit) {
11533
+ return {
11534
+ isStale: false,
11535
+ sealedCommit: null,
11536
+ currentCommit,
11537
+ message: "No sealed analysis. Run `p. sync` then `p. seal`."
11538
+ };
11539
+ }
11540
+ if (!currentCommit) {
11541
+ return {
11542
+ isStale: true,
11543
+ sealedCommit,
11544
+ currentCommit: null,
11545
+ message: "Cannot determine current commit. Analysis may be stale."
11546
+ };
11547
+ }
11548
+ if (sealedCommit !== currentCommit) {
11549
+ return {
11550
+ isStale: true,
11551
+ sealedCommit,
11552
+ currentCommit,
11553
+ message: `Analysis is stale: sealed at ${sealedCommit}, HEAD is ${currentCommit}. Run \`p. sync\` + \`p. seal\` to update.`
11554
+ };
11555
+ }
11556
+ return {
11557
+ isStale: false,
11558
+ sealedCommit,
11559
+ currentCommit,
11560
+ message: "Analysis is current."
11561
+ };
11562
+ }
11563
+ /**
11564
+ * Verify the integrity of a sealed analysis by recomputing its signature.
11565
+ */
11566
+ async verify(projectId) {
11567
+ const data = await this.read(projectId);
11568
+ if (!data.sealed) {
11569
+ return { valid: false, message: "No sealed analysis to verify." };
11570
+ }
11571
+ if (!data.sealed.signature) {
11572
+ return { valid: false, message: "Sealed analysis has no signature." };
11573
+ }
11574
+ const expected = this.computeSignature({
11575
+ ...data.sealed,
11576
+ // Strip signature and sealedAt before recomputing — they weren't part of the original hash
11577
+ signature: void 0,
11578
+ sealedAt: void 0
11579
+ });
11580
+ if (expected === data.sealed.signature) {
11581
+ return { valid: true, message: "Signature verified. Analysis integrity confirmed." };
11582
+ }
11583
+ return {
11584
+ valid: false,
11585
+ message: `Signature mismatch. Expected ${expected}, got ${data.sealed.signature}. Analysis may have been modified.`
11586
+ };
11587
+ }
11588
+ // ===========================================================================
11589
+ // Private Helpers
11590
+ // ===========================================================================
11591
+ /**
11592
+ * Compute SHA-256 signature for analysis data.
11593
+ * Deterministic: same input always produces same hash.
11594
+ */
11595
+ computeSignature(analysis2) {
11596
+ const canonical = {
11597
+ projectId: analysis2.projectId,
11598
+ languages: analysis2.languages,
11599
+ frameworks: analysis2.frameworks,
11600
+ packageManager: analysis2.packageManager,
11601
+ sourceDir: analysis2.sourceDir,
11602
+ testDir: analysis2.testDir,
11603
+ configFiles: analysis2.configFiles,
11604
+ fileCount: analysis2.fileCount,
11605
+ patterns: analysis2.patterns,
11606
+ antiPatterns: analysis2.antiPatterns,
11607
+ analyzedAt: analysis2.analyzedAt,
11608
+ commitHash: analysis2.commitHash
11609
+ };
11610
+ return createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
11611
+ }
11612
+ };
11613
+ analysisStorage = new AnalysisStorage();
11614
+ }
11615
+ });
11616
+
11330
11617
  // core/storage/ideas-storage.ts
11331
11618
  var IdeasStorage, ideasStorage;
11332
11619
  var init_ideas_storage = __esm({
@@ -13363,6 +13650,7 @@ var init_storage = __esm({
13363
13650
  var init_storage2 = __esm({
13364
13651
  "core/storage/index.ts"() {
13365
13652
  "use strict";
13653
+ init_analysis_storage();
13366
13654
  init_ideas_storage();
13367
13655
  init_index_storage();
13368
13656
  init_metrics_storage();
@@ -13375,11 +13663,11 @@ var init_storage2 = __esm({
13375
13663
  });
13376
13664
 
13377
13665
  // core/agentic/domain-classifier.ts
13378
- import { createHash } from "node:crypto";
13666
+ import { createHash as createHash2 } from "node:crypto";
13379
13667
  import fs28 from "node:fs/promises";
13380
13668
  import path26 from "node:path";
13381
13669
  function hashDescription(description) {
13382
- return createHash("sha256").update(description.toLowerCase().trim()).digest("hex").slice(0, 16);
13670
+ return createHash2("sha256").update(description.toLowerCase().trim()).digest("hex").slice(0, 16);
13383
13671
  }
13384
13672
  async function loadCache(globalPath) {
13385
13673
  try {
@@ -15054,22 +15342,94 @@ var init_outcomes2 = __esm({
15054
15342
  }
15055
15343
  });
15056
15344
 
15345
+ // core/agentic/anti-hallucination.ts
15346
+ import { z as z15 } from "zod";
15347
+ function buildAntiHallucinationBlock(truth) {
15348
+ const parts = [];
15349
+ parts.push("## CONSTRAINTS (Read Before Acting)\n");
15350
+ const available = [];
15351
+ if (truth.language) available.push(truth.language);
15352
+ if (truth.framework) available.push(truth.framework);
15353
+ const techStack = truth.techStack ?? [];
15354
+ available.push(...techStack.filter((t) => t !== truth.framework));
15355
+ if (available.length > 0) {
15356
+ parts.push(`AVAILABLE in this project: ${available.join(", ")}`);
15357
+ }
15358
+ if (truth.domains) {
15359
+ const absent = Object.entries(truth.domains).filter(([, hasIt]) => !hasIt).map(([key]) => DOMAIN_LABELS[key]).filter(Boolean);
15360
+ if (absent.length > 0) {
15361
+ parts.push(`NOT PRESENT: ${absent.join(", ")}`);
15362
+ }
15363
+ }
15364
+ const availableAgents = truth.availableAgents ?? [];
15365
+ if (availableAgents.length > 0) {
15366
+ parts.push(`AGENTS: ${availableAgents.join(", ")}`);
15367
+ }
15368
+ parts.push("");
15369
+ parts.push(`SCOPE: Only files in \`${truth.projectPath}\` are accessible.`);
15370
+ parts.push("RULE: Use ONLY file paths explicitly shown in context. Do NOT infer or guess paths.");
15371
+ parts.push("RULE: NEVER assume a library is available. Check package.json/imports first.");
15372
+ parts.push("RULE: If previous context contradicts this section, trust this section.");
15373
+ parts.push("RULE: Read files BEFORE modifying. Never assume code structure.");
15374
+ if (truth.fileCount) {
15375
+ parts.push(`
15376
+ Context: ${truth.fileCount} files in project.`);
15377
+ }
15378
+ return parts.join("\n");
15379
+ }
15380
+ var ProjectGroundTruthSchema, DOMAIN_LABELS;
15381
+ var init_anti_hallucination = __esm({
15382
+ "core/agentic/anti-hallucination.ts"() {
15383
+ "use strict";
15384
+ ProjectGroundTruthSchema = z15.object({
15385
+ /** Project root path */
15386
+ projectPath: z15.string(),
15387
+ /** Programming language (e.g., 'TypeScript', 'JavaScript', 'Python') */
15388
+ language: z15.string().optional(),
15389
+ /** Primary framework (e.g., 'Hono', 'Next.js', 'Express') */
15390
+ framework: z15.string().optional(),
15391
+ /** Technology stack items (e.g., ['Hono', 'Zod', 'Vitest']) */
15392
+ techStack: z15.array(z15.string()).default([]),
15393
+ /** Domain flags from sealed analysis */
15394
+ domains: z15.object({
15395
+ hasFrontend: z15.boolean().default(false),
15396
+ hasBackend: z15.boolean().default(false),
15397
+ hasDatabase: z15.boolean().default(false),
15398
+ hasTesting: z15.boolean().default(false),
15399
+ hasDocker: z15.boolean().default(false)
15400
+ }).optional(),
15401
+ /** Total files in project */
15402
+ fileCount: z15.number().optional(),
15403
+ /** Available agent names (e.g., ['backend', 'testing']) */
15404
+ availableAgents: z15.array(z15.string()).default([])
15405
+ });
15406
+ DOMAIN_LABELS = {
15407
+ hasFrontend: "Frontend (UI/components)",
15408
+ hasBackend: "Backend (APIs/servers)",
15409
+ hasDatabase: "Database (SQL/ORM)",
15410
+ hasTesting: "Testing (unit/integration)",
15411
+ hasDocker: "Docker/containers"
15412
+ };
15413
+ __name(buildAntiHallucinationBlock, "buildAntiHallucinationBlock");
15414
+ }
15415
+ });
15416
+
15057
15417
  // core/schemas/command-context.ts
15058
- import { z as z14 } from "zod";
15418
+ import { z as z16 } from "zod";
15059
15419
  var CommandContextEntrySchema, CommandContextConfigSchema;
15060
15420
  var init_command_context = __esm({
15061
15421
  "core/schemas/command-context.ts"() {
15062
15422
  "use strict";
15063
- CommandContextEntrySchema = z14.object({
15064
- agents: z14.boolean(),
15065
- patterns: z14.boolean(),
15066
- checklist: z14.boolean(),
15067
- modules: z14.array(z14.string())
15423
+ CommandContextEntrySchema = z16.object({
15424
+ agents: z16.boolean(),
15425
+ patterns: z16.boolean(),
15426
+ checklist: z16.boolean(),
15427
+ modules: z16.array(z16.string())
15068
15428
  });
15069
- CommandContextConfigSchema = z14.object({
15070
- version: z14.string(),
15071
- description: z14.string().optional(),
15072
- commands: z14.record(z14.string(), CommandContextEntrySchema).refine((commands) => "*" in commands, {
15429
+ CommandContextConfigSchema = z16.object({
15430
+ version: z16.string(),
15431
+ description: z16.string().optional(),
15432
+ commands: z16.record(z16.string(), CommandContextEntrySchema).refine((commands) => "*" in commands, {
15073
15433
  message: 'Config must include a "*" wildcard entry for unknown commands'
15074
15434
  })
15075
15435
  });
@@ -15259,7 +15619,82 @@ var init_command_context2 = __esm({
15259
15619
  }
15260
15620
  });
15261
15621
 
15622
+ // core/agentic/environment-block.ts
15623
+ import os10 from "node:os";
15624
+ import { z as z17 } from "zod";
15625
+ function detectRuntime2() {
15626
+ if (typeof globalThis !== "undefined" && "Bun" in globalThis) {
15627
+ return "bun";
15628
+ }
15629
+ return "node";
15630
+ }
15631
+ function normalizePlatform(platform) {
15632
+ const platformMap = {
15633
+ darwin: "macOS",
15634
+ linux: "Linux",
15635
+ win32: "Windows",
15636
+ freebsd: "FreeBSD"
15637
+ };
15638
+ return platformMap[platform] ?? platform;
15639
+ }
15640
+ function buildEnvironmentBlock(input) {
15641
+ const platform = input.platform ?? os10.platform();
15642
+ const runtime = input.runtime ?? detectRuntime2();
15643
+ const date = input.date ?? (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
15644
+ const fields = [
15645
+ ["project", input.projectName],
15646
+ ["path", input.projectPath],
15647
+ ["git", input.isGitRepo ? "true" : "false"],
15648
+ ["branch", input.gitBranch],
15649
+ ["platform", normalizePlatform(platform)],
15650
+ ["runtime", runtime],
15651
+ ["date", date],
15652
+ ["model", input.model],
15653
+ ["provider", input.provider]
15654
+ ];
15655
+ const lines = fields.filter(([, value]) => value !== void 0).map(([key, value]) => `${key}: ${value}`);
15656
+ return `<env>
15657
+ ${lines.join("\n")}
15658
+ </env>`;
15659
+ }
15660
+ var EnvironmentBlockInputSchema;
15661
+ var init_environment_block = __esm({
15662
+ "core/agentic/environment-block.ts"() {
15663
+ "use strict";
15664
+ EnvironmentBlockInputSchema = z17.object({
15665
+ /** Project display name */
15666
+ projectName: z17.string(),
15667
+ /** Absolute path to project root */
15668
+ projectPath: z17.string(),
15669
+ /** Whether the project is a git repository */
15670
+ isGitRepo: z17.boolean().default(true),
15671
+ /** Current git branch name */
15672
+ gitBranch: z17.string().optional(),
15673
+ /** Operating system platform (auto-detected if not provided) */
15674
+ platform: z17.string().optional(),
15675
+ /** JavaScript runtime (auto-detected if not provided) */
15676
+ runtime: z17.string().optional(),
15677
+ /** Current date in ISO format (auto-generated if not provided) */
15678
+ date: z17.string().optional(),
15679
+ /** AI model identifier (e.g., 'opus', 'sonnet', '2.5-pro') */
15680
+ model: z17.string().optional(),
15681
+ /** AI provider name (e.g., 'claude', 'gemini', 'cursor') */
15682
+ provider: z17.string().optional()
15683
+ });
15684
+ __name(detectRuntime2, "detectRuntime");
15685
+ __name(normalizePlatform, "normalizePlatform");
15686
+ __name(buildEnvironmentBlock, "buildEnvironmentBlock");
15687
+ }
15688
+ });
15689
+
15262
15690
  // core/agentic/injection-validator.ts
15691
+ function budgetsFromCoordinator(coordinator) {
15692
+ const injectionBudget = coordinator.getAllocationFor("injection");
15693
+ return {
15694
+ ...DEFAULT_BUDGETS,
15695
+ totalPrompt: injectionBudget
15696
+ };
15697
+ }
15263
15698
  function truncateToTokenBudget(text, maxTokens) {
15264
15699
  const maxChars = maxTokens * CHARS_PER_TOKEN2;
15265
15700
  if (text.length <= maxChars) return text;
@@ -15299,6 +15734,7 @@ var init_injection_validator = __esm({
15299
15734
  memories: 600,
15300
15735
  totalPrompt: 8e3
15301
15736
  };
15737
+ __name(budgetsFromCoordinator, "budgetsFromCoordinator");
15302
15738
  CHARS_PER_TOKEN2 = 4;
15303
15739
  __name(truncateToTokenBudget, "truncateToTokenBudget");
15304
15740
  __name(estimateTokens, "estimateTokens");
@@ -15362,7 +15798,9 @@ var init_prompt_builder = __esm({
15362
15798
  init_fs();
15363
15799
  init_fs_helpers();
15364
15800
  init_version();
15801
+ init_anti_hallucination();
15365
15802
  init_command_context2();
15803
+ init_environment_block();
15366
15804
  init_injection_validator();
15367
15805
  PromptBuilder = class {
15368
15806
  static {
@@ -15379,6 +15817,8 @@ var init_prompt_builder = __esm({
15379
15817
  _templateCache = /* @__PURE__ */ new Map();
15380
15818
  TEMPLATE_CACHE_TTL_MS = 6e4;
15381
15819
  // 60 seconds
15820
+ /** Active token budget coordinator (PRJ-266) */
15821
+ _coordinator = null;
15382
15822
  /**
15383
15823
  * Get a template with TTL caching.
15384
15824
  * Returns cached content if within TTL, otherwise loads from disk.
@@ -15414,6 +15854,31 @@ var init_prompt_builder = __esm({
15414
15854
  this._checklistRoutingCache = null;
15415
15855
  this._checklistRoutingCacheTime = 0;
15416
15856
  }
15857
+ /**
15858
+ * Set the token budget coordinator for model-aware budget management.
15859
+ * When set, budget allocations flow from the coordinator instead of defaults.
15860
+ *
15861
+ * @see PRJ-266
15862
+ */
15863
+ setCoordinator(coordinator) {
15864
+ this._coordinator = coordinator;
15865
+ }
15866
+ /** Get the active coordinator (may be null) */
15867
+ getCoordinator() {
15868
+ return this._coordinator;
15869
+ }
15870
+ /**
15871
+ * Get effective injection budgets.
15872
+ * Uses coordinator allocation when available, falls back to DEFAULT_BUDGETS.
15873
+ *
15874
+ * @see PRJ-266
15875
+ */
15876
+ getEffectiveBudgets() {
15877
+ if (this._coordinator) {
15878
+ return budgetsFromCoordinator(this._coordinator);
15879
+ }
15880
+ return DEFAULT_BUDGETS;
15881
+ }
15417
15882
  /**
15418
15883
  * Reset context (for testing)
15419
15884
  */
@@ -15555,7 +16020,7 @@ var init_prompt_builder = __esm({
15555
16020
  parts.push("---");
15556
16021
  parts.push("");
15557
16022
  const result = parts.join("\n");
15558
- return truncateToTokenBudget(result, DEFAULT_BUDGETS.autoContext);
16023
+ return truncateToTokenBudget(result, this.getEffectiveBudgets().autoContext);
15559
16024
  }
15560
16025
  /**
15561
16026
  * Calculate elapsed time from ISO timestamp.
@@ -15622,7 +16087,12 @@ var init_prompt_builder = __esm({
15622
16087
  return parts.join("");
15623
16088
  }
15624
16089
  /**
15625
- * Build a complete prompt for Claude from template, context, and enhancements
16090
+ * Build a complete prompt for Claude from template, context, and enhancements.
16091
+ *
16092
+ * Section ordering follows research-backed pattern (PRJ-301):
16093
+ * Identity → Environment → Ground Truth → Capabilities → Constraints →
16094
+ * Task Context → Task → Output Schema → Efficiency
16095
+ *
15626
16096
  * @deprecated Use buildWithInjection for auto-injected context
15627
16097
  */
15628
16098
  async build(template, context2, state, agent = null, learnedPatterns = null, thinkBlock = null, relevantMemories = null, planInfo = null, orchestratorContext = null) {
@@ -15661,33 +16131,70 @@ Apply specialized expertise. Read agent file for details if needed.
15661
16131
  parts.push(`INPUT: ${params.params.task || params.params.description}
15662
16132
  `);
15663
16133
  }
15664
- parts.push("\n---\n");
15665
- parts.push(template.content);
16134
+ const projectPath = context2.projectPath;
16135
+ if (projectPath) {
16136
+ const projectName = orchestratorContext?.project?.id ? path31.basename(projectPath) : path31.basename(projectPath);
16137
+ const envBlock = buildEnvironmentBlock({
16138
+ projectName,
16139
+ projectPath,
16140
+ isGitRepo: true,
16141
+ gitBranch: orchestratorContext?.realContext?.gitBranch
16142
+ });
16143
+ parts.push(`
16144
+ ${envBlock}
16145
+ `);
16146
+ }
15666
16147
  if (orchestratorContext) {
15667
- parts.push("\n## ORCHESTRATOR CONTEXT\n");
16148
+ parts.push("\n## PROJECT ANALYSIS (Sealed)\n");
16149
+ parts.push(`**Ecosystem**: ${orchestratorContext.project.ecosystem}
16150
+ `);
15668
16151
  parts.push(`**Primary Domain**: ${orchestratorContext.primaryDomain}
15669
16152
  `);
15670
16153
  parts.push(`**Domains**: ${orchestratorContext.detectedDomains.join(", ")}
15671
- `);
15672
- parts.push(`**Ecosystem**: ${orchestratorContext.project.ecosystem}
15673
16154
 
15674
16155
  `);
16156
+ }
16157
+ const needsPatterns = commandContext.patterns;
16158
+ const codePatternsContent = state?.codePatterns || "";
16159
+ if (needsPatterns && codePatternsContent && codePatternsContent.trim()) {
16160
+ const patternSummary = this.extractPatternSummary(codePatternsContent);
16161
+ if (patternSummary) {
16162
+ parts.push("## CODE PATTERNS\n");
16163
+ parts.push(patternSummary);
16164
+ parts.push("\nFull patterns: Read analysis/patterns.md\n");
16165
+ }
16166
+ }
16167
+ const analysisContent = state?.analysis || "";
16168
+ if (needsPatterns && analysisContent && analysisContent.trim()) {
16169
+ const stackMatch = analysisContent.match(/Stack[:\s]+([^\n]+)/i) || analysisContent.match(/Technology[:\s]+([^\n]+)/i);
16170
+ const stack = stackMatch ? stackMatch[1].trim() : "detected";
16171
+ parts.push(`
16172
+ ## STACK
16173
+ Stack: ${stack}
16174
+ `);
16175
+ if (!codePatternsContent) {
16176
+ parts.push(
16177
+ "Read analysis/repo-summary.md + similar files before coding. Match patterns exactly.\n"
16178
+ );
16179
+ }
16180
+ }
16181
+ if (orchestratorContext) {
15675
16182
  if (orchestratorContext.agents.length > 0) {
15676
- parts.push("### LOADED AGENTS (Project-Specific Specialists)\n\n");
15677
- for (const agent2 of orchestratorContext.agents) {
15678
- parts.push(`#### Agent: ${agent2.name} (${agent2.domain})
16183
+ parts.push("\n### LOADED AGENTS (Project-Specific Specialists)\n\n");
16184
+ for (const orcAgent of orchestratorContext.agents) {
16185
+ parts.push(`#### Agent: ${orcAgent.name} (${orcAgent.domain})
15679
16186
  `);
15680
- if (agent2.effort) parts.push(`Effort: ${agent2.effort}
16187
+ if (orcAgent.effort) parts.push(`Effort: ${orcAgent.effort}
15681
16188
  `);
15682
- if (agent2.model) parts.push(`Model: ${agent2.model}
16189
+ if (orcAgent.model) parts.push(`Model: ${orcAgent.model}
15683
16190
  `);
15684
- if (agent2.skills.length > 0) {
15685
- parts.push(`Skills: ${agent2.skills.join(", ")}
16191
+ if (orcAgent.skills.length > 0) {
16192
+ parts.push(`Skills: ${orcAgent.skills.join(", ")}
15686
16193
  `);
15687
16194
  }
15688
16195
  const truncatedContent = truncateToTokenBudget(
15689
- agent2.content,
15690
- DEFAULT_BUDGETS.agentContent
16196
+ orcAgent.content,
16197
+ this.getEffectiveBudgets().agentContent
15691
16198
  );
15692
16199
  parts.push(`\`\`\`markdown
15693
16200
  ${truncatedContent}
@@ -15707,87 +16214,94 @@ ${truncatedContent}
15707
16214
  `);
15708
16215
  const truncatedContent = truncateToTokenBudget(
15709
16216
  skill.content,
15710
- DEFAULT_BUDGETS.skillContent
16217
+ this.getEffectiveBudgets().skillContent
15711
16218
  );
15712
16219
  parts.push(`\`\`\`markdown
15713
16220
  ${truncatedContent}
15714
16221
  \`\`\`
15715
16222
 
15716
16223
  `);
15717
- }
15718
- }
15719
- if (orchestratorContext.realContext) {
15720
- const rc = orchestratorContext.realContext;
15721
- parts.push("### CODEBASE CONTEXT (Real \u2014 gathered proactively)\n\n");
15722
- parts.push(`**Git State**: Branch \`${rc.gitBranch}\` | ${rc.gitStatus}
16224
+ }
16225
+ }
16226
+ }
16227
+ const additionalModules = this.getModulesForCommand(commandName, commandContext);
16228
+ if (additionalModules.length > 0) {
16229
+ for (const moduleName of additionalModules) {
16230
+ const moduleContent = await this.loadModule(moduleName);
16231
+ if (moduleContent) {
16232
+ parts.push("\n");
16233
+ parts.push(moduleContent);
16234
+ }
16235
+ }
16236
+ }
16237
+ if (planInfo?.isPlanning) {
16238
+ parts.push(
16239
+ `
16240
+ ## PLAN MODE
16241
+ Read-only. Gather info \u2192 Analyze \u2192 Propose plan \u2192 Wait for approval.
16242
+ `
16243
+ );
16244
+ if (planInfo.allowedTools) parts.push(`Tools: ${planInfo.allowedTools.join(", ")}
16245
+ `);
16246
+ }
16247
+ if (planInfo?.requiresApproval) {
16248
+ parts.push(
16249
+ `
16250
+ ## APPROVAL REQUIRED
16251
+ Show changes, list affected files, ask for confirmation.
16252
+ `
16253
+ );
16254
+ }
16255
+ if (projectPath) {
16256
+ const groundTruth2 = {
16257
+ projectPath,
16258
+ language: orchestratorContext?.project?.ecosystem,
16259
+ techStack: orchestratorContext?.project?.conventions || [],
16260
+ domains: this.extractDomains(state),
16261
+ fileCount: context2.files?.length || context2.filteredSize || 0,
16262
+ availableAgents: orchestratorContext?.agents?.map((a) => a.name) || []
16263
+ };
16264
+ parts.push(`
16265
+ ${buildAntiHallucinationBlock(groundTruth2)}
16266
+ `);
16267
+ } else {
16268
+ parts.push(this.buildCriticalRules());
16269
+ }
16270
+ if (orchestratorContext?.realContext) {
16271
+ const rc = orchestratorContext.realContext;
16272
+ parts.push("\n### CODEBASE CONTEXT\n\n");
16273
+ parts.push(`**Git State**: Branch \`${rc.gitBranch}\` | ${rc.gitStatus}
15723
16274
 
15724
16275
  `);
15725
- if (rc.relevantFiles.length > 0) {
15726
- parts.push("**Relevant Files** (scored by task relevance):\n");
15727
- parts.push("| Score | File | Why |\n");
15728
- parts.push("|-------|------|-----|\n");
15729
- for (const f of rc.relevantFiles.slice(0, 8)) {
15730
- parts.push(`| ${f.score} | ${f.path} | ${f.reason} |
16276
+ if (rc.relevantFiles.length > 0) {
16277
+ parts.push("**Relevant Files** (scored by task relevance):\n");
16278
+ parts.push("| Score | File | Why |\n");
16279
+ parts.push("|-------|------|-----|\n");
16280
+ for (const f of rc.relevantFiles.slice(0, 8)) {
16281
+ parts.push(`| ${f.score} | ${f.path} | ${f.reason} |
15731
16282
  `);
15732
- }
15733
- parts.push("\n");
15734
16283
  }
15735
- if (rc.signatures.length > 0) {
15736
- parts.push("**Code Signatures** (top files):\n");
15737
- for (const sig of rc.signatures) {
15738
- parts.push(`\`\`\`typescript
16284
+ parts.push("\n");
16285
+ }
16286
+ if (rc.signatures.length > 0) {
16287
+ parts.push("**Code Signatures** (top files):\n");
16288
+ for (const sig of rc.signatures) {
16289
+ parts.push(`\`\`\`typescript
15739
16290
  // ${sig.path}
15740
16291
  ${sig.content}
15741
16292
  \`\`\`
15742
- `);
15743
- }
15744
- parts.push("\n");
15745
- }
15746
- if (rc.recentFiles.length > 0) {
15747
- parts.push("**Recently Changed**: ");
15748
- const recentSummary = rc.recentFiles.slice(0, 5).map((f) => `${f.path} (${f.lastChanged})`).join(", ");
15749
- parts.push(`${recentSummary}
15750
-
15751
16293
  `);
15752
16294
  }
16295
+ parts.push("\n");
15753
16296
  }
15754
- if (orchestratorContext.requiresFragmentation && orchestratorContext.subtasks) {
15755
- parts.push("### SUBTASKS (Execute in Order)\n\n");
15756
- parts.push(
15757
- "**IMPORTANT**: Focus on the CURRENT subtask. Use `p. done` when complete to advance.\n\n"
15758
- );
15759
- parts.push("| # | Domain | Description | Status |\n");
15760
- parts.push("|---|--------|-------------|--------|\n");
15761
- for (const subtask of orchestratorContext.subtasks) {
15762
- const statusIcon2 = subtask.status === "in_progress" ? "\u25B6\uFE0F **CURRENT**" : subtask.status === "completed" ? "\u2705 Done" : subtask.status === "failed" ? "\u274C Failed" : "\u23F3 Pending";
15763
- parts.push(
15764
- `| ${subtask.order} | ${subtask.domain} | ${subtask.description} | ${statusIcon2} |
15765
- `
15766
- );
15767
- }
15768
- const currentSubtask = orchestratorContext.subtasks.find((s) => s.status === "in_progress");
15769
- if (currentSubtask) {
15770
- parts.push(
15771
- `
15772
- **FOCUS ON SUBTASK #${currentSubtask.order}**: ${currentSubtask.description}
15773
- `
15774
- );
15775
- parts.push(`Agent: ${currentSubtask.agent} | Domain: ${currentSubtask.domain}
15776
- `);
15777
- if (currentSubtask.dependsOn.length > 0) {
15778
- parts.push(`Dependencies: ${currentSubtask.dependsOn.join(", ")}
16297
+ if (rc.recentFiles.length > 0) {
16298
+ parts.push("**Recently Changed**: ");
16299
+ const recentSummary = rc.recentFiles.slice(0, 5).map((f) => `${f.path} (${f.lastChanged})`).join(", ");
16300
+ parts.push(`${recentSummary}
16301
+
15779
16302
  `);
15780
- }
15781
- }
15782
- parts.push("\n");
15783
16303
  }
15784
16304
  }
15785
- const relevantState = this.filterRelevantState(state);
15786
- if (relevantState) {
15787
- parts.push("\n## PRJCT STATE (Project Management Data)\n");
15788
- parts.push(relevantState);
15789
- parts.push("\n");
15790
- }
15791
16305
  const files = context2.files || [];
15792
16306
  if (files.length > 0) {
15793
16307
  const top5 = files.slice(0, 5).join(", ");
@@ -15795,49 +16309,18 @@ ${sig.content}
15795
16309
  ## FILES: ${files.length} available. Top: ${top5}
15796
16310
  `);
15797
16311
  parts.push("Read BEFORE modifying. Use Glob/Grep to find more.\n\n");
15798
- } else if (context2.projectPath) {
15799
- parts.push(
15800
- `
15801
- ## PROJECT: ${context2.projectPath}
16312
+ } else if (projectPath) {
16313
+ parts.push(`
16314
+ ## PROJECT: ${projectPath}
15802
16315
  Read files before modifying.
15803
16316
 
15804
- `
15805
- );
15806
- }
15807
- const needsPatterns = commandContext.patterns;
15808
- const codePatternsContent = state?.codePatterns || "";
15809
- if (needsPatterns && codePatternsContent && codePatternsContent.trim()) {
15810
- const patternSummary = this.extractPatternSummary(codePatternsContent);
15811
- if (patternSummary) {
15812
- parts.push("\n## CODE PATTERNS\n");
15813
- parts.push(patternSummary);
15814
- parts.push("\nFull patterns: Read analysis/patterns.md\n");
15815
- }
15816
- }
15817
- const analysisContent = state?.analysis || "";
15818
- if (needsPatterns && analysisContent && analysisContent.trim()) {
15819
- const stackMatch = analysisContent.match(/Stack[:\s]+([^\n]+)/i) || analysisContent.match(/Technology[:\s]+([^\n]+)/i);
15820
- const stack = stackMatch ? stackMatch[1].trim() : "detected";
15821
- parts.push(`
15822
- ## STACK
15823
- Stack: ${stack}
15824
16317
  `);
15825
- if (!codePatternsContent) {
15826
- parts.push(
15827
- "Read analysis/repo-summary.md + similar files before coding. Match patterns exactly.\n"
15828
- );
15829
- }
15830
16318
  }
15831
- parts.push(this.buildCriticalRules());
15832
- const additionalModules = this.getModulesForCommand(commandName, commandContext);
15833
- if (additionalModules.length > 0) {
15834
- for (const moduleName of additionalModules) {
15835
- const moduleContent = await this.loadModule(moduleName);
15836
- if (moduleContent) {
15837
- parts.push("\n");
15838
- parts.push(moduleContent);
15839
- }
15840
- }
16319
+ const relevantState = this.filterRelevantState(state);
16320
+ if (relevantState) {
16321
+ parts.push("\n## PRJCT STATE (Project Management Data)\n");
16322
+ parts.push(relevantState);
16323
+ parts.push("\n");
15841
16324
  }
15842
16325
  if (learnedPatterns && Object.keys(learnedPatterns).some((k) => learnedPatterns[k])) {
15843
16326
  parts.push("\n## PROJECT DEFAULTS (apply automatically)\n");
@@ -15876,23 +16359,47 @@ Stack: ${stack}
15876
16359
  }
15877
16360
  }
15878
16361
  }
15879
- if (planInfo?.isPlanning) {
16362
+ parts.push("\n---\n");
16363
+ parts.push(template.content);
16364
+ if (orchestratorContext?.requiresFragmentation && orchestratorContext.subtasks) {
16365
+ parts.push("\n### SUBTASKS (Execute in Order)\n\n");
15880
16366
  parts.push(
15881
- `
15882
- ## PLAN MODE
15883
- Read-only. Gather info \u2192 Analyze \u2192 Propose plan \u2192 Wait for approval.
15884
- `
16367
+ "**IMPORTANT**: Focus on the CURRENT subtask. Use `p. done` when complete to advance.\n\n"
15885
16368
  );
15886
- if (planInfo.allowedTools) parts.push(`Tools: ${planInfo.allowedTools.join(", ")}
16369
+ parts.push("| # | Domain | Description | Status |\n");
16370
+ parts.push("|---|--------|-------------|--------|\n");
16371
+ for (const subtask of orchestratorContext.subtasks) {
16372
+ const statusIcon2 = subtask.status === "in_progress" ? "\u25B6\uFE0F **CURRENT**" : subtask.status === "completed" ? "\u2705 Done" : subtask.status === "failed" ? "\u274C Failed" : "\u23F3 Pending";
16373
+ parts.push(
16374
+ `| ${subtask.order} | ${subtask.domain} | ${subtask.description} | ${statusIcon2} |
16375
+ `
16376
+ );
16377
+ }
16378
+ const currentSubtask = orchestratorContext.subtasks.find((s) => s.status === "in_progress");
16379
+ if (currentSubtask) {
16380
+ parts.push(
16381
+ `
16382
+ **FOCUS ON SUBTASK #${currentSubtask.order}**: ${currentSubtask.description}
16383
+ `
16384
+ );
16385
+ parts.push(`Agent: ${currentSubtask.agent} | Domain: ${currentSubtask.domain}
15887
16386
  `);
16387
+ if (currentSubtask.dependsOn.length > 0) {
16388
+ parts.push(`Dependencies: ${currentSubtask.dependsOn.join(", ")}
16389
+ `);
16390
+ }
16391
+ }
16392
+ parts.push("\n");
15888
16393
  }
15889
- if (planInfo?.requiresApproval) {
15890
- parts.push(
15891
- `
15892
- ## APPROVAL REQUIRED
15893
- Show changes, list affected files, ask for confirmation.
15894
- `
15895
- );
16394
+ const schemaType = this.getSchemaTypeForCommand(commandName);
16395
+ if (schemaType) {
16396
+ const { renderSchemaForPrompt: renderSchemaForPrompt2 } = await Promise.resolve().then(() => (init_llm_output(), llm_output_exports));
16397
+ const schemaBlock = renderSchemaForPrompt2(schemaType);
16398
+ if (schemaBlock) {
16399
+ parts.push(`
16400
+ ${schemaBlock}
16401
+ `);
16402
+ }
15896
16403
  }
15897
16404
  if (commandContext.checklist) {
15898
16405
  const routing = await this.loadChecklistRouting();
@@ -15908,17 +16415,7 @@ Show changes, list affected files, ask for confirmation.
15908
16415
  parts.push("Use Read tool to load checklists you determine are relevant.\n");
15909
16416
  }
15910
16417
  }
15911
- const schemaType = this.getSchemaTypeForCommand(commandName);
15912
- if (schemaType) {
15913
- const { renderSchemaForPrompt: renderSchemaForPrompt2 } = await Promise.resolve().then(() => (init_llm_output(), llm_output_exports));
15914
- const schemaBlock = renderSchemaForPrompt2(schemaType);
15915
- if (schemaBlock) {
15916
- parts.push(`
15917
- ${schemaBlock}
15918
- `);
15919
- }
15920
- }
15921
- parts.push("\nEXECUTE: Follow flow. Use tools. Decide.\n");
16418
+ parts.push(this.buildEfficiencyDirective());
15922
16419
  return parts.join("");
15923
16420
  }
15924
16421
  /**
@@ -15927,7 +16424,8 @@ ${schemaBlock}
15927
16424
  */
15928
16425
  filterRelevantState(state) {
15929
16426
  if (!state || Object.keys(state).length === 0) return null;
15930
- const tracker = new InjectionBudgetTracker({ totalPrompt: DEFAULT_BUDGETS.stateData });
16427
+ const budgets = this.getEffectiveBudgets();
16428
+ const tracker = new InjectionBudgetTracker({ totalPrompt: budgets.stateData });
15931
16429
  const criticalFiles = ["now", "next", "context", "analysis", "codePatterns"];
15932
16430
  const relevant = [];
15933
16431
  for (const [key, content] of Object.entries(state)) {
@@ -15992,7 +16490,9 @@ ${antiPatterns}`);
15992
16490
  return schemaMap[commandName] ?? null;
15993
16491
  }
15994
16492
  /**
15995
- * Build critical anti-hallucination rules section
16493
+ * Build critical anti-hallucination rules section.
16494
+ * Used as fallback when full anti-hallucination block can't be built
16495
+ * (e.g., no project path available).
15996
16496
  */
15997
16497
  buildCriticalRules() {
15998
16498
  const fileCount = this._currentContext?.files?.length || this._currentContext?.filteredSize || 0;
@@ -16006,6 +16506,41 @@ ${antiPatterns}`);
16006
16506
  Context: ${fileCount} files available. Read what you need.
16007
16507
  `;
16008
16508
  }
16509
+ /**
16510
+ * Build token efficiency directive (PRJ-301).
16511
+ * Instructs the LLM to be concise and avoid wasting tokens on preamble.
16512
+ */
16513
+ buildEfficiencyDirective() {
16514
+ return `
16515
+ ## OUTPUT RULES
16516
+ - Be concise. Maximum 4 lines of explanation unless asked for detail.
16517
+ - No preamble ("Here is...", "I'll help you...", "Based on...").
16518
+ - No postamble (summaries, next steps suggestions unless asked).
16519
+ - When executing code: show the code, not the explanation.
16520
+ - Prefer structured output (JSON) over free text when applicable.
16521
+
16522
+ EXECUTE: Follow flow. Use tools. Decide.
16523
+ `;
16524
+ }
16525
+ /**
16526
+ * Extract domain flags from state data.
16527
+ * Returns the domains object if available in the raw state.
16528
+ */
16529
+ extractDomains(state) {
16530
+ if (!state) return void 0;
16531
+ const raw = state;
16532
+ if (raw.domains && typeof raw.domains === "object") {
16533
+ const d = raw.domains;
16534
+ return {
16535
+ hasFrontend: d.hasFrontend ?? false,
16536
+ hasBackend: d.hasBackend ?? false,
16537
+ hasDatabase: d.hasDatabase ?? false,
16538
+ hasTesting: d.hasTesting ?? false,
16539
+ hasDocker: d.hasDocker ?? false
16540
+ };
16541
+ }
16542
+ return void 0;
16543
+ }
16009
16544
  };
16010
16545
  promptBuilder = new PromptBuilder();
16011
16546
  prompt_builder_default = promptBuilder;
@@ -16302,7 +16837,7 @@ var init_tool_registry = __esm({
16302
16837
 
16303
16838
  // core/agentic/command-executor.ts
16304
16839
  import fs35 from "node:fs/promises";
16305
- import os10 from "node:os";
16840
+ import os11 from "node:os";
16306
16841
  import path33 from "node:path";
16307
16842
  async function signalStart(commandName) {
16308
16843
  try {
@@ -16341,7 +16876,7 @@ var init_command_executor = __esm({
16341
16876
  init_template_executor();
16342
16877
  init_template_loader();
16343
16878
  init_tool_registry();
16344
- RUNNING_FILE = path33.join(os10.homedir(), ".prjct-cli", ".running");
16879
+ RUNNING_FILE = path33.join(os11.homedir(), ".prjct-cli", ".running");
16345
16880
  __name(signalStart, "signalStart");
16346
16881
  __name(signalEnd, "signalEnd");
16347
16882
  CommandExecutor = class {
@@ -16652,7 +17187,7 @@ var init_command_executor = __esm({
16652
17187
  // core/infrastructure/update-checker.ts
16653
17188
  import fs36 from "node:fs/promises";
16654
17189
  import https from "node:https";
16655
- import os11 from "node:os";
17190
+ import os12 from "node:os";
16656
17191
  import path34 from "node:path";
16657
17192
  import chalk8 from "chalk";
16658
17193
  var UpdateChecker, update_checker_default;
@@ -16671,7 +17206,7 @@ var init_update_checker = __esm({
16671
17206
  checkInterval;
16672
17207
  constructor() {
16673
17208
  this.packageName = "prjct-cli";
16674
- this.cacheDir = path34.join(os11.homedir(), ".prjct-cli", "config");
17209
+ this.cacheDir = path34.join(os12.homedir(), ".prjct-cli", "config");
16675
17210
  this.cacheFile = path34.join(this.cacheDir, "update-cache.json");
16676
17211
  this.checkInterval = 24 * 60 * 60 * 1e3;
16677
17212
  }
@@ -19456,10 +19991,10 @@ var init_onboarding = __esm({
19456
19991
  async detectInstalledAgents() {
19457
19992
  const fs56 = await import("node:fs/promises");
19458
19993
  const path68 = await import("node:path");
19459
- const os21 = await import("node:os");
19994
+ const os22 = await import("node:os");
19460
19995
  const agents = [];
19461
19996
  try {
19462
- await fs56.access(path68.join(os21.homedir(), ".claude"));
19997
+ await fs56.access(path68.join(os22.homedir(), ".claude"));
19463
19998
  agents.push("claude");
19464
19999
  } catch {
19465
20000
  }
@@ -19479,7 +20014,7 @@ var init_onboarding = __esm({
19479
20014
  } catch {
19480
20015
  }
19481
20016
  try {
19482
- await fs56.access(path68.join(os21.homedir(), ".gemini"));
20017
+ await fs56.access(path68.join(os22.homedir(), ".gemini"));
19483
20018
  agents.push("gemini");
19484
20019
  } catch {
19485
20020
  }
@@ -20398,6 +20933,7 @@ var init_analysis2 = __esm({
20398
20933
  init_metrics();
20399
20934
  init_services();
20400
20935
  init_diff_generator();
20936
+ init_analysis_storage();
20401
20937
  init_metrics_storage();
20402
20938
  init_fs();
20403
20939
  init_next_steps();
@@ -20998,22 +21534,83 @@ ${formatFullDiff(diff)}`);
20998
21534
  const checker = createStalenessChecker(projectPath);
20999
21535
  const status = await checker.check(projectId);
21000
21536
  const sessionInfo = await checker.getSessionInfo(projectId);
21537
+ const analysisStatus = await analysisStorage.getStatus(projectId);
21001
21538
  if (options.json) {
21002
21539
  console.log(
21003
21540
  JSON.stringify({
21004
21541
  success: true,
21005
21542
  ...status,
21006
- session: sessionInfo
21543
+ session: sessionInfo,
21544
+ analysis: analysisStatus
21007
21545
  })
21008
21546
  );
21009
- return { success: true, data: { ...status, session: sessionInfo } };
21547
+ return {
21548
+ success: true,
21549
+ data: { ...status, session: sessionInfo, analysis: analysisStatus }
21550
+ };
21010
21551
  }
21011
21552
  console.log("");
21012
21553
  console.log(checker.formatStatus(status));
21013
21554
  console.log("");
21014
21555
  console.log(checker.formatSessionInfo(sessionInfo));
21556
+ if (analysisStatus.hasSealed || analysisStatus.hasDraft) {
21557
+ console.log("");
21558
+ console.log("Analysis:");
21559
+ if (analysisStatus.hasSealed) {
21560
+ console.log(` Sealed: ${analysisStatus.sealedCommit} (${analysisStatus.sealedAt})`);
21561
+ }
21562
+ if (analysisStatus.hasDraft) {
21563
+ console.log(` Draft: ${analysisStatus.draftCommit} (pending seal)`);
21564
+ }
21565
+ }
21566
+ console.log("");
21567
+ return { success: true, data: { ...status, session: sessionInfo, analysis: analysisStatus } };
21568
+ } catch (error) {
21569
+ const errMsg = getErrorMessage2(error);
21570
+ if (options.json) {
21571
+ console.log(JSON.stringify({ success: false, error: errMsg }));
21572
+ } else {
21573
+ output_default.fail(errMsg);
21574
+ }
21575
+ return { success: false, error: errMsg };
21576
+ }
21577
+ }
21578
+ /**
21579
+ * prjct seal - Seal the current draft analysis (PRJ-263)
21580
+ *
21581
+ * Locks the current draft with a SHA-256 signature.
21582
+ * Only sealed analysis feeds task context.
21583
+ */
21584
+ async seal(projectPath = process.cwd(), options = {}) {
21585
+ try {
21586
+ const initResult = await this.ensureProjectInit(projectPath);
21587
+ if (!initResult.success) return initResult;
21588
+ const projectId = await config_manager_default.getProjectId(projectPath);
21589
+ if (!projectId) {
21590
+ if (options.json) {
21591
+ console.log(JSON.stringify({ success: false, error: "No project ID found" }));
21592
+ }
21593
+ return { success: false, error: "No project ID found" };
21594
+ }
21595
+ const result = await analysisStorage.seal(projectId);
21596
+ if (options.json) {
21597
+ console.log(
21598
+ JSON.stringify({
21599
+ success: result.success,
21600
+ signature: result.signature,
21601
+ error: result.error
21602
+ })
21603
+ );
21604
+ return { success: result.success, error: result.error };
21605
+ }
21606
+ if (!result.success) {
21607
+ output_default.fail(result.error || "Seal failed");
21608
+ return { success: false, error: result.error };
21609
+ }
21610
+ output_default.done("Analysis sealed");
21611
+ console.log(` Signature: ${result.signature?.substring(0, 16)}...`);
21015
21612
  console.log("");
21016
- return { success: true, data: { ...status, session: sessionInfo } };
21613
+ return { success: true, data: { signature: result.signature } };
21017
21614
  } catch (error) {
21018
21615
  const errMsg = getErrorMessage2(error);
21019
21616
  if (options.json) {
@@ -21024,6 +21621,35 @@ ${formatFullDiff(diff)}`);
21024
21621
  return { success: false, error: errMsg };
21025
21622
  }
21026
21623
  }
21624
+ /**
21625
+ * prjct verify - Verify integrity of sealed analysis (PRJ-263)
21626
+ */
21627
+ async verify(projectPath = process.cwd(), options = {}) {
21628
+ try {
21629
+ const initResult = await this.ensureProjectInit(projectPath);
21630
+ if (!initResult.success) return initResult;
21631
+ const projectId = await config_manager_default.getProjectId(projectPath);
21632
+ if (!projectId) {
21633
+ return { success: false, error: "No project ID found" };
21634
+ }
21635
+ const result = await analysisStorage.verify(projectId);
21636
+ if (options.json) {
21637
+ console.log(JSON.stringify(result));
21638
+ return { success: result.valid };
21639
+ }
21640
+ if (result.valid) {
21641
+ output_default.done(result.message);
21642
+ } else {
21643
+ output_default.fail(result.message);
21644
+ }
21645
+ console.log("");
21646
+ return { success: result.valid, data: result };
21647
+ } catch (error) {
21648
+ const errMsg = getErrorMessage2(error);
21649
+ output_default.fail(errMsg);
21650
+ return { success: false, error: errMsg };
21651
+ }
21652
+ }
21027
21653
  /**
21028
21654
  * Get session activity stats from today's events
21029
21655
  * @see PRJ-89
@@ -22363,7 +22989,7 @@ var init_formatters = __esm({
22363
22989
 
22364
22990
  // core/ai-tools/registry.ts
22365
22991
  import { exec as exec13 } from "node:child_process";
22366
- import os12 from "node:os";
22992
+ import os13 from "node:os";
22367
22993
  import path45 from "node:path";
22368
22994
  import { promisify as promisify14 } from "node:util";
22369
22995
  function getAIToolConfig(id) {
@@ -22391,7 +23017,7 @@ async function detectInstalledTools(repoPath = process.cwd()) {
22391
23017
  if (await commandExists("windsurf") || await fileExists(path45.join(repoPath, ".windsurf"))) {
22392
23018
  detected.push("windsurf");
22393
23019
  }
22394
- if (await fileExists(path45.join(repoPath, ".continue")) || await fileExists(path45.join(os12.homedir(), ".continue"))) {
23020
+ if (await fileExists(path45.join(repoPath, ".continue")) || await fileExists(path45.join(os13.homedir(), ".continue"))) {
22395
23021
  detected.push("continue");
22396
23022
  }
22397
23023
  return detected;
@@ -23011,10 +23637,10 @@ var init_local_state_generator = __esm({
23011
23637
 
23012
23638
  // core/services/skill-lock.ts
23013
23639
  import fs46 from "node:fs/promises";
23014
- import os13 from "node:os";
23640
+ import os14 from "node:os";
23015
23641
  import path49 from "node:path";
23016
23642
  function getLockFilePath() {
23017
- return path49.join(os13.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
23643
+ return path49.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
23018
23644
  }
23019
23645
  function createEmptyLockFile() {
23020
23646
  return {
@@ -23089,13 +23715,13 @@ var init_skill_lock = __esm({
23089
23715
  // core/services/skill-installer.ts
23090
23716
  import { exec as execCallback7 } from "node:child_process";
23091
23717
  import fs47 from "node:fs/promises";
23092
- import os14 from "node:os";
23718
+ import os15 from "node:os";
23093
23719
  import path50 from "node:path";
23094
23720
  import { promisify as promisify15 } from "node:util";
23095
23721
  import { glob } from "glob";
23096
23722
  function parseSource(source) {
23097
23723
  if (source.startsWith("./") || source.startsWith("/") || source.startsWith("~")) {
23098
- const resolvedPath = source.startsWith("~") ? path50.join(os14.homedir(), source.slice(1)) : path50.resolve(source);
23724
+ const resolvedPath = source.startsWith("~") ? path50.join(os15.homedir(), source.slice(1)) : path50.resolve(source);
23099
23725
  return {
23100
23726
  type: "local",
23101
23727
  localPath: resolvedPath,
@@ -23184,7 +23810,7 @@ ${prjctBlock.join("\n")}
23184
23810
  ${content}`;
23185
23811
  }
23186
23812
  function getInstallDir() {
23187
- return path50.join(os14.homedir(), ".claude", "skills");
23813
+ return path50.join(os15.homedir(), ".claude", "skills");
23188
23814
  }
23189
23815
  async function installSkillFile(sourcePath, name, source, sha) {
23190
23816
  const installDir = getInstallDir();
@@ -23210,7 +23836,7 @@ async function installFromGitHub(source) {
23210
23836
  );
23211
23837
  return result;
23212
23838
  }
23213
- const tmpDir = path50.join(os14.tmpdir(), `prjct-skill-${Date.now()}`);
23839
+ const tmpDir = path50.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
23214
23840
  try {
23215
23841
  const cloneUrl = `https://github.com/${source.owner}/${source.repo}.git`;
23216
23842
  await exec14(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
@@ -23747,7 +24373,7 @@ var init_sync_verifier = __esm({
23747
24373
  // core/services/sync-service.ts
23748
24374
  import { exec as exec16 } from "node:child_process";
23749
24375
  import fs50 from "node:fs/promises";
23750
- import os15 from "node:os";
24376
+ import os16 from "node:os";
23751
24377
  import path53 from "node:path";
23752
24378
  import { promisify as promisify17 } from "node:util";
23753
24379
  var execAsync11, SyncService, syncService;
@@ -23759,6 +24385,7 @@ var init_sync_service = __esm({
23759
24385
  init_command_installer();
23760
24386
  init_config_manager();
23761
24387
  init_path_manager();
24388
+ init_analysis_storage();
23762
24389
  init_metrics_storage();
23763
24390
  init_citations();
23764
24391
  init_date_helper();
@@ -23863,7 +24490,8 @@ var init_sync_service = __esm({
23863
24490
  await Promise.all([
23864
24491
  this.updateProjectJson(git, stats),
23865
24492
  this.updateStateJson(stats, stack),
23866
- this.logToMemory(git, stats)
24493
+ this.logToMemory(git, stats),
24494
+ this.saveDraftAnalysis(git, stats, stack)
23867
24495
  ]);
23868
24496
  const duration = Date.now() - startTime;
23869
24497
  const syncMetrics = await this.recordSyncMetrics(stats, contextFiles, agents, duration);
@@ -24384,7 +25012,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
24384
25012
  }
24385
25013
  }
24386
25014
  if (packagesToInstall.length === 0) return results;
24387
- const skillsDir = path53.join(os15.homedir(), ".claude", "skills");
25015
+ const skillsDir = path53.join(os16.homedir(), ".claude", "skills");
24388
25016
  for (const { pkg, agent } of packagesToInstall) {
24389
25017
  const skillName = pkg.split("/").pop() || pkg;
24390
25018
  const subdirPath = path53.join(skillsDir, skillName, "SKILL.md");
@@ -24598,6 +25226,32 @@ You are the ${name} expert for this project. Apply best practices for the detect
24598
25226
  };
24599
25227
  }
24600
25228
  // ==========================================================================
25229
+ // DRAFT ANALYSIS (PRJ-263)
25230
+ // ==========================================================================
25231
+ /**
25232
+ * Save sync results as a draft analysis.
25233
+ * Preserves existing sealed analysis — only the draft is overwritten.
25234
+ */
25235
+ async saveDraftAnalysis(git, stats, _stack) {
25236
+ try {
25237
+ const commitHash = git.recentCommits[0]?.hash || null;
25238
+ await analysisStorage.saveDraft(this.projectId, {
25239
+ projectId: this.projectId,
25240
+ languages: stats.languages,
25241
+ frameworks: stats.frameworks,
25242
+ configFiles: [],
25243
+ fileCount: stats.fileCount,
25244
+ patterns: [],
25245
+ antiPatterns: [],
25246
+ analyzedAt: getTimestamp(),
25247
+ status: "draft",
25248
+ commitHash: commitHash ?? void 0
25249
+ });
25250
+ } catch (error) {
25251
+ logger_default.debug("Failed to save draft analysis (non-critical)", { error: getErrorMessage(error) });
25252
+ }
25253
+ }
25254
+ // ==========================================================================
24601
25255
  // HELPERS
24602
25256
  // ==========================================================================
24603
25257
  async fileExists(filename) {
@@ -24774,7 +25428,7 @@ __export(uninstall_exports, {
24774
25428
  });
24775
25429
  import { execSync as execSync3 } from "node:child_process";
24776
25430
  import fs51 from "node:fs/promises";
24777
- import os16 from "node:os";
25431
+ import os17 from "node:os";
24778
25432
  import path54 from "node:path";
24779
25433
  import readline2 from "node:readline";
24780
25434
  import chalk12 from "chalk";
@@ -24942,7 +25596,7 @@ async function removePrjctSection(filePath) {
24942
25596
  }
24943
25597
  }
24944
25598
  async function createBackup2() {
24945
- const homeDir = os16.homedir();
25599
+ const homeDir = os17.homedir();
24946
25600
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
24947
25601
  const backupDir = path54.join(homeDir, `.prjct-backup-${timestamp}`);
24948
25602
  try {
@@ -25607,6 +26261,35 @@ var init_command_data = __esm({
25607
26261
  "Configurable staleness thresholds"
25608
26262
  ]
25609
26263
  },
26264
+ {
26265
+ name: "seal",
26266
+ group: "core",
26267
+ description: "Seal the current draft analysis with a commit-hash signature",
26268
+ usage: { claude: "/p:seal", terminal: "prjct seal" },
26269
+ params: "[--json]",
26270
+ implemented: true,
26271
+ hasTemplate: false,
26272
+ requiresProject: true,
26273
+ features: [
26274
+ "Locks draft analysis with SHA-256 signature",
26275
+ "Only sealed analysis feeds task context",
26276
+ "Detects staleness when HEAD moves past sealed commit"
26277
+ ]
26278
+ },
26279
+ {
26280
+ name: "verify",
26281
+ group: "core",
26282
+ description: "Verify integrity of sealed analysis",
26283
+ usage: { claude: "/p:verify", terminal: "prjct verify" },
26284
+ params: "[--json]",
26285
+ implemented: true,
26286
+ hasTemplate: false,
26287
+ requiresProject: true,
26288
+ features: [
26289
+ "Recomputes SHA-256 signature and compares",
26290
+ "Detects if sealed analysis was modified"
26291
+ ]
26292
+ },
25610
26293
  {
25611
26294
  name: "help",
25612
26295
  group: "core",
@@ -26068,7 +26751,7 @@ __export(setup_exports, {
26068
26751
  });
26069
26752
  import { execSync as execSync4 } from "node:child_process";
26070
26753
  import fs52 from "node:fs/promises";
26071
- import os17 from "node:os";
26754
+ import os18 from "node:os";
26072
26755
  import path56 from "node:path";
26073
26756
  import chalk15 from "chalk";
26074
26757
  async function installAICLI(provider) {
@@ -26208,7 +26891,7 @@ async function run() {
26208
26891
  }
26209
26892
  async function installGeminiRouter() {
26210
26893
  try {
26211
- const geminiCommandsDir = path56.join(os17.homedir(), ".gemini", "commands");
26894
+ const geminiCommandsDir = path56.join(os18.homedir(), ".gemini", "commands");
26212
26895
  const routerSource = path56.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
26213
26896
  const routerDest = path56.join(geminiCommandsDir, "p.toml");
26214
26897
  await fs52.mkdir(geminiCommandsDir, { recursive: true });
@@ -26224,7 +26907,7 @@ async function installGeminiRouter() {
26224
26907
  }
26225
26908
  async function installGeminiGlobalConfig() {
26226
26909
  try {
26227
- const geminiDir = path56.join(os17.homedir(), ".gemini");
26910
+ const geminiDir = path56.join(os18.homedir(), ".gemini");
26228
26911
  const globalConfigPath = path56.join(geminiDir, "GEMINI.md");
26229
26912
  const templatePath = path56.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
26230
26913
  await fs52.mkdir(geminiDir, { recursive: true });
@@ -26273,7 +26956,7 @@ ${templateContent}`;
26273
26956
  }
26274
26957
  async function installAntigravitySkill() {
26275
26958
  try {
26276
- const antigravitySkillsDir = path56.join(os17.homedir(), ".gemini", "antigravity", "skills");
26959
+ const antigravitySkillsDir = path56.join(os18.homedir(), ".gemini", "antigravity", "skills");
26277
26960
  const prjctSkillDir = path56.join(antigravitySkillsDir, "prjct");
26278
26961
  const skillMdPath = path56.join(prjctSkillDir, "SKILL.md");
26279
26962
  const templatePath = path56.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
@@ -26467,7 +27150,7 @@ async function needsWindsurfRegeneration(projectRoot) {
26467
27150
  }
26468
27151
  async function migrateProjectsCliVersion() {
26469
27152
  try {
26470
- const projectsDir = path56.join(os17.homedir(), ".prjct-cli", "projects");
27153
+ const projectsDir = path56.join(os18.homedir(), ".prjct-cli", "projects");
26471
27154
  if (!await fileExists(projectsDir)) {
26472
27155
  return;
26473
27156
  }
@@ -26517,10 +27200,10 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
26517
27200
  }
26518
27201
  async function installStatusLine() {
26519
27202
  try {
26520
- const claudeDir = path56.join(os17.homedir(), ".claude");
27203
+ const claudeDir = path56.join(os18.homedir(), ".claude");
26521
27204
  const settingsPath = path56.join(claudeDir, "settings.json");
26522
27205
  const claudeStatusLinePath = path56.join(claudeDir, "prjct-statusline.sh");
26523
- const prjctStatusLineDir = path56.join(os17.homedir(), ".prjct-cli", "statusline");
27206
+ const prjctStatusLineDir = path56.join(os18.homedir(), ".prjct-cli", "statusline");
26524
27207
  const prjctStatusLinePath = path56.join(prjctStatusLineDir, "statusline.sh");
26525
27208
  const prjctThemesDir = path56.join(prjctStatusLineDir, "themes");
26526
27209
  const prjctLibDir = path56.join(prjctStatusLineDir, "lib");
@@ -26627,7 +27310,7 @@ echo "prjct"
26627
27310
  }
26628
27311
  async function installContext7MCP() {
26629
27312
  try {
26630
- const claudeDir = path56.join(os17.homedir(), ".claude");
27313
+ const claudeDir = path56.join(os18.homedir(), ".claude");
26631
27314
  const mcpConfigPath = path56.join(claudeDir, "mcp.json");
26632
27315
  if (!await fileExists(claudeDir)) {
26633
27316
  await fs52.mkdir(claudeDir, { recursive: true });
@@ -29694,10 +30377,10 @@ var init_linear = __esm({
29694
30377
 
29695
30378
  // core/utils/project-credentials.ts
29696
30379
  import fs55 from "node:fs/promises";
29697
- import os18 from "node:os";
30380
+ import os19 from "node:os";
29698
30381
  import path65 from "node:path";
29699
30382
  function getCredentialsPath(projectId) {
29700
- return path65.join(os18.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
30383
+ return path65.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
29701
30384
  }
29702
30385
  async function getProjectCredentials(projectId) {
29703
30386
  const credPath = getCredentialsPath(projectId);
@@ -30235,6 +30918,12 @@ var init_commands = __esm({
30235
30918
  async status(projectPath = process.cwd(), options = {}) {
30236
30919
  return this.analysis.status(projectPath, options);
30237
30920
  }
30921
+ async seal(projectPath = process.cwd(), options = {}) {
30922
+ return this.analysis.seal(projectPath, options);
30923
+ }
30924
+ async verify(projectPath = process.cwd(), options = {}) {
30925
+ return this.analysis.verify(projectPath, options);
30926
+ }
30238
30927
  // ========== Context Commands ==========
30239
30928
  async context(input = null, projectPath = process.cwd()) {
30240
30929
  return this.contextCmds.context(input, projectPath);
@@ -30306,6 +30995,8 @@ function registerAllCommands() {
30306
30995
  commandRegistry.registerMethod("sync", analysis, "sync", getMeta("sync"));
30307
30996
  commandRegistry.registerMethod("stats", analysis, "stats", getMeta("stats"));
30308
30997
  commandRegistry.registerMethod("status", analysis, "status", getMeta("status"));
30998
+ commandRegistry.registerMethod("seal", analysis, "seal", getMeta("seal"));
30999
+ commandRegistry.registerMethod("verify", analysis, "verify", getMeta("verify"));
30309
31000
  commandRegistry.registerMethod("start", setup, "start", getMeta("start"));
30310
31001
  commandRegistry.registerMethod("setup", setup, "setup", getMeta("setup"));
30311
31002
  commandRegistry.registerMethod("uninstall", uninstallCmd, "uninstall", getMeta("uninstall"));
@@ -30359,7 +31050,7 @@ var require_package = __commonJS({
30359
31050
  "package.json"(exports, module) {
30360
31051
  module.exports = {
30361
31052
  name: "prjct-cli",
30362
- version: "1.9.0",
31053
+ version: "1.11.0",
30363
31054
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
30364
31055
  main: "core/index.ts",
30365
31056
  bin: {
@@ -30465,7 +31156,7 @@ var require_package = __commonJS({
30465
31156
 
30466
31157
  // core/index.ts
30467
31158
  var core_exports = {};
30468
- import os19 from "node:os";
31159
+ import os20 from "node:os";
30469
31160
  import path66 from "node:path";
30470
31161
  import chalk19 from "chalk";
30471
31162
  async function main() {
@@ -30572,6 +31263,8 @@ async function main() {
30572
31263
  json: options.json === true,
30573
31264
  package: options.package ? String(options.package) : void 0
30574
31265
  }), "sync"),
31266
+ seal: /* @__PURE__ */ __name(() => commands.seal(process.cwd(), { json: options.json === true }), "seal"),
31267
+ verify: /* @__PURE__ */ __name(() => commands.verify(process.cwd(), { json: options.json === true }), "verify"),
30575
31268
  start: /* @__PURE__ */ __name(() => commands.start(), "start"),
30576
31269
  // Context (for Claude templates)
30577
31270
  context: /* @__PURE__ */ __name((p) => commands.context(p), "context")
@@ -30676,8 +31369,8 @@ function parseCommandArgs(_cmd, rawArgs) {
30676
31369
  }
30677
31370
  async function displayVersion(version) {
30678
31371
  const detection = await detectAllProviders();
30679
- const claudeCommandPath = path66.join(os19.homedir(), ".claude", "commands", "p.md");
30680
- const geminiCommandPath = path66.join(os19.homedir(), ".gemini", "commands", "p.toml");
31372
+ const claudeCommandPath = path66.join(os20.homedir(), ".claude", "commands", "p.md");
31373
+ const geminiCommandPath = path66.join(os20.homedir(), ".gemini", "commands", "p.toml");
30681
31374
  const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
30682
31375
  fileExists(claudeCommandPath),
30683
31376
  fileExists(geminiCommandPath),
@@ -30820,7 +31513,7 @@ var init_core = __esm({
30820
31513
  init_ai_provider();
30821
31514
  init_config_manager();
30822
31515
  init_editors_config();
30823
- import os20 from "node:os";
31516
+ import os21 from "node:os";
30824
31517
  import path67 from "node:path";
30825
31518
  import chalk20 from "chalk";
30826
31519
 
@@ -31639,7 +32332,7 @@ init_provider_cache();
31639
32332
  init_version();
31640
32333
  globalThis.__perfStartNs = process.hrtime.bigint();
31641
32334
  async function checkRoutersInstalled() {
31642
- const home = os20.homedir();
32335
+ const home = os21.homedir();
31643
32336
  const detection = await detectAllProviders();
31644
32337
  if (detection.claude.installed) {
31645
32338
  const claudeRouter = path67.join(home, ".claude", "commands", "p.md");
@@ -31806,7 +32499,7 @@ if (args[0] === "start" || args[0] === "setup") {
31806
32499
  process.exitCode = 0;
31807
32500
  } else if (args[0] === "version" || args[0] === "-v" || args[0] === "--version") {
31808
32501
  const detection = await detectAllProviders(isRefresh);
31809
- const home = os20.homedir();
32502
+ const home = os21.homedir();
31810
32503
  const cwd = process.cwd();
31811
32504
  const [
31812
32505
  claudeConfigured,
@@ -31860,7 +32553,7 @@ ${chalk20.dim("Run 'prjct init' to configure (Cursor/Windsurf IDE)")}
31860
32553
  ${chalk20.cyan("https://prjct.app")}
31861
32554
  `);
31862
32555
  } else {
31863
- const configPath = path67.join(os20.homedir(), ".prjct-cli", "config", "installed-editors.json");
32556
+ const configPath = path67.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
31864
32557
  const routersInstalled = await checkRoutersInstalled();
31865
32558
  if (!await fileExists(configPath) || !routersInstalled) {
31866
32559
  console.log(`