@cat-factory/contracts 0.6.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.
- package/LICENSE +21 -0
- package/dist/accounts.d.ts +103 -0
- package/dist/accounts.d.ts.map +1 -0
- package/dist/accounts.js +102 -0
- package/dist/accounts.js.map +1 -0
- package/dist/agent-config.d.ts +77 -0
- package/dist/agent-config.d.ts.map +1 -0
- package/dist/agent-config.js +78 -0
- package/dist/agent-config.js.map +1 -0
- package/dist/api-keys.d.ts +44 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +49 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/auth.d.ts +24 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +15 -0
- package/dist/auth.js.map +1 -0
- package/dist/board-scan.d.ts +89 -0
- package/dist/board-scan.d.ts.map +1 -0
- package/dist/board-scan.js +122 -0
- package/dist/board-scan.js.map +1 -0
- package/dist/bootstrap.d.ts +168 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +148 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/clarity.d.ts +75 -0
- package/dist/clarity.d.ts.map +1 -0
- package/dist/clarity.js +66 -0
- package/dist/clarity.js.map +1 -0
- package/dist/companion.d.ts +32 -0
- package/dist/companion.d.ts.map +1 -0
- package/dist/companion.js +43 -0
- package/dist/companion.js.map +1 -0
- package/dist/consensus.d.ts +195 -0
- package/dist/consensus.d.ts.map +1 -0
- package/dist/consensus.js +164 -0
- package/dist/consensus.js.map +1 -0
- package/dist/documents.d.ts +197 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +161 -0
- package/dist/documents.js.map +1 -0
- package/dist/entities.d.ts +1691 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +853 -0
- package/dist/entities.js.map +1 -0
- package/dist/environments.d.ts +426 -0
- package/dist/environments.d.ts.map +1 -0
- package/dist/environments.js +190 -0
- package/dist/environments.js.map +1 -0
- package/dist/events.d.ts +98 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/fragment-library.d.ts +123 -0
- package/dist/fragment-library.d.ts.map +1 -0
- package/dist/fragment-library.js +88 -0
- package/dist/fragment-library.js.map +1 -0
- package/dist/github.d.ts +215 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +204 -0
- package/dist/github.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/iteration-cap.d.ts +17 -0
- package/dist/iteration-cap.d.ts.map +1 -0
- package/dist/iteration-cap.js +25 -0
- package/dist/iteration-cap.js.map +1 -0
- package/dist/localModels.d.ts +54 -0
- package/dist/localModels.d.ts.map +1 -0
- package/dist/localModels.js +79 -0
- package/dist/localModels.js.map +1 -0
- package/dist/merge.d.ts +106 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +129 -0
- package/dist/merge.js.map +1 -0
- package/dist/model-defaults.d.ts +23 -0
- package/dist/model-defaults.d.ts.map +1 -0
- package/dist/model-defaults.js +34 -0
- package/dist/model-defaults.js.map +1 -0
- package/dist/notifications.d.ts +136 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +125 -0
- package/dist/notifications.js.map +1 -0
- package/dist/observability.d.ts +271 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +152 -0
- package/dist/observability.js.map +1 -0
- package/dist/personal-subscriptions.d.ts +66 -0
- package/dist/personal-subscriptions.d.ts.map +1 -0
- package/dist/personal-subscriptions.js +70 -0
- package/dist/personal-subscriptions.js.map +1 -0
- package/dist/primitives.d.ts +57 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +66 -0
- package/dist/primitives.js.map +1 -0
- package/dist/provisioning.d.ts +46 -0
- package/dist/provisioning.d.ts.map +1 -0
- package/dist/provisioning.js +107 -0
- package/dist/provisioning.js.map +1 -0
- package/dist/recurring.d.ts +117 -0
- package/dist/recurring.d.ts.map +1 -0
- package/dist/recurring.js +99 -0
- package/dist/recurring.js.map +1 -0
- package/dist/release.d.ts +60 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +75 -0
- package/dist/release.js.map +1 -0
- package/dist/requests.d.ts +451 -0
- package/dist/requests.d.ts.map +1 -0
- package/dist/requests.js +231 -0
- package/dist/requests.js.map +1 -0
- package/dist/requirements.d.ts +127 -0
- package/dist/requirements.d.ts.map +1 -0
- package/dist/requirements.js +137 -0
- package/dist/requirements.js.map +1 -0
- package/dist/runners.d.ts +387 -0
- package/dist/runners.d.ts.map +1 -0
- package/dist/runners.js +117 -0
- package/dist/runners.js.map +1 -0
- package/dist/sandbox.d.ts +300 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +243 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/service-fragment-defaults.d.ts +16 -0
- package/dist/service-fragment-defaults.d.ts.map +1 -0
- package/dist/service-fragment-defaults.js +23 -0
- package/dist/service-fragment-defaults.js.map +1 -0
- package/dist/services.d.ts +81 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +77 -0
- package/dist/services.js.map +1 -0
- package/dist/slack.d.ts +104 -0
- package/dist/slack.d.ts.map +1 -0
- package/dist/slack.js +98 -0
- package/dist/slack.js.map +1 -0
- package/dist/snapshot.d.ts +522 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +104 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/spec.d.ts +174 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +173 -0
- package/dist/spec.js.map +1 -0
- package/dist/tasks.d.ts +150 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +146 -0
- package/dist/tasks.js.map +1 -0
- package/dist/testing.d.ts +67 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +64 -0
- package/dist/testing.js.map +1 -0
- package/dist/tracker.d.ts +18 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +24 -0
- package/dist/tracker.js.map +1 -0
- package/dist/vendor-credentials.d.ts +37 -0
- package/dist/vendor-credentials.d.ts.map +1 -0
- package/dist/vendor-credentials.js +40 -0
- package/dist/vendor-credentials.js.map +1 -0
- package/dist/workspace-settings.d.ts +36 -0
- package/dist/workspace-settings.d.ts.map +1 -0
- package/dist/workspace-settings.js +41 -0
- package/dist/workspace-settings.js.map +1 -0
- package/package.json +31 -0
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
import { blockSchema, executionInstanceSchema, pipelineSchema, spendStatusSchema, workspaceSchema, } from './entities.js';
|
|
3
|
+
import { bootstrapJobSchema } from './bootstrap.js';
|
|
4
|
+
import { notificationSchema } from './notifications.js';
|
|
5
|
+
import { mergeThresholdPresetSchema } from './merge.js';
|
|
6
|
+
import { agentConfigCatalogSchema } from './agent-config.js';
|
|
7
|
+
import { modelDefaultsSchema } from './model-defaults.js';
|
|
8
|
+
import { serviceFragmentDefaultsSchema } from './service-fragment-defaults.js';
|
|
9
|
+
import { pipelineScheduleSchema } from './recurring.js';
|
|
10
|
+
import { serviceSchema, workspaceMountSchema } from './services.js';
|
|
11
|
+
import { trackerSettingsSchema } from './tracker.js';
|
|
12
|
+
import { workspaceSettingsSchema } from './workspace-settings.js';
|
|
13
|
+
// The full board snapshot returned by GET /workspaces/:id (and POST /workspaces).
|
|
14
|
+
// It lives in its own module because it references both ./entities and
|
|
15
|
+
// ./bootstrap, and ./bootstrap imports from ./entities — defining it in either
|
|
16
|
+
// would be a circular import.
|
|
17
|
+
export const workspaceSnapshotSchema = v.object({
|
|
18
|
+
workspace: workspaceSchema,
|
|
19
|
+
blocks: v.array(blockSchema),
|
|
20
|
+
pipelines: v.array(pipelineSchema),
|
|
21
|
+
executions: v.array(executionInstanceSchema),
|
|
22
|
+
/**
|
|
23
|
+
* Bootstrap runs for this workspace (the unified `agent_runs` table's bootstrap
|
|
24
|
+
* rows). Carried in the snapshot so the board can render a bootstrap's live
|
|
25
|
+
* progress / failure + retry the moment it loads, without a separate fetch that
|
|
26
|
+
* could fail independently. Attached by the worker, so optional on the wire.
|
|
27
|
+
*/
|
|
28
|
+
bootstrapJobs: v.optional(v.array(bootstrapJobSchema)),
|
|
29
|
+
/**
|
|
30
|
+
* The current spend-safeguard status. Attached by the worker (it depends on
|
|
31
|
+
* deployment-wide pricing/budget config), so it is optional on the wire.
|
|
32
|
+
*/
|
|
33
|
+
spend: v.optional(spendStatusSchema),
|
|
34
|
+
/**
|
|
35
|
+
* Open human-actionable notifications for this workspace (PRs awaiting a merge
|
|
36
|
+
* decision, completed pipelines awaiting confirmation, CI that gave up). Carried
|
|
37
|
+
* in the snapshot so the board renders the inbox + badges on load. Attached by
|
|
38
|
+
* the worker, so optional on the wire.
|
|
39
|
+
*/
|
|
40
|
+
notifications: v.optional(v.array(notificationSchema)),
|
|
41
|
+
/**
|
|
42
|
+
* The workspace's merge threshold presets (the library a task picks its
|
|
43
|
+
* auto-merge policy from). Attached by the worker, so optional on the wire.
|
|
44
|
+
*/
|
|
45
|
+
mergePresets: v.optional(v.array(mergeThresholdPresetSchema)),
|
|
46
|
+
/**
|
|
47
|
+
* The catalog of agent config-contribution descriptors (the task-level parameters
|
|
48
|
+
* the registered agent kinds surface, e.g. the Tester's environment). The board
|
|
49
|
+
* renders the subset whose owning kind appears in a task's selected pipeline.
|
|
50
|
+
* Static metadata derived from the agent registry; attached by the facade, so
|
|
51
|
+
* optional on the wire.
|
|
52
|
+
*/
|
|
53
|
+
agentConfigCatalog: v.optional(agentConfigCatalogSchema),
|
|
54
|
+
/**
|
|
55
|
+
* The workspace's per-agent-kind default models (the model each agent kind
|
|
56
|
+
* defaults to, overriding the env routing for this workspace). Attached by the
|
|
57
|
+
* worker, so optional on the wire.
|
|
58
|
+
*/
|
|
59
|
+
modelDefaults: v.optional(modelDefaultsSchema),
|
|
60
|
+
/**
|
|
61
|
+
* The deployment's env-routing defaults as `provider:model` refs: the model an
|
|
62
|
+
* agent kind runs on when neither the task nor the workspace pins one. `default`
|
|
63
|
+
* is the global fallback; `byKind` carries the kinds an operator routed
|
|
64
|
+
* specifically (e.g. a strong coding model for the coder). The frontend resolves
|
|
65
|
+
* a kind's deployment default as `byKind[kind] ?? default` and labels it so the
|
|
66
|
+
* model-defaults panel can name the model behind "Deployment default". Derived
|
|
67
|
+
* from shared config, attached by the facade, so optional on the wire.
|
|
68
|
+
*/
|
|
69
|
+
deploymentModelDefaults: v.optional(v.object({
|
|
70
|
+
default: v.string(),
|
|
71
|
+
byKind: v.record(v.string(), v.string()),
|
|
72
|
+
})),
|
|
73
|
+
/**
|
|
74
|
+
* The workspace's default service-fragment selection (the best-practice fragment ids
|
|
75
|
+
* new services inherit). Attached by the facade, so optional on the wire.
|
|
76
|
+
*/
|
|
77
|
+
serviceFragmentDefaults: v.optional(serviceFragmentDefaultsSchema),
|
|
78
|
+
/**
|
|
79
|
+
* The workspace's recurring pipelines (schedules that re-run a pipeline against
|
|
80
|
+
* a service on a cadence). Carried in the snapshot so the board renders the
|
|
81
|
+
* recurring-task badges + inspector on load. Run history is fetched lazily.
|
|
82
|
+
*/
|
|
83
|
+
recurringPipelines: v.optional(v.array(pipelineScheduleSchema)),
|
|
84
|
+
/**
|
|
85
|
+
* The workspace's issue-tracker selection (where the tech-debt pipeline files
|
|
86
|
+
* its ticket). Attached by the worker, so optional on the wire.
|
|
87
|
+
*/
|
|
88
|
+
trackerSettings: v.optional(trackerSettingsSchema),
|
|
89
|
+
/**
|
|
90
|
+
* In-org shared services. `mounts` are the services this workspace mounts (with the
|
|
91
|
+
* per-workspace frame layout); `serviceCatalog` is the org's services the board can
|
|
92
|
+
* mount from (each annotated with `mountCount` so the UI can badge a shared frame).
|
|
93
|
+
* Attached by the worker when the services module is wired, so optional on the wire.
|
|
94
|
+
*/
|
|
95
|
+
mounts: v.optional(v.array(workspaceMountSchema)),
|
|
96
|
+
serviceCatalog: v.optional(v.array(serviceSchema)),
|
|
97
|
+
/**
|
|
98
|
+
* The workspace's runtime settings (the human-wait escalation threshold + the
|
|
99
|
+
* per-service running-task limit policy). Lazily seeded from the defaults; attached
|
|
100
|
+
* by the facade, so optional on the wire.
|
|
101
|
+
*/
|
|
102
|
+
settings: v.optional(workspaceSettingsSchema),
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,kFAAkF;AAClF,uEAAuE;AACvE,+EAA+E;AAC/E,8BAA8B;AAE9B,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;IAClC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC;IAC5C;;;;;OAKG;IACH,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtD;;;OAGG;IACH,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IACpC;;;;;OAKG;IACH,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtD;;;OAGG;IACH,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC7D;;;;;;OAMG;IACH,kBAAkB,EAAE,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IACxD;;;;OAIG;IACH,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAC9C;;;;;;;;OAQG;IACH,uBAAuB,EAAE,CAAC,CAAC,QAAQ,CACjC,CAAC,CAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;KACzC,CAAC,CACH;IACD;;;OAGG;IACH,uBAAuB,EAAE,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IAClE;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC/D;;;OAGG;IACH,eAAe,EAAE,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAClD;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACjD,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD;;;;OAIG;IACH,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;CAC9C,CAAC,CAAA"}
|
package/dist/spec.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
/** MoSCoW priority — how essential a requirement is. */
|
|
3
|
+
export declare const requirementPrioritySchema: v.PicklistSchema<["must", "should", "could"], undefined>;
|
|
4
|
+
export type RequirementPriority = v.InferOutput<typeof requirementPrioritySchema>;
|
|
5
|
+
/** Whether a requirement is a behaviour, a quality attribute, or a hard constraint. */
|
|
6
|
+
export declare const requirementKindSchema: v.PicklistSchema<["functional", "nonfunctional", "constraint"], undefined>;
|
|
7
|
+
export type RequirementKind = v.InferOutput<typeof requirementKindSchema>;
|
|
8
|
+
/**
|
|
9
|
+
* A single acceptance criterion in structured Given/When/Then form — the seed for
|
|
10
|
+
* one Gherkin `Scenario`. Kept structured (not prose) so the harness can render it
|
|
11
|
+
* mechanically and deterministically into a `.feature` file.
|
|
12
|
+
*/
|
|
13
|
+
export declare const acceptanceCriterionSchema: v.ObjectSchema<{
|
|
14
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
15
|
+
readonly given: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
16
|
+
readonly when: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
17
|
+
readonly outcome: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
18
|
+
}, undefined>;
|
|
19
|
+
export type AcceptanceCriterion = v.InferOutput<typeof acceptanceCriterionSchema>;
|
|
20
|
+
/** A single prescriptive requirement, traceable back to the board task(s) it came from. */
|
|
21
|
+
export declare const requirementItemSchema: v.ObjectSchema<{
|
|
22
|
+
/** Stable slug, e.g. `req-login-rate-limit`. */
|
|
23
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
24
|
+
/** Short headline. */
|
|
25
|
+
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
26
|
+
/** The requirement itself, as `The system SHALL …` prose. */
|
|
27
|
+
readonly statement: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 4000, undefined>]>;
|
|
28
|
+
readonly kind: v.PicklistSchema<["functional", "nonfunctional", "constraint"], undefined>;
|
|
29
|
+
readonly priority: v.PicklistSchema<["must", "should", "could"], undefined>;
|
|
30
|
+
/** Ids of the board task/block(s) this requirement was aggregated from (provenance). */
|
|
31
|
+
readonly sourceBlockIds: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
32
|
+
/** Structured acceptance criteria → the seed for this requirement's Gherkin scenarios. */
|
|
33
|
+
readonly acceptance: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
34
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
35
|
+
readonly given: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
36
|
+
readonly when: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
37
|
+
readonly outcome: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
38
|
+
}, undefined>, undefined>, readonly []>;
|
|
39
|
+
}, undefined>;
|
|
40
|
+
export type RequirementItem = v.InferOutput<typeof requirementItemSchema>;
|
|
41
|
+
/**
|
|
42
|
+
* A cross-cutting domain rule / invariant / constraint — prescriptive, but not tied
|
|
43
|
+
* to a single capability. Unified into THIS document (not a separate `domain/`
|
|
44
|
+
* artifact) because rules share the spec's lifecycle; rendered to `rules.md`.
|
|
45
|
+
*/
|
|
46
|
+
export declare const domainRuleSchema: v.ObjectSchema<{
|
|
47
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
48
|
+
/** The invariant, e.g. `An order may never have a negative total.` */
|
|
49
|
+
readonly rule: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 4000, undefined>]>;
|
|
50
|
+
/** Why the rule exists (optional). */
|
|
51
|
+
readonly rationale: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
52
|
+
readonly sourceBlockIds: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
53
|
+
}, undefined>;
|
|
54
|
+
export type DomainRule = v.InferOutput<typeof domainRuleSchema>;
|
|
55
|
+
/** A grouping of related requirements (a capability / feature area ≈ one `.feature` file). */
|
|
56
|
+
export declare const requirementGroupSchema: v.ObjectSchema<{
|
|
57
|
+
readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
58
|
+
readonly summary: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
59
|
+
readonly requirements: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
60
|
+
/** Stable slug, e.g. `req-login-rate-limit`. */
|
|
61
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
62
|
+
/** Short headline. */
|
|
63
|
+
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
64
|
+
/** The requirement itself, as `The system SHALL …` prose. */
|
|
65
|
+
readonly statement: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 4000, undefined>]>;
|
|
66
|
+
readonly kind: v.PicklistSchema<["functional", "nonfunctional", "constraint"], undefined>;
|
|
67
|
+
readonly priority: v.PicklistSchema<["must", "should", "could"], undefined>;
|
|
68
|
+
/** Ids of the board task/block(s) this requirement was aggregated from (provenance). */
|
|
69
|
+
readonly sourceBlockIds: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
70
|
+
/** Structured acceptance criteria → the seed for this requirement's Gherkin scenarios. */
|
|
71
|
+
readonly acceptance: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
72
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
73
|
+
readonly given: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
74
|
+
readonly when: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
75
|
+
readonly outcome: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
76
|
+
}, undefined>, undefined>, readonly []>;
|
|
77
|
+
}, undefined>, undefined>, readonly []>;
|
|
78
|
+
}, undefined>;
|
|
79
|
+
export type RequirementGroup = v.InferOutput<typeof requirementGroupSchema>;
|
|
80
|
+
/** The unified, prescriptive specification document for one service (the `spec.json` tree). */
|
|
81
|
+
export declare const specDocSchema: v.ObjectSchema<{
|
|
82
|
+
/** Service / frame name (defaults to the repo name). */
|
|
83
|
+
readonly service: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
84
|
+
/** One-paragraph product intent for the service overall. */
|
|
85
|
+
readonly summary: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
86
|
+
/** Requirements grouped by capability; each group renders one `.feature` file. */
|
|
87
|
+
readonly groups: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
88
|
+
readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
89
|
+
readonly summary: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
90
|
+
readonly requirements: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
91
|
+
/** Stable slug, e.g. `req-login-rate-limit`. */
|
|
92
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
93
|
+
/** Short headline. */
|
|
94
|
+
readonly title: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>]>;
|
|
95
|
+
/** The requirement itself, as `The system SHALL …` prose. */
|
|
96
|
+
readonly statement: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 4000, undefined>]>;
|
|
97
|
+
readonly kind: v.PicklistSchema<["functional", "nonfunctional", "constraint"], undefined>;
|
|
98
|
+
readonly priority: v.PicklistSchema<["must", "should", "could"], undefined>;
|
|
99
|
+
/** Ids of the board task/block(s) this requirement was aggregated from (provenance). */
|
|
100
|
+
readonly sourceBlockIds: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
101
|
+
/** Structured acceptance criteria → the seed for this requirement's Gherkin scenarios. */
|
|
102
|
+
readonly acceptance: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
103
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
104
|
+
readonly given: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
105
|
+
readonly when: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
106
|
+
readonly outcome: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>;
|
|
107
|
+
}, undefined>, undefined>, readonly []>;
|
|
108
|
+
}, undefined>, undefined>, readonly []>;
|
|
109
|
+
}, undefined>, undefined>, readonly []>;
|
|
110
|
+
/** Cross-cutting domain rules / invariants / constraints. */
|
|
111
|
+
readonly rules: v.OptionalSchema<v.ArraySchema<v.ObjectSchema<{
|
|
112
|
+
readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
113
|
+
/** The invariant, e.g. `An order may never have a negative total.` */
|
|
114
|
+
readonly rule: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 4000, undefined>]>;
|
|
115
|
+
/** Why the rule exists (optional). */
|
|
116
|
+
readonly rationale: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 2000, undefined>]>, "">;
|
|
117
|
+
readonly sourceBlockIds: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>, readonly []>;
|
|
118
|
+
}, undefined>, undefined>, readonly []>;
|
|
119
|
+
}, undefined>;
|
|
120
|
+
export type SpecDoc = v.InferOutput<typeof specDocSchema>;
|
|
121
|
+
/**
|
|
122
|
+
* The lightweight `version.json` manifest committed alongside the spec. It carries a
|
|
123
|
+
* monotonic version counter, the generation timestamp, a content hash of the
|
|
124
|
+
* canonical tree, and the requirement/rule counts — so staleness checks are a tiny
|
|
125
|
+
* read rather than a full parse of `spec.json`. Mirrors the blueprint's
|
|
126
|
+
* `version.json` manifest field-for-field in spirit.
|
|
127
|
+
*/
|
|
128
|
+
export declare const specVersionSchema: v.ObjectSchema<{
|
|
129
|
+
readonly version: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
130
|
+
readonly generatedAt: v.StringSchema<undefined>;
|
|
131
|
+
/** sha256 (hex) of the canonical `spec.json` bytes. */
|
|
132
|
+
readonly hash: v.StringSchema<undefined>;
|
|
133
|
+
readonly requirements: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
134
|
+
readonly rules: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
135
|
+
}, undefined>;
|
|
136
|
+
export type SpecVersion = v.InferOutput<typeof specVersionSchema>;
|
|
137
|
+
/** Folder, relative to the repo root, that holds the persisted spec. */
|
|
138
|
+
export declare const SPEC_DIR = "spec";
|
|
139
|
+
/** Canonical machine-readable spec file (the SpecDoc tree). */
|
|
140
|
+
export declare const SPEC_JSON_PATH = "spec/spec.json";
|
|
141
|
+
/** High-level overview markdown — the file agents read first. */
|
|
142
|
+
export declare const SPEC_OVERVIEW_PATH = "spec/overview.md";
|
|
143
|
+
/** Domain rules / invariants / constraints markdown. */
|
|
144
|
+
export declare const SPEC_RULES_PATH = "spec/rules.md";
|
|
145
|
+
/** Tiny manifest read for quick staleness checks without parsing the full tree. */
|
|
146
|
+
export declare const SPEC_VERSION_PATH = "spec/version.json";
|
|
147
|
+
/** Sub-folder holding the generated Gherkin `.feature` files (one per group). */
|
|
148
|
+
export declare const SPEC_FEATURES_DIR = "spec/features";
|
|
149
|
+
/** Legacy folder name the spec lived under before the rename; relocated on first run. */
|
|
150
|
+
export declare const LEGACY_SPEC_DIR = "requirements";
|
|
151
|
+
/**
|
|
152
|
+
* Strictly parse an arbitrary value (e.g. the JSON read from `spec.json`, or a tree
|
|
153
|
+
* returned by the spec-writer container) into a {@link SpecDoc}, enforcing the exact
|
|
154
|
+
* schema shape. Throws on any shape violation, so a bad payload can never be
|
|
155
|
+
* ingested. Use it at every trust boundary that ingests a spec.
|
|
156
|
+
*/
|
|
157
|
+
export declare function parseSpecDoc(value: unknown): SpecDoc;
|
|
158
|
+
/** Non-throwing variant: returns the parsed doc or `undefined` when invalid. */
|
|
159
|
+
export declare function safeParseSpecDoc(value: unknown): SpecDoc | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* Render a {@link SpecDoc} as readable markdown for HUMAN + COMPANION review.
|
|
162
|
+
*
|
|
163
|
+
* The spec-writer is a container agent: it emits the spec as JSON, renders the
|
|
164
|
+
* in-repo files and commits them, then its raw `summary` (a fragment of the Pi
|
|
165
|
+
* transcript) is all that survives on the step. Grading that transcript instead of
|
|
166
|
+
* the document is what made the spec-companion declare every pass "unreviewable" and
|
|
167
|
+
* loop the producer to its cap. This renders the actual tree — every group, its
|
|
168
|
+
* requirements (statement / kind / priority) and their Given/When/Then acceptance
|
|
169
|
+
* criteria, plus the cross-cutting rules — so the reviewer (and the SPA reader, and
|
|
170
|
+
* downstream steps) see the spec itself, not the agent's chatter. Deterministic and
|
|
171
|
+
* dependency-free so it is safe to call at the ingest trust boundary.
|
|
172
|
+
*/
|
|
173
|
+
export declare function renderSpecForReview(spec: SpecDoc): string;
|
|
174
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AA2B5B,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,0DAA0C,CAAA;AAChF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEjF,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,4EAA4D,CAAA;AAC9F,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;;aAOpC,CAAA;AACF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEjF,2FAA2F;AAC3F,eAAO,MAAM,qBAAqB;IAChC,gDAAgD;;IAEhD,sBAAsB;;IAEtB,6DAA6D;;;;IAI7D,wFAAwF;;IAExF,0FAA0F;;;;;;;aAE1F,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;IAE3B,sEAAsE;;IAEtE,sCAAsC;;;aAGtC,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAE/D,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB;;;;QA/BjC,gDAAgD;;QAEhD,sBAAsB;;QAEtB,6DAA6D;;;;QAI7D,wFAAwF;;QAExF,0FAA0F;;;;;;;;aAyB1F,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE3E,+FAA+F;AAC/F,eAAO,MAAM,aAAa;IACxB,wDAAwD;;IAExD,4DAA4D;;IAE5D,kFAAkF;;;;;YA5ClF,gDAAgD;;YAEhD,sBAAsB;;YAEtB,6DAA6D;;;;YAI7D,wFAAwF;;YAExF,0FAA0F;;;;;;;;;IAoC1F,6DAA6D;;;QAxB7D,sEAAsE;;QAEtE,sCAAsC;;;;aAwBtC,CAAA;AACF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,aAAa,CAAC,CAAA;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;IAG5B,uDAAuD;;;;aAIvD,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAOjE,wEAAwE;AACxE,eAAO,MAAM,QAAQ,SAAS,CAAA;AAC9B,+DAA+D;AAC/D,eAAO,MAAM,cAAc,mBAA0B,CAAA;AACrD,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,qBAA4B,CAAA;AAC3D,wDAAwD;AACxD,eAAO,MAAM,eAAe,kBAAyB,CAAA;AACrD,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,sBAA6B,CAAA;AAC3D,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,kBAAyB,CAAA;AAEvD,yFAAyF;AACzF,eAAO,MAAM,eAAe,iBAAiB,CAAA;AAE7C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAGpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAuBzD"}
|
package/dist/spec.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Unified in-repo SPECIFICATION artifact (prescriptive, service-level).
|
|
4
|
+
//
|
|
5
|
+
// This is the durable PRESCRIPTIVE spec for a whole service, persisted in the
|
|
6
|
+
// service's own GitHub repo under `spec/` and aggregated across every task. It is
|
|
7
|
+
// the mirror image of the blueprint: a blueprint is DESCRIPTIVE ("what the code
|
|
8
|
+
// is"), this spec is PRESCRIPTIVE ("what must be true"). The canonical,
|
|
9
|
+
// machine-readable file is `spec.json` (a SpecDoc); the markdown files
|
|
10
|
+
// (`overview.md`, `rules.md`) and the Gherkin `features/*.feature` files are
|
|
11
|
+
// deterministic renderings of the same tree. Every agent reads it as context, and
|
|
12
|
+
// its acceptance criteria seed the test scenarios.
|
|
13
|
+
//
|
|
14
|
+
// Naming note: this "spec" family is distinct from the transient, per-block
|
|
15
|
+
// "requirements" CONTEXT review (see `requirements.ts`), which clarifies the
|
|
16
|
+
// linked-prose brief before work starts. A spec legitimately *contains*
|
|
17
|
+
// requirements, domain rules and acceptance criteria, so those inner item types
|
|
18
|
+
// keep their names.
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const requirementIdField = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(200));
|
|
21
|
+
const reqNameField = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(120));
|
|
22
|
+
const reqSummaryField = v.pipe(v.string(), v.maxLength(2000));
|
|
23
|
+
const reqStatementField = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(4000));
|
|
24
|
+
const blockIdField = v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(200));
|
|
25
|
+
/** MoSCoW priority — how essential a requirement is. */
|
|
26
|
+
export const requirementPrioritySchema = v.picklist(['must', 'should', 'could']);
|
|
27
|
+
/** Whether a requirement is a behaviour, a quality attribute, or a hard constraint. */
|
|
28
|
+
export const requirementKindSchema = v.picklist(['functional', 'nonfunctional', 'constraint']);
|
|
29
|
+
/**
|
|
30
|
+
* A single acceptance criterion in structured Given/When/Then form — the seed for
|
|
31
|
+
* one Gherkin `Scenario`. Kept structured (not prose) so the harness can render it
|
|
32
|
+
* mechanically and deterministically into a `.feature` file.
|
|
33
|
+
*/
|
|
34
|
+
export const acceptanceCriterionSchema = v.object({
|
|
35
|
+
id: requirementIdField,
|
|
36
|
+
given: v.pipe(v.string(), v.maxLength(2000)),
|
|
37
|
+
when: v.pipe(v.string(), v.maxLength(2000)),
|
|
38
|
+
// The Gherkin "Then" clause. Named `outcome` (not `then`) so the object is never
|
|
39
|
+
// accidentally thenable — an object with a `then` member misbehaves under `await`.
|
|
40
|
+
outcome: v.pipe(v.string(), v.maxLength(2000)),
|
|
41
|
+
});
|
|
42
|
+
/** A single prescriptive requirement, traceable back to the board task(s) it came from. */
|
|
43
|
+
export const requirementItemSchema = v.object({
|
|
44
|
+
/** Stable slug, e.g. `req-login-rate-limit`. */
|
|
45
|
+
id: requirementIdField,
|
|
46
|
+
/** Short headline. */
|
|
47
|
+
title: reqNameField,
|
|
48
|
+
/** The requirement itself, as `The system SHALL …` prose. */
|
|
49
|
+
statement: reqStatementField,
|
|
50
|
+
kind: requirementKindSchema,
|
|
51
|
+
priority: requirementPrioritySchema,
|
|
52
|
+
/** Ids of the board task/block(s) this requirement was aggregated from (provenance). */
|
|
53
|
+
sourceBlockIds: v.optional(v.array(blockIdField), []),
|
|
54
|
+
/** Structured acceptance criteria → the seed for this requirement's Gherkin scenarios. */
|
|
55
|
+
acceptance: v.optional(v.array(acceptanceCriterionSchema), []),
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* A cross-cutting domain rule / invariant / constraint — prescriptive, but not tied
|
|
59
|
+
* to a single capability. Unified into THIS document (not a separate `domain/`
|
|
60
|
+
* artifact) because rules share the spec's lifecycle; rendered to `rules.md`.
|
|
61
|
+
*/
|
|
62
|
+
export const domainRuleSchema = v.object({
|
|
63
|
+
id: requirementIdField,
|
|
64
|
+
/** The invariant, e.g. `An order may never have a negative total.` */
|
|
65
|
+
rule: reqStatementField,
|
|
66
|
+
/** Why the rule exists (optional). */
|
|
67
|
+
rationale: v.optional(reqSummaryField, ''),
|
|
68
|
+
sourceBlockIds: v.optional(v.array(blockIdField), []),
|
|
69
|
+
});
|
|
70
|
+
/** A grouping of related requirements (a capability / feature area ≈ one `.feature` file). */
|
|
71
|
+
export const requirementGroupSchema = v.object({
|
|
72
|
+
name: reqNameField,
|
|
73
|
+
summary: v.optional(reqSummaryField, ''),
|
|
74
|
+
requirements: v.optional(v.array(requirementItemSchema), []),
|
|
75
|
+
});
|
|
76
|
+
/** The unified, prescriptive specification document for one service (the `spec.json` tree). */
|
|
77
|
+
export const specDocSchema = v.object({
|
|
78
|
+
/** Service / frame name (defaults to the repo name). */
|
|
79
|
+
service: reqNameField,
|
|
80
|
+
/** One-paragraph product intent for the service overall. */
|
|
81
|
+
summary: v.optional(reqSummaryField, ''),
|
|
82
|
+
/** Requirements grouped by capability; each group renders one `.feature` file. */
|
|
83
|
+
groups: v.optional(v.array(requirementGroupSchema), []),
|
|
84
|
+
/** Cross-cutting domain rules / invariants / constraints. */
|
|
85
|
+
rules: v.optional(v.array(domainRuleSchema), []),
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* The lightweight `version.json` manifest committed alongside the spec. It carries a
|
|
89
|
+
* monotonic version counter, the generation timestamp, a content hash of the
|
|
90
|
+
* canonical tree, and the requirement/rule counts — so staleness checks are a tiny
|
|
91
|
+
* read rather than a full parse of `spec.json`. Mirrors the blueprint's
|
|
92
|
+
* `version.json` manifest field-for-field in spirit.
|
|
93
|
+
*/
|
|
94
|
+
export const specVersionSchema = v.object({
|
|
95
|
+
version: v.pipe(v.number(), v.integer(), v.minValue(0)),
|
|
96
|
+
generatedAt: v.string(),
|
|
97
|
+
/** sha256 (hex) of the canonical `spec.json` bytes. */
|
|
98
|
+
hash: v.string(),
|
|
99
|
+
requirements: v.pipe(v.number(), v.integer(), v.minValue(0)),
|
|
100
|
+
rules: v.pipe(v.number(), v.integer(), v.minValue(0)),
|
|
101
|
+
});
|
|
102
|
+
// ---- In-repo spec artifact paths ------------------------------------------
|
|
103
|
+
// The folder + file layout, the prescriptive sibling of `blueprints/`. The
|
|
104
|
+
// canonical machine-readable file is `spec.json`; the markdown and feature files
|
|
105
|
+
// are deterministic renderings of the same tree.
|
|
106
|
+
/** Folder, relative to the repo root, that holds the persisted spec. */
|
|
107
|
+
export const SPEC_DIR = 'spec';
|
|
108
|
+
/** Canonical machine-readable spec file (the SpecDoc tree). */
|
|
109
|
+
export const SPEC_JSON_PATH = `${SPEC_DIR}/spec.json`;
|
|
110
|
+
/** High-level overview markdown — the file agents read first. */
|
|
111
|
+
export const SPEC_OVERVIEW_PATH = `${SPEC_DIR}/overview.md`;
|
|
112
|
+
/** Domain rules / invariants / constraints markdown. */
|
|
113
|
+
export const SPEC_RULES_PATH = `${SPEC_DIR}/rules.md`;
|
|
114
|
+
/** Tiny manifest read for quick staleness checks without parsing the full tree. */
|
|
115
|
+
export const SPEC_VERSION_PATH = `${SPEC_DIR}/version.json`;
|
|
116
|
+
/** Sub-folder holding the generated Gherkin `.feature` files (one per group). */
|
|
117
|
+
export const SPEC_FEATURES_DIR = `${SPEC_DIR}/features`;
|
|
118
|
+
/** Legacy folder name the spec lived under before the rename; relocated on first run. */
|
|
119
|
+
export const LEGACY_SPEC_DIR = 'requirements';
|
|
120
|
+
/**
|
|
121
|
+
* Strictly parse an arbitrary value (e.g. the JSON read from `spec.json`, or a tree
|
|
122
|
+
* returned by the spec-writer container) into a {@link SpecDoc}, enforcing the exact
|
|
123
|
+
* schema shape. Throws on any shape violation, so a bad payload can never be
|
|
124
|
+
* ingested. Use it at every trust boundary that ingests a spec.
|
|
125
|
+
*/
|
|
126
|
+
export function parseSpecDoc(value) {
|
|
127
|
+
return v.parse(specDocSchema, value);
|
|
128
|
+
}
|
|
129
|
+
/** Non-throwing variant: returns the parsed doc or `undefined` when invalid. */
|
|
130
|
+
export function safeParseSpecDoc(value) {
|
|
131
|
+
const result = v.safeParse(specDocSchema, value);
|
|
132
|
+
return result.success ? result.output : undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Render a {@link SpecDoc} as readable markdown for HUMAN + COMPANION review.
|
|
136
|
+
*
|
|
137
|
+
* The spec-writer is a container agent: it emits the spec as JSON, renders the
|
|
138
|
+
* in-repo files and commits them, then its raw `summary` (a fragment of the Pi
|
|
139
|
+
* transcript) is all that survives on the step. Grading that transcript instead of
|
|
140
|
+
* the document is what made the spec-companion declare every pass "unreviewable" and
|
|
141
|
+
* loop the producer to its cap. This renders the actual tree — every group, its
|
|
142
|
+
* requirements (statement / kind / priority) and their Given/When/Then acceptance
|
|
143
|
+
* criteria, plus the cross-cutting rules — so the reviewer (and the SPA reader, and
|
|
144
|
+
* downstream steps) see the spec itself, not the agent's chatter. Deterministic and
|
|
145
|
+
* dependency-free so it is safe to call at the ingest trust boundary.
|
|
146
|
+
*/
|
|
147
|
+
export function renderSpecForReview(spec) {
|
|
148
|
+
const lines = [`# Specification: ${spec.service}`];
|
|
149
|
+
if (spec.summary)
|
|
150
|
+
lines.push('', spec.summary);
|
|
151
|
+
for (const group of spec.groups ?? []) {
|
|
152
|
+
lines.push('', `## ${group.name}`);
|
|
153
|
+
if (group.summary)
|
|
154
|
+
lines.push('', group.summary);
|
|
155
|
+
for (const req of group.requirements ?? []) {
|
|
156
|
+
lines.push('', `### ${req.title} (${req.id})`, '', `- Kind: ${req.kind}`);
|
|
157
|
+
lines.push(`- Priority: ${req.priority}`);
|
|
158
|
+
lines.push(`- Statement: ${req.statement}`);
|
|
159
|
+
for (const ac of req.acceptance ?? []) {
|
|
160
|
+
lines.push(` - Acceptance ${ac.id}: GIVEN ${ac.given} WHEN ${ac.when} THEN ${ac.outcome}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const rules = spec.rules ?? [];
|
|
165
|
+
if (rules.length) {
|
|
166
|
+
lines.push('', '## Domain rules');
|
|
167
|
+
for (const rule of rules) {
|
|
168
|
+
lines.push(`- ${rule.rule}${rule.rationale ? ` (${rule.rationale})` : ''}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return lines.join('\n');
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=spec.js.map
|
package/dist/spec.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"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"}
|
package/dist/tasks.d.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
/** The external task trackers cat-factory can link to. */
|
|
3
|
+
export declare const taskSourceKindSchema: v.PicklistSchema<["jira", "github"], undefined>;
|
|
4
|
+
export type TaskSourceKind = v.InferOutput<typeof taskSourceKindSchema>;
|
|
5
|
+
/**
|
|
6
|
+
* Everything the frontend needs to render a source's connect form and import
|
|
7
|
+
* box without hard-coding any provider specifics.
|
|
8
|
+
*/
|
|
9
|
+
export declare const taskSourceDescriptorSchema: v.ObjectSchema<{
|
|
10
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
11
|
+
/** Display name, e.g. `Jira`. */
|
|
12
|
+
readonly label: v.StringSchema<undefined>;
|
|
13
|
+
/** Lucide icon name for the source. */
|
|
14
|
+
readonly icon: v.StringSchema<undefined>;
|
|
15
|
+
/** Credentials required to connect, in display order. */
|
|
16
|
+
readonly credentialFields: v.ArraySchema<v.ObjectSchema<{
|
|
17
|
+
readonly key: v.StringSchema<undefined>;
|
|
18
|
+
readonly label: v.StringSchema<undefined>;
|
|
19
|
+
readonly help: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
20
|
+
readonly placeholder: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
21
|
+
readonly secret: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
22
|
+
}, undefined>, undefined>;
|
|
23
|
+
/** Label for the "import an issue" input. */
|
|
24
|
+
readonly refLabel: v.StringSchema<undefined>;
|
|
25
|
+
/** Placeholder for the "import an issue" input. */
|
|
26
|
+
readonly refPlaceholder: v.StringSchema<undefined>;
|
|
27
|
+
/**
|
|
28
|
+
* Whether this source supports searching its catalogue by title/content (so
|
|
29
|
+
* the UI offers a search box, not just a paste-a-URL field). Optional for
|
|
30
|
+
* backward-compatibility; absent is treated as `false`.
|
|
31
|
+
*/
|
|
32
|
+
readonly searchable: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
33
|
+
}, undefined>;
|
|
34
|
+
export type TaskSourceDescriptor = v.InferOutput<typeof taskSourceDescriptorSchema>;
|
|
35
|
+
/** A workspace's connection to a task source, as exposed to clients (never the credentials). */
|
|
36
|
+
export declare const taskConnectionSchema: v.ObjectSchema<{
|
|
37
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
38
|
+
/** A human-friendly label for what we're connected to (site URL). */
|
|
39
|
+
readonly label: v.StringSchema<undefined>;
|
|
40
|
+
/** When the connection was established (epoch ms). */
|
|
41
|
+
readonly connectedAt: v.NumberSchema<undefined>;
|
|
42
|
+
}, undefined>;
|
|
43
|
+
export type TaskConnection = v.InferOutput<typeof taskConnectionSchema>;
|
|
44
|
+
/** A single comment on an issue, with its body normalized to Markdown. */
|
|
45
|
+
export declare const taskCommentSchema: v.ObjectSchema<{
|
|
46
|
+
/** Comment author's display name; '' when unknown. */
|
|
47
|
+
readonly author: v.StringSchema<undefined>;
|
|
48
|
+
/** Source-supplied creation timestamp, kept as the source's ISO string. */
|
|
49
|
+
readonly createdAt: v.StringSchema<undefined>;
|
|
50
|
+
/** Comment body, normalized to lightweight Markdown. */
|
|
51
|
+
readonly body: v.StringSchema<undefined>;
|
|
52
|
+
}, undefined>;
|
|
53
|
+
export type TaskComment = v.InferOutput<typeof taskCommentSchema>;
|
|
54
|
+
/** An issue imported from a source, projected locally as a structured record. */
|
|
55
|
+
export declare const sourceTaskSchema: v.ObjectSchema<{
|
|
56
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
57
|
+
/** The source's canonical key for the issue (e.g. a Jira issue key `PROJ-123`). */
|
|
58
|
+
readonly externalId: v.StringSchema<undefined>;
|
|
59
|
+
/** Issue summary / title. */
|
|
60
|
+
readonly title: v.StringSchema<undefined>;
|
|
61
|
+
/** Canonical URL of the issue on the source. */
|
|
62
|
+
readonly url: v.StringSchema<undefined>;
|
|
63
|
+
/** Workflow status name, e.g. `In Progress`. */
|
|
64
|
+
readonly status: v.StringSchema<undefined>;
|
|
65
|
+
/** Issue type name, e.g. `Bug`. */
|
|
66
|
+
readonly type: v.StringSchema<undefined>;
|
|
67
|
+
/** Assignee display name, or null when unassigned. */
|
|
68
|
+
readonly assignee: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
69
|
+
/** Priority name, or null when none. */
|
|
70
|
+
readonly priority: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
71
|
+
/** Issue labels. */
|
|
72
|
+
readonly labels: v.ArraySchema<v.StringSchema<undefined>, undefined>;
|
|
73
|
+
/** Issue description, normalized to lightweight Markdown. */
|
|
74
|
+
readonly description: v.StringSchema<undefined>;
|
|
75
|
+
/** Recent comments, oldest→newest, bodies normalized to Markdown. */
|
|
76
|
+
readonly comments: v.ArraySchema<v.ObjectSchema<{
|
|
77
|
+
/** Comment author's display name; '' when unknown. */
|
|
78
|
+
readonly author: v.StringSchema<undefined>;
|
|
79
|
+
/** Source-supplied creation timestamp, kept as the source's ISO string. */
|
|
80
|
+
readonly createdAt: v.StringSchema<undefined>;
|
|
81
|
+
/** Comment body, normalized to lightweight Markdown. */
|
|
82
|
+
readonly body: v.StringSchema<undefined>;
|
|
83
|
+
}, undefined>, undefined>;
|
|
84
|
+
/** A short plain-text excerpt of the issue (for list/preview rendering). */
|
|
85
|
+
readonly excerpt: v.StringSchema<undefined>;
|
|
86
|
+
/** The board block this issue is attached to as context, if any. */
|
|
87
|
+
readonly linkedBlockId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
88
|
+
/** When this projection row was last refreshed (epoch ms). */
|
|
89
|
+
readonly syncedAt: v.NumberSchema<undefined>;
|
|
90
|
+
}, undefined>;
|
|
91
|
+
export type SourceTask = v.InferOutput<typeof sourceTaskSchema>;
|
|
92
|
+
/**
|
|
93
|
+
* A single hit from searching a tracker. A lean shape (no description/comments)
|
|
94
|
+
* used to populate a picker: selecting one imports it (by `externalId`) and
|
|
95
|
+
* links it to a block. Distinct from {@link SourceTask} — a hit is not yet
|
|
96
|
+
* projected locally, so it carries no `linkedBlockId`/`syncedAt`.
|
|
97
|
+
*/
|
|
98
|
+
export declare const taskSearchResultSchema: v.ObjectSchema<{
|
|
99
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
100
|
+
/** The source's canonical key for the issue (re-usable as an import ref). */
|
|
101
|
+
readonly externalId: v.StringSchema<undefined>;
|
|
102
|
+
readonly title: v.StringSchema<undefined>;
|
|
103
|
+
/** Canonical URL of the issue on the source. */
|
|
104
|
+
readonly url: v.StringSchema<undefined>;
|
|
105
|
+
/** Workflow status name, e.g. `In Progress` (may be empty). */
|
|
106
|
+
readonly status: v.StringSchema<undefined>;
|
|
107
|
+
/** A short plain-text excerpt for the result row (may be empty). */
|
|
108
|
+
readonly excerpt: v.StringSchema<undefined>;
|
|
109
|
+
}, undefined>;
|
|
110
|
+
export type TaskSearchResult = v.InferOutput<typeof taskSearchResultSchema>;
|
|
111
|
+
/**
|
|
112
|
+
* Connect a workspace to a task source. The `credentials` bag is validated by
|
|
113
|
+
* the target provider (the `:source` is in the path), keeping the wire shape
|
|
114
|
+
* uniform across providers.
|
|
115
|
+
*/
|
|
116
|
+
export declare const connectTaskSourceSchema: v.ObjectSchema<{
|
|
117
|
+
readonly credentials: v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 2000, undefined>]>, undefined>;
|
|
118
|
+
}, undefined>;
|
|
119
|
+
export type ConnectTaskSourceInput = v.InferOutput<typeof connectTaskSourceSchema>;
|
|
120
|
+
/** Import (fetch + persist) an issue by its key or a full issue URL. */
|
|
121
|
+
export declare const importTaskSchema: v.ObjectSchema<{
|
|
122
|
+
readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 500, undefined>]>;
|
|
123
|
+
}, undefined>;
|
|
124
|
+
export type ImportTaskInput = v.InferOutput<typeof importTaskSchema>;
|
|
125
|
+
/** Search a tracker's issues by free text (title/content). */
|
|
126
|
+
export declare const searchTasksSchema: v.ObjectSchema<{
|
|
127
|
+
readonly query: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>;
|
|
128
|
+
}, undefined>;
|
|
129
|
+
export type SearchTasksInput = v.InferOutput<typeof searchTasksSchema>;
|
|
130
|
+
/** Attach an imported issue to a task as extra agent context. */
|
|
131
|
+
export declare const linkTaskSchema: v.ObjectSchema<{
|
|
132
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
133
|
+
readonly externalId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
|
|
134
|
+
readonly blockId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
|
|
135
|
+
}, undefined>;
|
|
136
|
+
export type LinkTaskInput = v.InferOutput<typeof linkTaskSchema>;
|
|
137
|
+
/**
|
|
138
|
+
* Materialise an imported issue as a new board task (a leaf block) inside a
|
|
139
|
+
* container (service frame or module), and link the issue to it for context. The
|
|
140
|
+
* issue must already be imported (its key is `externalId`). The new task's
|
|
141
|
+
* title/description are seeded from the issue.
|
|
142
|
+
*/
|
|
143
|
+
export declare const createTaskFromIssueSchema: v.ObjectSchema<{
|
|
144
|
+
readonly source: v.PicklistSchema<["jira", "github"], undefined>;
|
|
145
|
+
readonly externalId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
|
|
146
|
+
/** The frame or module the new task is created in. */
|
|
147
|
+
readonly containerId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>]>;
|
|
148
|
+
}, undefined>;
|
|
149
|
+
export type CreateTaskFromIssueInput = v.InferOutput<typeof createTaskFromIssueSchema>;
|
|
150
|
+
//# sourceMappingURL=tasks.d.ts.map
|