@wrongstack/requirement-intake 1.0.24 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -17,6 +17,6 @@ export { type IntakeCreateResult, type IntakeListFilter, type IntakeSubmitResult
17
17
  export { type IntakeIndexEntry, newIntakeId, RequirementIntakeStore, type RequirementIntakeStoreOptions, type StoreCreateResult, type StoreUpdateOptions, } from './store.js';
18
18
  export { assertSuggestionString, type LlmSuggestionGenerator, type LlmSuggestionOutput, type LlmSuggestionRequest, llmSuggestionOutputSchema, type NormalizedLlmSuggestion, toProposals, validateLlmSuggestionOutput, } from './suggestions.js';
19
19
  export { type AddAnswerInput, type AttachResourceInput, type ChangeHistoryEntry, type CreateIntakeInput, INTAKE_EVENT_NAMES, type IntakeActor, type IntakeAnswer, type IntakeAttachment, type IntakeAttachmentInput, type IntakeContext, type IntakeEvent, type IntakeEventName, type IntakeQuestion, type IntakeQuestionTemplateInput, type LlmSuggestionProposal, type RelatedResource, type RelatedResourceInput, type RequirementIntakeRecord, type UpdateIntakeInput, } from './types.js';
20
- export { answerInputSchema, attachmentInputSchema, attachResourceInputSchema, createIntakeSchema, deterministicSummary, deterministicTitle, isBlank, metadataSchema, normalizeRequestType, parseWithIssues, prioritySchema, questionTemplateInputSchema, relatedResourceInputSchema, requestTypeSchema, updateIntakeSchema, validateAnswerInput, validateAttachmentInput, validateAttachResourceInput, validateCreateInput, validateFieldSource, validateQuestionTemplateInput, validateRelatedResourceInput, validateUpdateInput, } from './validation.js';
20
+ export { answerInputSchema, attachmentInputSchema, attachResourceInputSchema, createIntakeSchema, deterministicSummary, deterministicTitle, isBlank, metadataSchema, normalizeRequestType, parseWithIssues, prioritySchema, questionTemplateInputSchema, relatedResourceInputSchema, requestTypeSchema, updateIntakeSchema, validateAnswerInput, validateAttachmentInput, validateAttachResourceInput, validateCreateInput, validateFieldSource, validateQuestionTemplateInput, validateRelatedResourceInput, validateUpdateInput, vibeProtocolStateSchema, } from './validation.js';
21
21
  export { deriveVibeState, hasVibeTag, stripVibeTag, VIBE_TAG_REGEX, type VibeProtocolStage, type VibeProtocolState, } from './vibe.js';
22
22
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -413,6 +413,19 @@ var IDEMPOTENCY_PATH = "_idempotency.json";
413
413
  function hashIdempotencyKey(key) {
414
414
  return createHash("sha256").update(key, "utf8").digest("hex");
415
415
  }
416
+ function indexEntryFor(record) {
417
+ return {
418
+ id: record.id,
419
+ projectId: record.projectId,
420
+ title: record.title,
421
+ status: record.status,
422
+ requestType: record.requestType,
423
+ priority: record.priority,
424
+ requestedBy: record.requestedBy,
425
+ updatedAt: record.updatedAt,
426
+ createdAt: record.createdAt
427
+ };
428
+ }
416
429
  var RequirementIntakeStore = class {
417
430
  baseDir;
418
431
  indexPath;
@@ -566,26 +579,37 @@ var RequirementIntakeStore = class {
566
579
  const raw = await fsp.readFile(this.indexPath, "utf8");
567
580
  const parsed = JSON.parse(raw);
568
581
  if (parsed?.version === 1 && Array.isArray(parsed.entries)) return parsed;
569
- } catch {
582
+ } catch (error) {
583
+ if (error.code !== "ENOENT" && !(error instanceof SyntaxError)) {
584
+ throw error;
585
+ }
570
586
  }
571
- return { version: 1, entries: [] };
587
+ let files;
588
+ try {
589
+ files = await fsp.readdir(this.baseDir);
590
+ } catch (error) {
591
+ if (error.code === "ENOENT") return { version: 1, entries: [] };
592
+ throw error;
593
+ }
594
+ const entries = [];
595
+ for (const file of files) {
596
+ if (file === INDEX_PATH || file === IDEMPOTENCY_PATH || !file.endsWith(".json")) continue;
597
+ const id = file.slice(0, -".json".length);
598
+ if (!/^[A-Za-z0-9_-]{1,128}$/.test(id)) continue;
599
+ const record = JSON.parse(
600
+ await fsp.readFile(path.join(this.baseDir, file), "utf8")
601
+ );
602
+ if (record?.id !== id) throw new Error(`Invalid requirement intake record: ${file}`);
603
+ entries.push(indexEntryFor(record));
604
+ }
605
+ return { version: 1, entries };
572
606
  }
573
607
  async updateIndexFor(record) {
574
608
  return withFileLock(
575
609
  this.indexPath,
576
610
  async () => {
577
611
  const index = await this.readIndex();
578
- const entry = {
579
- id: record.id,
580
- projectId: record.projectId,
581
- title: record.title,
582
- status: record.status,
583
- requestType: record.requestType,
584
- priority: record.priority,
585
- requestedBy: record.requestedBy,
586
- updatedAt: record.updatedAt,
587
- createdAt: record.createdAt
588
- };
612
+ const entry = indexEntryFor(record);
589
613
  const position = index.entries.findIndex((candidate) => candidate.id === record.id);
590
614
  if (position >= 0) {
591
615
  index.entries[position] = entry;
@@ -691,6 +715,15 @@ var optionalString = (max) => z.string().max(max).optional();
691
715
  var optionalStringArray = z.array(z.string().trim().min(1).max(MAX_STRING_FIELD_LENGTH)).max(MAX_ARRAY_ITEMS).optional();
692
716
  var optionalAttachmentArray = z.array(attachmentInputSchema).max(MAX_ATTACHMENTS).optional();
693
717
  var optionalRelatedResourceArray = z.array(relatedResourceInputSchema).max(MAX_RELATED_RESOURCES).optional();
718
+ var vibeProtocolStateSchema = z.object({
719
+ isVibeMode: z.literal(true),
720
+ detectedAt: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
721
+ stage: z.enum(["synthesizer", "coder", "auditor", "passed"]),
722
+ synthesizedSpec: z.string().max(MAX_ANSWER_LENGTH).optional(),
723
+ coderContract: z.string().max(MAX_ANSWER_LENGTH).optional(),
724
+ auditVerdict: z.enum(["PASS", "REJECT"]).optional(),
725
+ auditNotes: z.array(z.string().max(MAX_STRING_FIELD_LENGTH)).max(MAX_ARRAY_ITEMS).optional()
726
+ }).strict();
694
727
  var createIntakeSchema = z.object({
695
728
  projectId: idSchema,
696
729
  originalRequest: nonBlankString(MAX_REQUEST_LENGTH, "originalRequest"),
@@ -711,7 +744,7 @@ var createIntakeSchema = z.object({
711
744
  knownFields: z.array(z.string().trim().min(1).max(64)).max(MAX_ARRAY_ITEMS).optional(),
712
745
  questions: z.array(questionTemplateInputSchema).max(50).optional(),
713
746
  isVibeMode: z.boolean().optional(),
714
- vibeProtocol: z.any().optional()
747
+ vibeProtocol: vibeProtocolStateSchema.optional()
715
748
  }).strict();
716
749
  var updateIntakeSchema = z.object({
717
750
  title: optionalString(MAX_TITLE_LENGTH),
@@ -725,7 +758,7 @@ var updateIntakeSchema = z.object({
725
758
  providedContext: optionalStringArray,
726
759
  metadata: metadataSchema.optional(),
727
760
  isVibeMode: z.boolean().optional(),
728
- vibeProtocol: z.any().optional()
761
+ vibeProtocol: vibeProtocolStateSchema.optional()
729
762
  }).strict();
730
763
  var answerInputSchema = z.object({
731
764
  field: nonBlankString(64, "answer field"),
@@ -1384,6 +1417,7 @@ var RequirementIntakeService = class {
1384
1417
  throw new IntakeValidationError([{ field: "title", message: "title must not be blank" }]);
1385
1418
  }
1386
1419
  return this.store.update(id, this.updateMeta(ctx, "updated", changedKeys, expectedVersion), (next) => {
1420
+ this.assertMutable(next, "updateIntake");
1387
1421
  if (validated.title !== void 0) {
1388
1422
  next.title = validated.title.trim();
1389
1423
  next.fieldSources.title = "user";
@@ -1421,6 +1455,7 @@ var RequirementIntakeService = class {
1421
1455
  id,
1422
1456
  this.updateMeta(ctx, "answer_added", [validated.field], expectedVersion),
1423
1457
  (next) => {
1458
+ this.assertMutable(next, "addAnswer");
1424
1459
  applyAnswerToRecord(next, validated, ctx.id, Date.now());
1425
1460
  }
1426
1461
  ).then((updated) => {
@@ -1438,6 +1473,7 @@ var RequirementIntakeService = class {
1438
1473
  })
1439
1474
  );
1440
1475
  return this.store.update(id, this.updateMeta(ctx, "answer_updated", [answerId], expectedVersion), (next) => {
1476
+ this.assertMutable(next, "updateAnswer");
1441
1477
  applyAnswerUpdateToRecord(next, answerId, validated.answer);
1442
1478
  }).then((updated) => {
1443
1479
  this.afterMutation(updated, ctx, "RequirementIntakeUpdated");
@@ -1454,6 +1490,7 @@ var RequirementIntakeService = class {
1454
1490
  id,
1455
1491
  this.updateMeta(ctx, "attachment_added", ["attachments"], expectedVersion),
1456
1492
  (next) => {
1493
+ this.assertMutable(next, "attachResource");
1457
1494
  applyAttachmentToRecord(next, validated, ctx.id, now);
1458
1495
  }
1459
1496
  ).then((updated) => {
@@ -1465,6 +1502,7 @@ var RequirementIntakeService = class {
1465
1502
  id,
1466
1503
  this.updateMeta(ctx, "related_resource_added", ["related_resources"], expectedVersion),
1467
1504
  (next) => {
1505
+ this.assertMutable(next, "attachResource");
1468
1506
  applyRelatedResourceToRecord(next, validated, ctx.id, now);
1469
1507
  }
1470
1508
  ).then((updated) => {
@@ -1520,6 +1558,7 @@ var RequirementIntakeService = class {
1520
1558
  to: previousStatus === nextStatus ? void 0 : nextStatus
1521
1559
  },
1522
1560
  (next) => {
1561
+ this.assertMutable(next, "generateSuggestions");
1523
1562
  next.llmSuggestions.push(...proposals);
1524
1563
  if (next.llmSuggestions.length > MAX_SUGGESTIONS) {
1525
1564
  next.llmSuggestions = next.llmSuggestions.slice(
@@ -1561,6 +1600,7 @@ var RequirementIntakeService = class {
1561
1600
  id,
1562
1601
  this.updateMeta(ctx, "suggestion_accepted", [proposal2.kind], expectedVersion),
1563
1602
  (next) => {
1603
+ this.assertMutable(next, "acceptSuggestion");
1564
1604
  const target = next.llmSuggestions.find((candidate) => candidate.id === proposalId);
1565
1605
  if (!target) {
1566
1606
  throw new IntakeValidationError([
@@ -1584,6 +1624,7 @@ var RequirementIntakeService = class {
1584
1624
  id,
1585
1625
  this.updateMeta(ctx, "suggestion_rejected", [proposalId], expectedVersion),
1586
1626
  (next) => {
1627
+ this.assertMutable(next, "rejectSuggestion");
1587
1628
  const target = next.llmSuggestions.find((candidate) => candidate.id === proposalId);
1588
1629
  if (!target) {
1589
1630
  throw new IntakeValidationError([
@@ -1915,6 +1956,7 @@ export {
1915
1956
  validateLlmSuggestionOutput,
1916
1957
  validateQuestionTemplateInput,
1917
1958
  validateRelatedResourceInput,
1918
- validateUpdateInput
1959
+ validateUpdateInput,
1960
+ vibeProtocolStateSchema
1919
1961
  };
1920
1962
  //# sourceMappingURL=index.js.map
@@ -75,6 +75,24 @@ export declare const questionTemplateInputSchema: z.ZodObject<{
75
75
  required: z.ZodOptional<z.ZodBoolean>;
76
76
  }, z.core.$strip>;
77
77
  export declare const metadataSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
78
+ /** Strict, bounded representation of resumable VIBE protocol state. */
79
+ export declare const vibeProtocolStateSchema: z.ZodObject<{
80
+ isVibeMode: z.ZodLiteral<true>;
81
+ detectedAt: z.ZodNumber;
82
+ stage: z.ZodEnum<{
83
+ auditor: "auditor";
84
+ coder: "coder";
85
+ passed: "passed";
86
+ synthesizer: "synthesizer";
87
+ }>;
88
+ synthesizedSpec: z.ZodOptional<z.ZodString>;
89
+ coderContract: z.ZodOptional<z.ZodString>;
90
+ auditVerdict: z.ZodOptional<z.ZodEnum<{
91
+ PASS: "PASS";
92
+ REJECT: "REJECT";
93
+ }>>;
94
+ auditNotes: z.ZodOptional<z.ZodArray<z.ZodString>>;
95
+ }, z.core.$strict>;
78
96
  export declare const createIntakeSchema: z.ZodObject<{
79
97
  projectId: z.ZodString;
80
98
  originalRequest: z.ZodString;
@@ -129,7 +147,23 @@ export declare const createIntakeSchema: z.ZodObject<{
129
147
  required: z.ZodOptional<z.ZodBoolean>;
130
148
  }, z.core.$strip>>>;
131
149
  isVibeMode: z.ZodOptional<z.ZodBoolean>;
132
- vibeProtocol: z.ZodOptional<z.ZodAny>;
150
+ vibeProtocol: z.ZodOptional<z.ZodObject<{
151
+ isVibeMode: z.ZodLiteral<true>;
152
+ detectedAt: z.ZodNumber;
153
+ stage: z.ZodEnum<{
154
+ auditor: "auditor";
155
+ coder: "coder";
156
+ passed: "passed";
157
+ synthesizer: "synthesizer";
158
+ }>;
159
+ synthesizedSpec: z.ZodOptional<z.ZodString>;
160
+ coderContract: z.ZodOptional<z.ZodString>;
161
+ auditVerdict: z.ZodOptional<z.ZodEnum<{
162
+ PASS: "PASS";
163
+ REJECT: "REJECT";
164
+ }>>;
165
+ auditNotes: z.ZodOptional<z.ZodArray<z.ZodString>>;
166
+ }, z.core.$strict>>;
133
167
  }, z.core.$strict>;
134
168
  export declare const updateIntakeSchema: z.ZodObject<{
135
169
  title: z.ZodOptional<z.ZodString>;
@@ -149,7 +183,23 @@ export declare const updateIntakeSchema: z.ZodObject<{
149
183
  providedContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
150
184
  metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
151
185
  isVibeMode: z.ZodOptional<z.ZodBoolean>;
152
- vibeProtocol: z.ZodOptional<z.ZodAny>;
186
+ vibeProtocol: z.ZodOptional<z.ZodObject<{
187
+ isVibeMode: z.ZodLiteral<true>;
188
+ detectedAt: z.ZodNumber;
189
+ stage: z.ZodEnum<{
190
+ auditor: "auditor";
191
+ coder: "coder";
192
+ passed: "passed";
193
+ synthesizer: "synthesizer";
194
+ }>;
195
+ synthesizedSpec: z.ZodOptional<z.ZodString>;
196
+ coderContract: z.ZodOptional<z.ZodString>;
197
+ auditVerdict: z.ZodOptional<z.ZodEnum<{
198
+ PASS: "PASS";
199
+ REJECT: "REJECT";
200
+ }>>;
201
+ auditNotes: z.ZodOptional<z.ZodArray<z.ZodString>>;
202
+ }, z.core.$strict>>;
153
203
  }, z.core.$strict>;
154
204
  export declare const answerInputSchema: z.ZodObject<{
155
205
  field: z.ZodString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/requirement-intake",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack Requirements Intake — collect, preserve, validate, normalize, and submit unstructured software development requests as structured intake records. Upstream of spec-driven development: it never plans, specifies, or implements.",
6
6
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "!dist/**/*.map"
28
28
  ],
29
29
  "dependencies": {
30
- "@wrongstack/core": "1.0.24",
30
+ "@wrongstack/core": "1.0.26",
31
31
  "zod": "4.6.2"
32
32
  },
33
33
  "devDependencies": {