etymd 0.2.2 → 0.3.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/CHANGELOG.md +42 -2
- package/README.md +145 -37
- package/dist/{approve-VC4V3OPW.js → approve-JEOEC2MV.js} +6 -4
- package/dist/audit-GYZ5YZ7U.js +12 -0
- package/dist/{brief-TZ45MNHD.js → brief-ZK7TXAC4.js} +6 -4
- package/dist/{chunk-MWIK6ML3.js → chunk-3NYDVB4Z.js} +123 -25
- package/dist/chunk-CRJHIXJH.js +5 -0
- package/dist/chunk-EF6BPBG6.js +22 -0
- package/dist/chunk-LT67FU2Y.js +59 -0
- package/dist/{chunk-BH37LELV.js → chunk-MKYPLNLH.js} +8 -5
- package/dist/{chunk-EUIHYD6F.js → chunk-MMPV67FW.js} +2 -2
- package/dist/{chunk-LVLZLCND.js → chunk-NFENQ3IK.js} +1 -1
- package/dist/{chunk-ANCCGYSH.js → chunk-NMZ3RHWW.js} +31 -59
- package/dist/{chunk-FZSIOCOZ.js → chunk-R74SJ7HS.js} +1 -1
- package/dist/{chunk-LBRNZZZF.js → chunk-TADKOW6P.js} +1 -99
- package/dist/{chunk-KMAJIQHC.js → chunk-V3DPLOOM.js} +7 -5
- package/dist/{chunk-KBF3SW3N.js → chunk-WWBF4Y7K.js} +1 -1
- package/dist/{chunk-IW6K5HLV.js → chunk-XTAX4YNT.js} +2 -2
- package/dist/chunk-YLNQQZ5F.js +102 -0
- package/dist/cli.js +50 -16
- package/dist/config-MX7OYI7F.js +4 -0
- package/dist/{context-GYCLR3TG.js → context-4DGXO7JR.js} +5 -3
- package/dist/doctor-C2RTL2QV.js +19 -0
- package/dist/{fleet-N3G5ZIGR.js → fleet-YZGR4UC2.js} +243 -10
- package/dist/gates-ILE4PXDA.js +272 -0
- package/dist/generate-IYCQETQB.js +4 -0
- package/dist/index.d.ts +113 -33
- package/dist/index.js +713 -257
- package/dist/{init-4CQOLFQG.js → init-OVLO4OBZ.js} +8 -5
- package/dist/ledger-TMIV45AA.js +5 -0
- package/dist/{scan-CYOOGJFG.js → scan-RAJUFTQR.js} +6 -4
- package/dist/scan-ZYZ7XDSJ.js +5 -0
- package/dist/screen-U7JMWZPS.js +134 -0
- package/package.json +2 -2
- package/dist/audit-LZJRJS5V.js +0 -9
- package/dist/doctor-6JDAHGDT.js +0 -16
- package/dist/gates-G5BCMRRV.js +0 -71
- package/dist/ledger-RHQJH5EA.js +0 -4
package/dist/index.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ interface GitFacts {
|
|
|
70
70
|
husky: boolean;
|
|
71
71
|
/** Distinct commit authors in recent history — the solo-vs-team profile signal. */
|
|
72
72
|
recentAuthors?: number;
|
|
73
|
-
/** Ticket-key prefix inferred from recent commit subjects (e.g. "
|
|
73
|
+
/** Ticket-key prefix inferred from recent commit subjects (e.g. "PROJ"). */
|
|
74
74
|
ticketKey?: string;
|
|
75
75
|
}
|
|
76
76
|
interface HookFacts {
|
|
@@ -104,6 +104,22 @@ interface ProjectFacts {
|
|
|
104
104
|
files: string[];
|
|
105
105
|
};
|
|
106
106
|
hooks: HookFacts;
|
|
107
|
+
/**
|
|
108
|
+
* This project would publish something if asked — a manifest exists and does not declare
|
|
109
|
+
* `private: true`.
|
|
110
|
+
*
|
|
111
|
+
* A GUESS, not a fact: npm treats a missing `private` as publishable, which is right about
|
|
112
|
+
* npm's semantics and wrong about a local fork nobody will ever publish. It seeds the plan;
|
|
113
|
+
* `gates.publishGate` in `.etymd/config.json` overrides it for good.
|
|
114
|
+
*/
|
|
115
|
+
publishable: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* How this project publishes, when it does. The route decides which manifest key fires a
|
|
118
|
+
* publish-time gate: npm runs `prepublishOnly`, while `vsce` ignores that key entirely and
|
|
119
|
+
* runs `vscode:prepublish` — so wiring the npm key into an extension is a gate that silently
|
|
120
|
+
* never runs.
|
|
121
|
+
*/
|
|
122
|
+
publishRoute: "npm" | "vscode" | "none";
|
|
107
123
|
artifacts: DetectedArtifact[];
|
|
108
124
|
/** Optional: baselines approved by older versions predate this fact. */
|
|
109
125
|
freshness?: FreshnessFacts;
|
|
@@ -159,35 +175,6 @@ declare const EXTRACTION_THRESHOLD: number;
|
|
|
159
175
|
declare function isAlwaysAppliedCursorRule(text: string): boolean;
|
|
160
176
|
declare function measureContext(root: string, perFileWords?: number): Promise<ContextBudget>;
|
|
161
177
|
|
|
162
|
-
interface GeneratedFile {
|
|
163
|
-
path: string;
|
|
164
|
-
contents: string;
|
|
165
|
-
/** Present on disk already — apply will skip or ask before overwriting. */
|
|
166
|
-
exists: boolean;
|
|
167
|
-
/** The existing file's content differs from what the pack would generate (hand-edited or stale). */
|
|
168
|
-
differs?: boolean;
|
|
169
|
-
/** Hooks need the executable bit. */
|
|
170
|
-
executable?: boolean;
|
|
171
|
-
label: string;
|
|
172
|
-
}
|
|
173
|
-
interface PlanOptions {
|
|
174
|
-
/** Scaffold a minimal AGENTS.md (init only offers this when none exists). */
|
|
175
|
-
agents: boolean;
|
|
176
|
-
gates: boolean;
|
|
177
|
-
}
|
|
178
|
-
/** Build the file set an onboarding would write, flagging which exist and which differ. */
|
|
179
|
-
declare function planWorkflow(root: string, facts: ProjectFacts, opts: PlanOptions): Promise<GeneratedFile[]>;
|
|
180
|
-
|
|
181
|
-
interface ApplyResult {
|
|
182
|
-
written: string[];
|
|
183
|
-
skipped: string[];
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Write a planned file set. Idempotent by default: an existing file is skipped unless `overwrite`
|
|
187
|
-
* names it — etymd never clobbers hand-authored contracts without consent.
|
|
188
|
-
*/
|
|
189
|
-
declare function applyFiles(root: string, files: GeneratedFile[], overwrite?: Set<string>): Promise<ApplyResult>;
|
|
190
|
-
|
|
191
178
|
declare const CONFIG_FILE: string;
|
|
192
179
|
interface InstructionScope {
|
|
193
180
|
/** Extra instruction files to audit beyond the auto-detected set (globs, repo-relative). */
|
|
@@ -207,10 +194,29 @@ interface StateBudgets {
|
|
|
207
194
|
/** Chars in a state doc past which the file is a finding (session hooks truncate ~10k). */
|
|
208
195
|
maxChars: number;
|
|
209
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* What the generated gates should contain. Every field here is DERIVED from the repo on a first
|
|
199
|
+
* run and written into the plan, not asked: a wrong guess costs a slightly slow hook or a
|
|
200
|
+
* slightly strict audit, and both are one edit away. Prompting is reserved for the choices where
|
|
201
|
+
* a wrong default is expensive — trust (a permanent leak) and the publish gate (a write into
|
|
202
|
+
* package.json). Recording the derivation here is what makes `gates` re-runnable without
|
|
203
|
+
* re-deciding, and what a drift check compares against.
|
|
204
|
+
*/
|
|
205
|
+
interface GateConfig {
|
|
206
|
+
/** Command keys the pre-push gate runs, in order. Empty = whatever the scan finds. */
|
|
207
|
+
commands: string[];
|
|
208
|
+
/** Tier the audit step fails on: risk | gap | polish. */
|
|
209
|
+
failOn: string;
|
|
210
|
+
/** Emit the publish-time screen. Unset = derive from whether the repo publishes. */
|
|
211
|
+
publishGate?: boolean;
|
|
212
|
+
/** Commands allowed into a gate despite looking like they write (an explicit override). */
|
|
213
|
+
allowWriting: string[];
|
|
214
|
+
}
|
|
210
215
|
interface EtymdConfig {
|
|
211
216
|
instructions: InstructionScope;
|
|
212
217
|
context: ContextBudgets;
|
|
213
218
|
state: StateBudgets;
|
|
219
|
+
gates: GateConfig;
|
|
214
220
|
}
|
|
215
221
|
interface LoadedConfig {
|
|
216
222
|
config: EtymdConfig;
|
|
@@ -228,6 +234,43 @@ declare function configPath(root: string): string;
|
|
|
228
234
|
*/
|
|
229
235
|
declare function readConfig(root: string): Promise<LoadedConfig>;
|
|
230
236
|
|
|
237
|
+
interface GeneratedFile {
|
|
238
|
+
path: string;
|
|
239
|
+
contents: string;
|
|
240
|
+
/** Present on disk already — apply will skip or ask before overwriting. */
|
|
241
|
+
exists: boolean;
|
|
242
|
+
/** The existing file's content differs from what the pack would generate (hand-edited or stale). */
|
|
243
|
+
differs?: boolean;
|
|
244
|
+
/** Hooks need the executable bit. */
|
|
245
|
+
executable?: boolean;
|
|
246
|
+
label: string;
|
|
247
|
+
}
|
|
248
|
+
interface PlanOptions {
|
|
249
|
+
/** Scaffold a minimal AGENTS.md (init only offers this when none exists). */
|
|
250
|
+
agents: boolean;
|
|
251
|
+
gates: boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Emit the publish-time screen. Defaults to `facts.publishable` — set it explicitly to
|
|
254
|
+
* override the derivation (a repo that publishes by a route npm cannot see, or one that
|
|
255
|
+
* declines the door).
|
|
256
|
+
*/
|
|
257
|
+
publishGate?: boolean;
|
|
258
|
+
/** Recorded gate choices; absent means derive everything from the scan. */
|
|
259
|
+
gateConfig?: GateConfig;
|
|
260
|
+
}
|
|
261
|
+
/** Build the file set an onboarding would write, flagging which exist and which differ. */
|
|
262
|
+
declare function planWorkflow(root: string, facts: ProjectFacts, opts: PlanOptions): Promise<GeneratedFile[]>;
|
|
263
|
+
|
|
264
|
+
interface ApplyResult {
|
|
265
|
+
written: string[];
|
|
266
|
+
skipped: string[];
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Write a planned file set. Idempotent by default: an existing file is skipped unless `overwrite`
|
|
270
|
+
* names it — etymd never clobbers hand-authored contracts without consent.
|
|
271
|
+
*/
|
|
272
|
+
declare function applyFiles(root: string, files: GeneratedFile[], overwrite?: Set<string>): Promise<ApplyResult>;
|
|
273
|
+
|
|
231
274
|
type FindingTier = "risk" | "gap" | "polish";
|
|
232
275
|
type Effort = "S" | "M" | "L";
|
|
233
276
|
type Confidence = "high" | "medium" | "low";
|
|
@@ -395,6 +438,35 @@ interface AuditResult {
|
|
|
395
438
|
declare function runAudit(root: string, opts?: AuditOptions): Promise<AuditResult>;
|
|
396
439
|
|
|
397
440
|
type FleetProfile = "personal" | "corp";
|
|
441
|
+
/**
|
|
442
|
+
* How exposed an entry's history is, or could plausibly become. A SAFETY PREDICATE, not a label:
|
|
443
|
+
* it decides whether content screening applies, so absence must never read as the permissive
|
|
444
|
+
* answer. `checkManifest` treats an undeclared non-corp entry as a finding — a repo published
|
|
445
|
+
* without ever answering the question is exactly the case a default would hide.
|
|
446
|
+
*
|
|
447
|
+
* `public-repo` already public — outside-contribution surface.
|
|
448
|
+
* `public-bound` private today, plausibly public later. Screened as hard as public, because
|
|
449
|
+
* publishing exposes ALL history: the scrub must precede the first commit,
|
|
450
|
+
* not the visibility flip.
|
|
451
|
+
* `private` not destined to be published. An ANSWER, not the absence of one.
|
|
452
|
+
*
|
|
453
|
+
* Corp entries do not carry it — `profile: "corp"` implies the answer (machine-pinned, never
|
|
454
|
+
* publishable), so requiring it there would be ceremony.
|
|
455
|
+
*/
|
|
456
|
+
type FleetTrust = "public-repo" | "public-bound" | "private";
|
|
457
|
+
/**
|
|
458
|
+
* Fleet-wide orientation: the one entry every other entry is guided by.
|
|
459
|
+
*
|
|
460
|
+
* Declared ONCE at the manifest level rather than as a per-entry link, because the relationship
|
|
461
|
+
* is constant — a per-entry field carries no information and can be forgotten, which is exactly
|
|
462
|
+
* how three entries came to be silently unlinked. Hoisting it makes the orphan state
|
|
463
|
+
* unrepresentable instead of merely detectable. A fleet with no orientation root simply omits
|
|
464
|
+
* the block; etymd never assumes one exists.
|
|
465
|
+
*/
|
|
466
|
+
interface FleetOrientation {
|
|
467
|
+
/** Registered name of the orientation root. Only the root itself is exempt from being guided. */
|
|
468
|
+
root: string;
|
|
469
|
+
}
|
|
398
470
|
interface FleetContract {
|
|
399
471
|
state?: string;
|
|
400
472
|
decisions?: string;
|
|
@@ -411,8 +483,14 @@ interface FleetEntry {
|
|
|
411
483
|
path?: string;
|
|
412
484
|
/** Remote name of the upstream this repo forks — freshness measures fork-authored commits. */
|
|
413
485
|
upstream?: string;
|
|
414
|
-
/**
|
|
415
|
-
|
|
486
|
+
/**
|
|
487
|
+
* How exposed this entry is — see {@link FleetTrust}. `"public-repo"` marks an
|
|
488
|
+
* outside-contribution surface (hygiene needles apply). Undeclared on a non-corp entry is a
|
|
489
|
+
* `fleet check` finding, never a silent "private".
|
|
490
|
+
*/
|
|
491
|
+
trust?: FleetTrust;
|
|
492
|
+
/** A declared `trust` value outside the vocabulary — preserved verbatim so the check can name it. */
|
|
493
|
+
trustRaw?: string;
|
|
416
494
|
staleAfterDays?: number;
|
|
417
495
|
/** Per-entry state char-budget override (ships unset — the schema slot exists). */
|
|
418
496
|
stateBudget?: number;
|
|
@@ -437,6 +515,8 @@ interface FleetManifest {
|
|
|
437
515
|
dir: string;
|
|
438
516
|
/** Resolved absolute fleet root (registry shape), when declared. */
|
|
439
517
|
root?: string;
|
|
518
|
+
/** Fleet-wide orientation root, when the manifest declares one. Absent = this fleet has none. */
|
|
519
|
+
orientation?: FleetOrientation;
|
|
440
520
|
machineProfile?: FleetProfile;
|
|
441
521
|
corpHosts: string[];
|
|
442
522
|
labels: Record<string, string>;
|
|
@@ -656,7 +736,7 @@ declare const gateIntegrityLens: Lens;
|
|
|
656
736
|
* change meaning. Stamped into facts, baselines, and generated artifacts so drift against the
|
|
657
737
|
* pack is computable and `harvest` has something to diff.
|
|
658
738
|
*/
|
|
659
|
-
declare const PACK_VERSION = "
|
|
739
|
+
declare const PACK_VERSION = "3";
|
|
660
740
|
|
|
661
741
|
declare const VERSION: string;
|
|
662
742
|
declare const NAME: string;
|