@ever-works/contracts 1.0.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/README.md +62 -0
- package/dist/api/index.cjs +395 -0
- package/dist/api/index.d.cts +2171 -0
- package/dist/api/index.d.ts +2171 -0
- package/dist/api/index.js +335 -0
- package/dist/domain/index.cjs +335 -0
- package/dist/domain/index.d.cts +316 -0
- package/dist/domain/index.d.ts +316 -0
- package/dist/domain/index.js +317 -0
- package/dist/feed.types-BWk3CHqj.d.cts +355 -0
- package/dist/feed.types-BWk3CHqj.d.ts +355 -0
- package/dist/form/index.cjs +2 -0
- package/dist/form/index.d.cts +104 -0
- package/dist/form/index.d.ts +104 -0
- package/dist/form/index.js +1 -0
- package/dist/index.cjs +6968 -0
- package/dist/index.d.cts +11815 -0
- package/dist/index.d.ts +11815 -0
- package/dist/index.js +6019 -0
- package/dist/item/index.cjs +2 -0
- package/dist/item/index.d.cts +195 -0
- package/dist/item/index.d.ts +195 -0
- package/dist/item/index.js +1 -0
- package/dist/telemetry/index.cjs +15 -0
- package/dist/telemetry/index.d.cts +120 -0
- package/dist/telemetry/index.d.ts +120 -0
- package/dist/telemetry/index.js +13 -0
- package/package.json +81 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain type classification for work content
|
|
3
|
+
*/
|
|
4
|
+
declare enum DomainType {
|
|
5
|
+
SOFTWARE = "software",
|
|
6
|
+
ECOMMERCE = "ecommerce",
|
|
7
|
+
SERVICES = "services",
|
|
8
|
+
GENERAL = "general"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Result of domain analysis for a work
|
|
12
|
+
*/
|
|
13
|
+
interface DomainAnalysis {
|
|
14
|
+
/** The detected domain type */
|
|
15
|
+
readonly domain_type: DomainType;
|
|
16
|
+
/** Confidence score from 0.0 to 1.0 */
|
|
17
|
+
readonly confidence: number;
|
|
18
|
+
/** The noun used to describe items in this domain (e.g., "tool", "product") */
|
|
19
|
+
readonly item_noun?: string;
|
|
20
|
+
/** Expected attributes for items in this domain */
|
|
21
|
+
readonly expected_attributes?: readonly string[];
|
|
22
|
+
/** URL patterns that indicate official sources */
|
|
23
|
+
readonly official_source_patterns?: readonly string[];
|
|
24
|
+
/** Domains known to be aggregators rather than official sources */
|
|
25
|
+
readonly aggregator_domains?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Web page data retrieved during content extraction
|
|
29
|
+
*/
|
|
30
|
+
interface WebPageData {
|
|
31
|
+
/** The source URL of the page */
|
|
32
|
+
readonly source_url: string;
|
|
33
|
+
/** ISO date string when the content was retrieved */
|
|
34
|
+
readonly retrieved_at: string;
|
|
35
|
+
/** Raw content extracted from the page */
|
|
36
|
+
readonly raw_content: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Relevance assessment for a piece of content
|
|
40
|
+
*/
|
|
41
|
+
interface RelevanceAssessment {
|
|
42
|
+
/** Whether the content is relevant */
|
|
43
|
+
readonly relevant: boolean;
|
|
44
|
+
/** Relevance score from 0.0 to 1.0 */
|
|
45
|
+
readonly relevance_score: number;
|
|
46
|
+
/** Human-readable reason for the assessment */
|
|
47
|
+
readonly reason: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Work "kind" vocabulary — the single source of truth shared by the API,
|
|
52
|
+
* the agent package and the web app.
|
|
53
|
+
*
|
|
54
|
+
* This lives in `@ever-works/contracts` rather than in the TypeORM entity
|
|
55
|
+
* because `apps/web` deliberately does not depend on `@ever-works/agent`;
|
|
56
|
+
* contracts is the only package both sides import at runtime. The entity
|
|
57
|
+
* (`packages/agent/src/entities/work.entity.ts`) re-exports from here so
|
|
58
|
+
* there is exactly one list to extend when a new kind ships.
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* Kinds a user can pick from the chip catalog at creation time.
|
|
62
|
+
*
|
|
63
|
+
* `company` is deliberately absent: Company Works are minted only through
|
|
64
|
+
* the dedicated Register-Company flow (`WorkLifecycleService.createCompanyWork`),
|
|
65
|
+
* never through the general create path.
|
|
66
|
+
*
|
|
67
|
+
* `repo` (chip label "Repository") is the one selectable kind that is NOT a
|
|
68
|
+
* generated site: it registers an EXISTING code repository — the platform
|
|
69
|
+
* monorepo, a template repo, a website repo — as a first-class Work so
|
|
70
|
+
* Tasks, Goals and fleet runs can attach to it (self-build slice D,
|
|
71
|
+
* EW-766). Its data repository IS the code repository; see
|
|
72
|
+
* `WORK_KIND_CAPABILITIES.repo`.
|
|
73
|
+
*/
|
|
74
|
+
declare const USER_SELECTABLE_WORK_KINDS: readonly ["website", "landing-page", "blog", "directory", "awesome-repo", "repo"];
|
|
75
|
+
type UserSelectableWorkKind = (typeof USER_SELECTABLE_WORK_KINDS)[number];
|
|
76
|
+
/**
|
|
77
|
+
* Every kind a persisted `work.kind` may hold.
|
|
78
|
+
*
|
|
79
|
+
* - `default` — the column default. Carried by every Work created before
|
|
80
|
+
* the kind-aware create path shipped, which is the overwhelming majority
|
|
81
|
+
* of existing rows. It must behave identically to `directory`; see
|
|
82
|
+
* `WORK_KIND_CAPABILITIES` for why that invariant is load-bearing.
|
|
83
|
+
* - `company` — see above.
|
|
84
|
+
* - `campaign` — a go-to-market campaign Work: the artifact home for the
|
|
85
|
+
* lead lists, drafts, and reports a go-to-market pipeline produces. Like
|
|
86
|
+
* `company` it is minted by a dedicated flow (template activation), not
|
|
87
|
+
* by the general create path, so it stays out of the chip catalog.
|
|
88
|
+
*/
|
|
89
|
+
declare const WORK_KINDS: readonly ["website", "landing-page", "blog", "directory", "awesome-repo", "repo", "company", "campaign", "default"];
|
|
90
|
+
type WorkKind = (typeof WORK_KINDS)[number];
|
|
91
|
+
/**
|
|
92
|
+
* Coerce an arbitrary value into a known `WorkKind`.
|
|
93
|
+
*
|
|
94
|
+
* `work.kind` is persisted as `varchar(32)` and modelled as an open string
|
|
95
|
+
* union so the server can ship a new kind without a coordinated web deploy.
|
|
96
|
+
* Every consumer must therefore route unknown values through here and get
|
|
97
|
+
* the safe generic `default` behaviour rather than crashing or silently
|
|
98
|
+
* mis-rendering.
|
|
99
|
+
*
|
|
100
|
+
* `landing` is accepted as an alias for `landing-page`.
|
|
101
|
+
*
|
|
102
|
+
* NEVER throws.
|
|
103
|
+
*/
|
|
104
|
+
declare function normalizeWorkKind(value?: string | null): WorkKind;
|
|
105
|
+
/** True when `value` is a kind the create-path chip catalog offers. */
|
|
106
|
+
declare function isUserSelectableWorkKind(value?: string | null): value is UserSelectableWorkKind;
|
|
107
|
+
/**
|
|
108
|
+
* True when `value` names the Repository kind (`repo`) — the one kind whose
|
|
109
|
+
* data repository is a code repository the user already owns rather than
|
|
110
|
+
* something the platform generated (self-build slice D, EW-766).
|
|
111
|
+
*
|
|
112
|
+
* This is deliberately a KIND test rather than a capability test. The
|
|
113
|
+
* content pipelines (item generation, README regeneration, deployment) are
|
|
114
|
+
* not capability-gated for any kind today; what is special about a
|
|
115
|
+
* Repository Work is not "it has no items" — a Company Work has none either
|
|
116
|
+
* — but that running the directory pipeline against its data repository
|
|
117
|
+
* would write generated scaffolding into a human's source tree. Callers
|
|
118
|
+
* that must never touch that repository check this predicate. Accepts the
|
|
119
|
+
* same loose input as `normalizeWorkKind` and never throws.
|
|
120
|
+
*/
|
|
121
|
+
declare function isRepositoryWorkKind(value?: string | null): boolean;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Goal "kind" vocabulary — the single source of truth shared by the API,
|
|
125
|
+
* the agent package, the MCP server and the web app.
|
|
126
|
+
*
|
|
127
|
+
* Lives in `@ever-works/contracts` for the same reason `work-kind.ts` does:
|
|
128
|
+
* `apps/web` deliberately does not depend on `@ever-works/agent`, and
|
|
129
|
+
* contracts is the only package every side imports. The Goal entity
|
|
130
|
+
* (`packages/agent/src/entities/goal.entity.ts`) re-exports from here so
|
|
131
|
+
* there is exactly one list to extend when a new kind ships.
|
|
132
|
+
*
|
|
133
|
+
* - `metric` — the original Goal: reads a number from a metrics-provider
|
|
134
|
+
* plugin on a schedule and completes when the comparator is
|
|
135
|
+
* satisfied against `targetValue`. Every row that predates
|
|
136
|
+
* the `goalKind` column is a metric Goal.
|
|
137
|
+
* - `delivery` — "ship feature X across three repos": there is NO metric,
|
|
138
|
+
* no comparator and no target value. The Goal completes on
|
|
139
|
+
* its approved Definition of Done alone — every approved
|
|
140
|
+
* criterion done or waived — and is otherwise driven by the
|
|
141
|
+
* same iteration loop and budget rules as a metric Goal.
|
|
142
|
+
*/
|
|
143
|
+
declare const GOAL_KINDS: readonly ["metric", "delivery"];
|
|
144
|
+
type GoalKind = (typeof GOAL_KINDS)[number];
|
|
145
|
+
/** The column default, and what every pre-existing Goal row reads as. */
|
|
146
|
+
declare const DEFAULT_GOAL_KIND: GoalKind;
|
|
147
|
+
/**
|
|
148
|
+
* Type guard for WRITE paths. Fail closed: an unknown kind is rejected by
|
|
149
|
+
* the caller, never coerced — a Goal that is neither metric nor delivery
|
|
150
|
+
* has no completion rule and must not be persisted.
|
|
151
|
+
*/
|
|
152
|
+
declare function isGoalKind(value: unknown): value is GoalKind;
|
|
153
|
+
/**
|
|
154
|
+
* Coerce an arbitrary value into a known `GoalKind` for READ paths only.
|
|
155
|
+
*
|
|
156
|
+
* `goals.goalKind` is `varchar(16)`, so a row written by a newer server (or
|
|
157
|
+
* by hand) may carry a value this build does not know. Rendering it as the
|
|
158
|
+
* generic `metric` behaviour is the safe default for a display surface; a
|
|
159
|
+
* write path must use {@link isGoalKind} instead.
|
|
160
|
+
*
|
|
161
|
+
* NEVER throws.
|
|
162
|
+
*/
|
|
163
|
+
declare function normalizeGoalKind(value?: string | null): GoalKind;
|
|
164
|
+
/** True when `value` names the Delivery kind. Accepts loose input; never throws. */
|
|
165
|
+
declare function isDeliveryGoalKind(value?: string | null): boolean;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Per-Work-kind metric vocabulary.
|
|
169
|
+
*
|
|
170
|
+
* A Work's headline statistics depend on what the Work *is*: counting
|
|
171
|
+
* "Total Items" on a landing page is noise, and counting "Comparisons" on a
|
|
172
|
+
* blog is meaningless. The kind → metric mapping lives in
|
|
173
|
+
* `work-capabilities.ts`; this module defines the metrics themselves.
|
|
174
|
+
*
|
|
175
|
+
* Definitions are data, not components — `@ever-works/contracts` is
|
|
176
|
+
* framework-free and must stay importable from the API, the agent package
|
|
177
|
+
* and the web app alike. The web app maps `WorkMetricDefinition.id` to a
|
|
178
|
+
* Lucide icon in its own presentation layer.
|
|
179
|
+
*/
|
|
180
|
+
/** Every metric the platform can render on a Work. */
|
|
181
|
+
declare const WORK_METRIC_IDS: readonly ["total-items", "posts", "categories", "tags", "comparisons", "generation-status", "deploy-status", "days-active", "registered-users", "team-members", "agents", "open-tasks", "works-owned", "page-views", "sessions", "conversions"];
|
|
182
|
+
type WorkMetricId = (typeof WORK_METRIC_IDS)[number];
|
|
183
|
+
/**
|
|
184
|
+
* Where a metric's value comes from. Drives which resolver runs and, when
|
|
185
|
+
* the value is unavailable, which remediation hint the UI offers.
|
|
186
|
+
*/
|
|
187
|
+
type WorkMetricSource =
|
|
188
|
+
/** Read straight off the Work row — always available. */
|
|
189
|
+
'work-column'
|
|
190
|
+
/** Computed from Work columns (e.g. days since creation). */
|
|
191
|
+
| 'derived'
|
|
192
|
+
/** A cheap `COUNT(*)` against a table the platform owns. */
|
|
193
|
+
| 'db-count'
|
|
194
|
+
/** Supplied by a connected metrics-provider plugin. */
|
|
195
|
+
| 'provider';
|
|
196
|
+
/** How the raw number should be presented. */
|
|
197
|
+
type WorkMetricFormat = 'integer' | 'percent' | 'duration-days' | 'status';
|
|
198
|
+
/**
|
|
199
|
+
* Message keys under `dashboard.workDetail.stats`.
|
|
200
|
+
*
|
|
201
|
+
* A literal union rather than `string`: the web app looks these up through
|
|
202
|
+
* next-intl, whose `useTranslations` type-checks keys against the message
|
|
203
|
+
* catalogue at compile time. Widening this to `string` would silently opt
|
|
204
|
+
* every tile label out of that check.
|
|
205
|
+
*/
|
|
206
|
+
type WorkMetricLabelKey = 'totalItems' | 'posts' | 'categories' | 'tags' | 'comparisons' | 'generationStatus' | 'deployStatus' | 'daysActive' | 'registeredUsers' | 'teamMembers' | 'agents' | 'openTasks' | 'worksOwned' | 'pageViews' | 'sessions' | 'conversions';
|
|
207
|
+
interface WorkMetricDefinition {
|
|
208
|
+
readonly id: WorkMetricId;
|
|
209
|
+
/**
|
|
210
|
+
* Key under `dashboard.workDetail.stats` in the web app's messages.
|
|
211
|
+
* Kept as a key rather than a label so contracts stays locale-free.
|
|
212
|
+
*/
|
|
213
|
+
readonly labelKey: WorkMetricLabelKey;
|
|
214
|
+
readonly source: WorkMetricSource;
|
|
215
|
+
readonly format: WorkMetricFormat;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* The resolution state of a single metric.
|
|
219
|
+
*
|
|
220
|
+
* Distinguishing these from a plain `0` is the whole point: a Website Work
|
|
221
|
+
* that has never had analytics connected has *unknown* page views, not zero
|
|
222
|
+
* page views, and showing "0" reads as a broken product.
|
|
223
|
+
*/
|
|
224
|
+
type WorkMetricState = 'ok'
|
|
225
|
+
/** No analytics/metrics provider is connected to this Work yet. */
|
|
226
|
+
| 'not_configured'
|
|
227
|
+
/** Metric needs a deployment that does not exist yet. */
|
|
228
|
+
| 'not_deployed'
|
|
229
|
+
/** Metric needs content generation that has not run yet. */
|
|
230
|
+
| 'not_generated'
|
|
231
|
+
/** Resolution failed. Never fatal — the tile degrades, the page renders. */
|
|
232
|
+
| 'error';
|
|
233
|
+
interface WorkMetricValue {
|
|
234
|
+
readonly id: WorkMetricId;
|
|
235
|
+
readonly state: WorkMetricState;
|
|
236
|
+
/** Present only when `state === 'ok'`. */
|
|
237
|
+
readonly value?: number | string;
|
|
238
|
+
/**
|
|
239
|
+
* Change versus the previous comparable period, as a signed ratio
|
|
240
|
+
* (`0.12` = +12%). Omitted when a comparison is unavailable or would be
|
|
241
|
+
* expensive.
|
|
242
|
+
*/
|
|
243
|
+
readonly delta?: number;
|
|
244
|
+
}
|
|
245
|
+
declare const WORK_METRIC_DEFINITIONS: Record<WorkMetricId, WorkMetricDefinition>;
|
|
246
|
+
/** Definition lookup that tolerates an unknown id from a newer server. */
|
|
247
|
+
declare function getWorkMetricDefinition(id: string): WorkMetricDefinition | undefined;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* What a Work of a given kind actually has.
|
|
251
|
+
*
|
|
252
|
+
* Before this registry, "given `work.kind`, what does this Work support?"
|
|
253
|
+
* was answered independently in half a dozen places — the create-page chip
|
|
254
|
+
* catalogs, the website-template resolver, and (mostly) nowhere at all,
|
|
255
|
+
* because every surface simply assumed a directory. That is why a Landing
|
|
256
|
+
* Page Work shows an Items tab and a "Total Items: 0" tile.
|
|
257
|
+
*
|
|
258
|
+
* Every kind-conditional decision in the platform should route through
|
|
259
|
+
* `getWorkCapabilities()` rather than testing `kind === 'directory'` inline.
|
|
260
|
+
*/
|
|
261
|
+
interface WorkCapabilities {
|
|
262
|
+
/**
|
|
263
|
+
* The Items surface: the Items tab, the `/items` routes, and the
|
|
264
|
+
* submission / import / export endpoints that operate on them.
|
|
265
|
+
* `labelKey` lets a kind keep the machinery but rename it — a blog's
|
|
266
|
+
* items are "posts", a website's are "pages".
|
|
267
|
+
*/
|
|
268
|
+
readonly items: {
|
|
269
|
+
readonly enabled: boolean;
|
|
270
|
+
readonly labelKey: 'items' | 'posts' | 'pages';
|
|
271
|
+
};
|
|
272
|
+
/** Categories / tags / collections CRUD and their tiles. */
|
|
273
|
+
readonly taxonomy: boolean;
|
|
274
|
+
/** The comparison generator sub-tab and its endpoints. */
|
|
275
|
+
readonly comparisons: boolean;
|
|
276
|
+
/** Community pull-request intake settings and processing. */
|
|
277
|
+
readonly communityPr: boolean;
|
|
278
|
+
/** Bulk item import / export. */
|
|
279
|
+
readonly itemImportExport: boolean;
|
|
280
|
+
/** Source-URL validation for items. */
|
|
281
|
+
readonly sourceValidation: boolean;
|
|
282
|
+
/** The Deploy tab and deployment endpoints. */
|
|
283
|
+
readonly deploy: boolean;
|
|
284
|
+
/** The knowledge-base workbench. */
|
|
285
|
+
readonly kb: boolean;
|
|
286
|
+
/** Ordered metric tiles rendered on the Overview tab. */
|
|
287
|
+
readonly metrics: readonly WorkMetricId[];
|
|
288
|
+
/**
|
|
289
|
+
* Which repositories this kind provisions.
|
|
290
|
+
*
|
|
291
|
+
* ⚠️ These keys are the PERSISTED `RepositoryRole` values and must not
|
|
292
|
+
* be renamed to match the newer UI labels. Mapping, for the avoidable
|
|
293
|
+
* confusion it saves: `data` → "Data Repository", `work` → the
|
|
294
|
+
* "{provider} Repository" shown to users, `website` → the "Work
|
|
295
|
+
* Repository" (the template output, which is not always a website).
|
|
296
|
+
*/
|
|
297
|
+
readonly repos: {
|
|
298
|
+
readonly data: boolean;
|
|
299
|
+
readonly work: boolean;
|
|
300
|
+
readonly website: boolean;
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
declare const WORK_KIND_CAPABILITIES: Record<WorkKind, WorkCapabilities>;
|
|
304
|
+
/**
|
|
305
|
+
* Capabilities for a possibly-unknown kind.
|
|
306
|
+
*
|
|
307
|
+
* ALWAYS use this instead of indexing `WORK_KIND_CAPABILITIES` directly.
|
|
308
|
+
* `work.kind` is an open string union — a server can ship a kind this build
|
|
309
|
+
* has never heard of, and indexing would hand back `undefined` and crash
|
|
310
|
+
* whatever destructured it.
|
|
311
|
+
*/
|
|
312
|
+
declare function getWorkCapabilities(kind?: string | null): WorkCapabilities;
|
|
313
|
+
/** Convenience predicate — the Items tab / routes are meaningful here. */
|
|
314
|
+
declare function workKindHasItems(kind?: string | null): boolean;
|
|
315
|
+
|
|
316
|
+
export { DEFAULT_GOAL_KIND, type DomainAnalysis, DomainType, GOAL_KINDS, type GoalKind, type RelevanceAssessment, USER_SELECTABLE_WORK_KINDS, type UserSelectableWorkKind, WORK_KINDS, WORK_KIND_CAPABILITIES, WORK_METRIC_DEFINITIONS, WORK_METRIC_IDS, type WebPageData, type WorkCapabilities, type WorkKind, type WorkMetricDefinition, type WorkMetricFormat, type WorkMetricId, type WorkMetricLabelKey, type WorkMetricSource, type WorkMetricState, type WorkMetricValue, getWorkCapabilities, getWorkMetricDefinition, isDeliveryGoalKind, isGoalKind, isRepositoryWorkKind, isUserSelectableWorkKind, normalizeGoalKind, normalizeWorkKind, workKindHasItems };
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain type classification for work content
|
|
3
|
+
*/
|
|
4
|
+
declare enum DomainType {
|
|
5
|
+
SOFTWARE = "software",
|
|
6
|
+
ECOMMERCE = "ecommerce",
|
|
7
|
+
SERVICES = "services",
|
|
8
|
+
GENERAL = "general"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Result of domain analysis for a work
|
|
12
|
+
*/
|
|
13
|
+
interface DomainAnalysis {
|
|
14
|
+
/** The detected domain type */
|
|
15
|
+
readonly domain_type: DomainType;
|
|
16
|
+
/** Confidence score from 0.0 to 1.0 */
|
|
17
|
+
readonly confidence: number;
|
|
18
|
+
/** The noun used to describe items in this domain (e.g., "tool", "product") */
|
|
19
|
+
readonly item_noun?: string;
|
|
20
|
+
/** Expected attributes for items in this domain */
|
|
21
|
+
readonly expected_attributes?: readonly string[];
|
|
22
|
+
/** URL patterns that indicate official sources */
|
|
23
|
+
readonly official_source_patterns?: readonly string[];
|
|
24
|
+
/** Domains known to be aggregators rather than official sources */
|
|
25
|
+
readonly aggregator_domains?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Web page data retrieved during content extraction
|
|
29
|
+
*/
|
|
30
|
+
interface WebPageData {
|
|
31
|
+
/** The source URL of the page */
|
|
32
|
+
readonly source_url: string;
|
|
33
|
+
/** ISO date string when the content was retrieved */
|
|
34
|
+
readonly retrieved_at: string;
|
|
35
|
+
/** Raw content extracted from the page */
|
|
36
|
+
readonly raw_content: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Relevance assessment for a piece of content
|
|
40
|
+
*/
|
|
41
|
+
interface RelevanceAssessment {
|
|
42
|
+
/** Whether the content is relevant */
|
|
43
|
+
readonly relevant: boolean;
|
|
44
|
+
/** Relevance score from 0.0 to 1.0 */
|
|
45
|
+
readonly relevance_score: number;
|
|
46
|
+
/** Human-readable reason for the assessment */
|
|
47
|
+
readonly reason: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Work "kind" vocabulary — the single source of truth shared by the API,
|
|
52
|
+
* the agent package and the web app.
|
|
53
|
+
*
|
|
54
|
+
* This lives in `@ever-works/contracts` rather than in the TypeORM entity
|
|
55
|
+
* because `apps/web` deliberately does not depend on `@ever-works/agent`;
|
|
56
|
+
* contracts is the only package both sides import at runtime. The entity
|
|
57
|
+
* (`packages/agent/src/entities/work.entity.ts`) re-exports from here so
|
|
58
|
+
* there is exactly one list to extend when a new kind ships.
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* Kinds a user can pick from the chip catalog at creation time.
|
|
62
|
+
*
|
|
63
|
+
* `company` is deliberately absent: Company Works are minted only through
|
|
64
|
+
* the dedicated Register-Company flow (`WorkLifecycleService.createCompanyWork`),
|
|
65
|
+
* never through the general create path.
|
|
66
|
+
*
|
|
67
|
+
* `repo` (chip label "Repository") is the one selectable kind that is NOT a
|
|
68
|
+
* generated site: it registers an EXISTING code repository — the platform
|
|
69
|
+
* monorepo, a template repo, a website repo — as a first-class Work so
|
|
70
|
+
* Tasks, Goals and fleet runs can attach to it (self-build slice D,
|
|
71
|
+
* EW-766). Its data repository IS the code repository; see
|
|
72
|
+
* `WORK_KIND_CAPABILITIES.repo`.
|
|
73
|
+
*/
|
|
74
|
+
declare const USER_SELECTABLE_WORK_KINDS: readonly ["website", "landing-page", "blog", "directory", "awesome-repo", "repo"];
|
|
75
|
+
type UserSelectableWorkKind = (typeof USER_SELECTABLE_WORK_KINDS)[number];
|
|
76
|
+
/**
|
|
77
|
+
* Every kind a persisted `work.kind` may hold.
|
|
78
|
+
*
|
|
79
|
+
* - `default` — the column default. Carried by every Work created before
|
|
80
|
+
* the kind-aware create path shipped, which is the overwhelming majority
|
|
81
|
+
* of existing rows. It must behave identically to `directory`; see
|
|
82
|
+
* `WORK_KIND_CAPABILITIES` for why that invariant is load-bearing.
|
|
83
|
+
* - `company` — see above.
|
|
84
|
+
* - `campaign` — a go-to-market campaign Work: the artifact home for the
|
|
85
|
+
* lead lists, drafts, and reports a go-to-market pipeline produces. Like
|
|
86
|
+
* `company` it is minted by a dedicated flow (template activation), not
|
|
87
|
+
* by the general create path, so it stays out of the chip catalog.
|
|
88
|
+
*/
|
|
89
|
+
declare const WORK_KINDS: readonly ["website", "landing-page", "blog", "directory", "awesome-repo", "repo", "company", "campaign", "default"];
|
|
90
|
+
type WorkKind = (typeof WORK_KINDS)[number];
|
|
91
|
+
/**
|
|
92
|
+
* Coerce an arbitrary value into a known `WorkKind`.
|
|
93
|
+
*
|
|
94
|
+
* `work.kind` is persisted as `varchar(32)` and modelled as an open string
|
|
95
|
+
* union so the server can ship a new kind without a coordinated web deploy.
|
|
96
|
+
* Every consumer must therefore route unknown values through here and get
|
|
97
|
+
* the safe generic `default` behaviour rather than crashing or silently
|
|
98
|
+
* mis-rendering.
|
|
99
|
+
*
|
|
100
|
+
* `landing` is accepted as an alias for `landing-page`.
|
|
101
|
+
*
|
|
102
|
+
* NEVER throws.
|
|
103
|
+
*/
|
|
104
|
+
declare function normalizeWorkKind(value?: string | null): WorkKind;
|
|
105
|
+
/** True when `value` is a kind the create-path chip catalog offers. */
|
|
106
|
+
declare function isUserSelectableWorkKind(value?: string | null): value is UserSelectableWorkKind;
|
|
107
|
+
/**
|
|
108
|
+
* True when `value` names the Repository kind (`repo`) — the one kind whose
|
|
109
|
+
* data repository is a code repository the user already owns rather than
|
|
110
|
+
* something the platform generated (self-build slice D, EW-766).
|
|
111
|
+
*
|
|
112
|
+
* This is deliberately a KIND test rather than a capability test. The
|
|
113
|
+
* content pipelines (item generation, README regeneration, deployment) are
|
|
114
|
+
* not capability-gated for any kind today; what is special about a
|
|
115
|
+
* Repository Work is not "it has no items" — a Company Work has none either
|
|
116
|
+
* — but that running the directory pipeline against its data repository
|
|
117
|
+
* would write generated scaffolding into a human's source tree. Callers
|
|
118
|
+
* that must never touch that repository check this predicate. Accepts the
|
|
119
|
+
* same loose input as `normalizeWorkKind` and never throws.
|
|
120
|
+
*/
|
|
121
|
+
declare function isRepositoryWorkKind(value?: string | null): boolean;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Goal "kind" vocabulary — the single source of truth shared by the API,
|
|
125
|
+
* the agent package, the MCP server and the web app.
|
|
126
|
+
*
|
|
127
|
+
* Lives in `@ever-works/contracts` for the same reason `work-kind.ts` does:
|
|
128
|
+
* `apps/web` deliberately does not depend on `@ever-works/agent`, and
|
|
129
|
+
* contracts is the only package every side imports. The Goal entity
|
|
130
|
+
* (`packages/agent/src/entities/goal.entity.ts`) re-exports from here so
|
|
131
|
+
* there is exactly one list to extend when a new kind ships.
|
|
132
|
+
*
|
|
133
|
+
* - `metric` — the original Goal: reads a number from a metrics-provider
|
|
134
|
+
* plugin on a schedule and completes when the comparator is
|
|
135
|
+
* satisfied against `targetValue`. Every row that predates
|
|
136
|
+
* the `goalKind` column is a metric Goal.
|
|
137
|
+
* - `delivery` — "ship feature X across three repos": there is NO metric,
|
|
138
|
+
* no comparator and no target value. The Goal completes on
|
|
139
|
+
* its approved Definition of Done alone — every approved
|
|
140
|
+
* criterion done or waived — and is otherwise driven by the
|
|
141
|
+
* same iteration loop and budget rules as a metric Goal.
|
|
142
|
+
*/
|
|
143
|
+
declare const GOAL_KINDS: readonly ["metric", "delivery"];
|
|
144
|
+
type GoalKind = (typeof GOAL_KINDS)[number];
|
|
145
|
+
/** The column default, and what every pre-existing Goal row reads as. */
|
|
146
|
+
declare const DEFAULT_GOAL_KIND: GoalKind;
|
|
147
|
+
/**
|
|
148
|
+
* Type guard for WRITE paths. Fail closed: an unknown kind is rejected by
|
|
149
|
+
* the caller, never coerced — a Goal that is neither metric nor delivery
|
|
150
|
+
* has no completion rule and must not be persisted.
|
|
151
|
+
*/
|
|
152
|
+
declare function isGoalKind(value: unknown): value is GoalKind;
|
|
153
|
+
/**
|
|
154
|
+
* Coerce an arbitrary value into a known `GoalKind` for READ paths only.
|
|
155
|
+
*
|
|
156
|
+
* `goals.goalKind` is `varchar(16)`, so a row written by a newer server (or
|
|
157
|
+
* by hand) may carry a value this build does not know. Rendering it as the
|
|
158
|
+
* generic `metric` behaviour is the safe default for a display surface; a
|
|
159
|
+
* write path must use {@link isGoalKind} instead.
|
|
160
|
+
*
|
|
161
|
+
* NEVER throws.
|
|
162
|
+
*/
|
|
163
|
+
declare function normalizeGoalKind(value?: string | null): GoalKind;
|
|
164
|
+
/** True when `value` names the Delivery kind. Accepts loose input; never throws. */
|
|
165
|
+
declare function isDeliveryGoalKind(value?: string | null): boolean;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Per-Work-kind metric vocabulary.
|
|
169
|
+
*
|
|
170
|
+
* A Work's headline statistics depend on what the Work *is*: counting
|
|
171
|
+
* "Total Items" on a landing page is noise, and counting "Comparisons" on a
|
|
172
|
+
* blog is meaningless. The kind → metric mapping lives in
|
|
173
|
+
* `work-capabilities.ts`; this module defines the metrics themselves.
|
|
174
|
+
*
|
|
175
|
+
* Definitions are data, not components — `@ever-works/contracts` is
|
|
176
|
+
* framework-free and must stay importable from the API, the agent package
|
|
177
|
+
* and the web app alike. The web app maps `WorkMetricDefinition.id` to a
|
|
178
|
+
* Lucide icon in its own presentation layer.
|
|
179
|
+
*/
|
|
180
|
+
/** Every metric the platform can render on a Work. */
|
|
181
|
+
declare const WORK_METRIC_IDS: readonly ["total-items", "posts", "categories", "tags", "comparisons", "generation-status", "deploy-status", "days-active", "registered-users", "team-members", "agents", "open-tasks", "works-owned", "page-views", "sessions", "conversions"];
|
|
182
|
+
type WorkMetricId = (typeof WORK_METRIC_IDS)[number];
|
|
183
|
+
/**
|
|
184
|
+
* Where a metric's value comes from. Drives which resolver runs and, when
|
|
185
|
+
* the value is unavailable, which remediation hint the UI offers.
|
|
186
|
+
*/
|
|
187
|
+
type WorkMetricSource =
|
|
188
|
+
/** Read straight off the Work row — always available. */
|
|
189
|
+
'work-column'
|
|
190
|
+
/** Computed from Work columns (e.g. days since creation). */
|
|
191
|
+
| 'derived'
|
|
192
|
+
/** A cheap `COUNT(*)` against a table the platform owns. */
|
|
193
|
+
| 'db-count'
|
|
194
|
+
/** Supplied by a connected metrics-provider plugin. */
|
|
195
|
+
| 'provider';
|
|
196
|
+
/** How the raw number should be presented. */
|
|
197
|
+
type WorkMetricFormat = 'integer' | 'percent' | 'duration-days' | 'status';
|
|
198
|
+
/**
|
|
199
|
+
* Message keys under `dashboard.workDetail.stats`.
|
|
200
|
+
*
|
|
201
|
+
* A literal union rather than `string`: the web app looks these up through
|
|
202
|
+
* next-intl, whose `useTranslations` type-checks keys against the message
|
|
203
|
+
* catalogue at compile time. Widening this to `string` would silently opt
|
|
204
|
+
* every tile label out of that check.
|
|
205
|
+
*/
|
|
206
|
+
type WorkMetricLabelKey = 'totalItems' | 'posts' | 'categories' | 'tags' | 'comparisons' | 'generationStatus' | 'deployStatus' | 'daysActive' | 'registeredUsers' | 'teamMembers' | 'agents' | 'openTasks' | 'worksOwned' | 'pageViews' | 'sessions' | 'conversions';
|
|
207
|
+
interface WorkMetricDefinition {
|
|
208
|
+
readonly id: WorkMetricId;
|
|
209
|
+
/**
|
|
210
|
+
* Key under `dashboard.workDetail.stats` in the web app's messages.
|
|
211
|
+
* Kept as a key rather than a label so contracts stays locale-free.
|
|
212
|
+
*/
|
|
213
|
+
readonly labelKey: WorkMetricLabelKey;
|
|
214
|
+
readonly source: WorkMetricSource;
|
|
215
|
+
readonly format: WorkMetricFormat;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* The resolution state of a single metric.
|
|
219
|
+
*
|
|
220
|
+
* Distinguishing these from a plain `0` is the whole point: a Website Work
|
|
221
|
+
* that has never had analytics connected has *unknown* page views, not zero
|
|
222
|
+
* page views, and showing "0" reads as a broken product.
|
|
223
|
+
*/
|
|
224
|
+
type WorkMetricState = 'ok'
|
|
225
|
+
/** No analytics/metrics provider is connected to this Work yet. */
|
|
226
|
+
| 'not_configured'
|
|
227
|
+
/** Metric needs a deployment that does not exist yet. */
|
|
228
|
+
| 'not_deployed'
|
|
229
|
+
/** Metric needs content generation that has not run yet. */
|
|
230
|
+
| 'not_generated'
|
|
231
|
+
/** Resolution failed. Never fatal — the tile degrades, the page renders. */
|
|
232
|
+
| 'error';
|
|
233
|
+
interface WorkMetricValue {
|
|
234
|
+
readonly id: WorkMetricId;
|
|
235
|
+
readonly state: WorkMetricState;
|
|
236
|
+
/** Present only when `state === 'ok'`. */
|
|
237
|
+
readonly value?: number | string;
|
|
238
|
+
/**
|
|
239
|
+
* Change versus the previous comparable period, as a signed ratio
|
|
240
|
+
* (`0.12` = +12%). Omitted when a comparison is unavailable or would be
|
|
241
|
+
* expensive.
|
|
242
|
+
*/
|
|
243
|
+
readonly delta?: number;
|
|
244
|
+
}
|
|
245
|
+
declare const WORK_METRIC_DEFINITIONS: Record<WorkMetricId, WorkMetricDefinition>;
|
|
246
|
+
/** Definition lookup that tolerates an unknown id from a newer server. */
|
|
247
|
+
declare function getWorkMetricDefinition(id: string): WorkMetricDefinition | undefined;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* What a Work of a given kind actually has.
|
|
251
|
+
*
|
|
252
|
+
* Before this registry, "given `work.kind`, what does this Work support?"
|
|
253
|
+
* was answered independently in half a dozen places — the create-page chip
|
|
254
|
+
* catalogs, the website-template resolver, and (mostly) nowhere at all,
|
|
255
|
+
* because every surface simply assumed a directory. That is why a Landing
|
|
256
|
+
* Page Work shows an Items tab and a "Total Items: 0" tile.
|
|
257
|
+
*
|
|
258
|
+
* Every kind-conditional decision in the platform should route through
|
|
259
|
+
* `getWorkCapabilities()` rather than testing `kind === 'directory'` inline.
|
|
260
|
+
*/
|
|
261
|
+
interface WorkCapabilities {
|
|
262
|
+
/**
|
|
263
|
+
* The Items surface: the Items tab, the `/items` routes, and the
|
|
264
|
+
* submission / import / export endpoints that operate on them.
|
|
265
|
+
* `labelKey` lets a kind keep the machinery but rename it — a blog's
|
|
266
|
+
* items are "posts", a website's are "pages".
|
|
267
|
+
*/
|
|
268
|
+
readonly items: {
|
|
269
|
+
readonly enabled: boolean;
|
|
270
|
+
readonly labelKey: 'items' | 'posts' | 'pages';
|
|
271
|
+
};
|
|
272
|
+
/** Categories / tags / collections CRUD and their tiles. */
|
|
273
|
+
readonly taxonomy: boolean;
|
|
274
|
+
/** The comparison generator sub-tab and its endpoints. */
|
|
275
|
+
readonly comparisons: boolean;
|
|
276
|
+
/** Community pull-request intake settings and processing. */
|
|
277
|
+
readonly communityPr: boolean;
|
|
278
|
+
/** Bulk item import / export. */
|
|
279
|
+
readonly itemImportExport: boolean;
|
|
280
|
+
/** Source-URL validation for items. */
|
|
281
|
+
readonly sourceValidation: boolean;
|
|
282
|
+
/** The Deploy tab and deployment endpoints. */
|
|
283
|
+
readonly deploy: boolean;
|
|
284
|
+
/** The knowledge-base workbench. */
|
|
285
|
+
readonly kb: boolean;
|
|
286
|
+
/** Ordered metric tiles rendered on the Overview tab. */
|
|
287
|
+
readonly metrics: readonly WorkMetricId[];
|
|
288
|
+
/**
|
|
289
|
+
* Which repositories this kind provisions.
|
|
290
|
+
*
|
|
291
|
+
* ⚠️ These keys are the PERSISTED `RepositoryRole` values and must not
|
|
292
|
+
* be renamed to match the newer UI labels. Mapping, for the avoidable
|
|
293
|
+
* confusion it saves: `data` → "Data Repository", `work` → the
|
|
294
|
+
* "{provider} Repository" shown to users, `website` → the "Work
|
|
295
|
+
* Repository" (the template output, which is not always a website).
|
|
296
|
+
*/
|
|
297
|
+
readonly repos: {
|
|
298
|
+
readonly data: boolean;
|
|
299
|
+
readonly work: boolean;
|
|
300
|
+
readonly website: boolean;
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
declare const WORK_KIND_CAPABILITIES: Record<WorkKind, WorkCapabilities>;
|
|
304
|
+
/**
|
|
305
|
+
* Capabilities for a possibly-unknown kind.
|
|
306
|
+
*
|
|
307
|
+
* ALWAYS use this instead of indexing `WORK_KIND_CAPABILITIES` directly.
|
|
308
|
+
* `work.kind` is an open string union — a server can ship a kind this build
|
|
309
|
+
* has never heard of, and indexing would hand back `undefined` and crash
|
|
310
|
+
* whatever destructured it.
|
|
311
|
+
*/
|
|
312
|
+
declare function getWorkCapabilities(kind?: string | null): WorkCapabilities;
|
|
313
|
+
/** Convenience predicate — the Items tab / routes are meaningful here. */
|
|
314
|
+
declare function workKindHasItems(kind?: string | null): boolean;
|
|
315
|
+
|
|
316
|
+
export { DEFAULT_GOAL_KIND, type DomainAnalysis, DomainType, GOAL_KINDS, type GoalKind, type RelevanceAssessment, USER_SELECTABLE_WORK_KINDS, type UserSelectableWorkKind, WORK_KINDS, WORK_KIND_CAPABILITIES, WORK_METRIC_DEFINITIONS, WORK_METRIC_IDS, type WebPageData, type WorkCapabilities, type WorkKind, type WorkMetricDefinition, type WorkMetricFormat, type WorkMetricId, type WorkMetricLabelKey, type WorkMetricSource, type WorkMetricState, type WorkMetricValue, getWorkCapabilities, getWorkMetricDefinition, isDeliveryGoalKind, isGoalKind, isRepositoryWorkKind, isUserSelectableWorkKind, normalizeGoalKind, normalizeWorkKind, workKindHasItems };
|