etymd 0.15.0 → 0.17.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/dist/index.d.ts CHANGED
@@ -303,6 +303,14 @@ interface PlanOptions {
303
303
  publishGate?: boolean;
304
304
  /** Recorded gate choices; absent means derive everything from the scan. */
305
305
  gateConfig?: GateConfig;
306
+ /**
307
+ * Whether `gateConfig.failOn` was PINNED by the repo's committed config, versus a default the
308
+ * config loader filled in. The tier derivation may only choose between defaults — a recorded
309
+ * tier is a decision and is never lowered (see `deriveFailOn`). Callers that read the config
310
+ * pass `explicit.gatesFailOn` from `readConfig`; callers planning from a bare scan leave it
311
+ * unset, which is the same as unpinned.
312
+ */
313
+ gateFailOnPinned?: boolean;
306
314
  }
307
315
  /** Build the file set an onboarding would write, flagging which exist and which differ. */
308
316
  declare function planWorkflow(root: string, facts: ProjectFacts, opts: PlanOptions): Promise<GeneratedFile[]>;
@@ -464,12 +472,12 @@ interface AuditOptions {
464
472
  persistLedger?: boolean;
465
473
  /**
466
474
  * Fleet: the audited root is READ-ONLY — write nothing into it, not even the scan cache
467
- * where `.etymd` already exists there. A corp worktree is never written, regardless of flags.
475
+ * where `.etymd` already exists there. A guarded worktree is never written, regardless of flags.
468
476
  */
469
477
  readOnlyRoot?: boolean;
470
478
  /**
471
- * Fleet: read/write the ledger at this root instead of the audited one. Corp findings persist
472
- * under the manifest's `corp/<name>/`, never inside the corp worktree.
479
+ * Fleet: read/write the ledger at this root instead of the audited one. Guarded findings persist
480
+ * under the manifest's `guarded/<name>/`, never inside the guarded worktree.
473
481
  */
474
482
  ledgerRoot?: string;
475
483
  /** Fleet: per-entry state-budget overlay (registry `staleAfterDays` / `stateBudget`). */
@@ -490,11 +498,11 @@ interface AuditResult {
490
498
  }
491
499
  declare function runAudit(root: string, opts?: AuditOptions): Promise<AuditResult>;
492
500
 
493
- type FleetProfile = "personal" | "corp";
501
+ type FleetProfile = "personal" | "guarded";
494
502
  /**
495
503
  * How exposed an entry's history is, or could plausibly become. A SAFETY PREDICATE, not a label:
496
504
  * it decides whether content screening applies, so absence must never read as the permissive
497
- * answer. `checkManifest` treats an undeclared non-corp entry as a finding — a repo published
505
+ * answer. `checkManifest` treats an undeclared non-guarded entry as a finding — a repo published
498
506
  * without ever answering the question is exactly the case a default would hide.
499
507
  *
500
508
  * `public-repo` already public — outside-contribution surface.
@@ -503,7 +511,7 @@ type FleetProfile = "personal" | "corp";
503
511
  * not the visibility flip.
504
512
  * `private` not destined to be published. An ANSWER, not the absence of one.
505
513
  *
506
- * Corp entries do not carry it — `profile: "corp"` implies the answer (machine-pinned, never
514
+ * Guarded entries do not carry it — `profile: "guarded"` implies the answer (machine-pinned, never
507
515
  * publishable), so requiring it there would be ceremony.
508
516
  */
509
517
  type FleetTrust = "public-repo" | "public-bound" | "private";
@@ -524,6 +532,12 @@ interface FleetContract {
524
532
  state?: string;
525
533
  decisions?: string;
526
534
  goals?: string;
535
+ /**
536
+ * The project's milestones file (`MILESTONES.md` by convention), rolled up by `etymd fleet
537
+ * board`; its shape is checked by the sweep. `"none"` declares the project deliberately
538
+ * carries no milestones (a state, not a gap).
539
+ */
540
+ milestones?: string;
527
541
  /** `"none"` = the contract file is legitimately absent (a declared state, not a gap). */
528
542
  placement?: string;
529
543
  }
@@ -538,7 +552,7 @@ interface FleetEntry {
538
552
  upstream?: string;
539
553
  /**
540
554
  * How exposed this entry is — see {@link FleetTrust}. `"public-repo"` marks an
541
- * outside-contribution surface (hygiene needles apply). Undeclared on a non-corp entry is a
555
+ * outside-contribution surface (hygiene needles apply). Undeclared on a non-guarded entry is a
542
556
  * `fleet check` finding, never a silent "private".
543
557
  */
544
558
  trust?: FleetTrust;
@@ -573,14 +587,14 @@ interface FleetManifest {
573
587
  shape: "registry" | "corpus";
574
588
  /** Absolute path of the tracked manifest file. */
575
589
  manifestPath: string;
576
- /** Its directory — corp persistence roots and the sweep delta file live beside it. */
590
+ /** Its directory — guarded persistence roots and the sweep delta file live beside it. */
577
591
  dir: string;
578
592
  /** Resolved absolute fleet root (registry shape), when declared. */
579
593
  root?: string;
580
594
  /** Fleet-wide orientation root, when the manifest declares one. Absent = this fleet has none. */
581
595
  orientation?: FleetOrientation;
582
596
  machineProfile?: FleetProfile;
583
- corpHosts: string[];
597
+ guardedHosts: string[];
584
598
  labels: Record<string, string>;
585
599
  localDirs: Record<string, string>;
586
600
  /** Absolute path where the gitignored local sibling is expected. */
@@ -605,18 +619,18 @@ declare const FLEET_JSON_SCHEMA = "fleet-experimental-0.2";
605
619
  interface FleetSweepOptions {
606
620
  /** Restrict to these registered names (unknown names throw — a typo must not skip silently). */
607
621
  only?: string[];
608
- profile?: "personal" | "corp";
622
+ profile?: "personal" | "guarded";
609
623
  /** Truth lenses only per repo (the doctor subset). */
610
624
  kind?: LensKind;
611
625
  /**
612
626
  * Persist per-repo ledgers — ONLY for personal-profile entries that already carry `.etymd`.
613
- * The sweep never creates `.etymd` anywhere, and corp worktrees are never written at all.
627
+ * The sweep never creates `.etymd` anywhere, and guarded worktrees are never written at all.
614
628
  */
615
629
  persistLedgers?: boolean;
616
630
  }
617
631
  interface FleetProjectSweep {
618
632
  name: string;
619
- profile: "personal" | "corp";
633
+ profile: "personal" | "guarded";
620
634
  kind?: string;
621
635
  resolvedRoot?: string;
622
636
  /** Why this entry could not be audited — mirrored into `outOfScope`. */
@@ -648,15 +662,15 @@ interface RecurringClass {
648
662
  /** The `<lens>/<class>` id prefix — minted by the engine's lenses, identical across repos. */
649
663
  classId: string;
650
664
  tier: FindingTier;
651
- /** Project names (corp entries by alias) where the class is currently open. */
665
+ /** Project names (guarded entries by alias) where the class is currently open. */
652
666
  projects: string[];
653
667
  }
654
668
  /**
655
- * Where a corp entry's audit state persists: beside the manifest, never in the worktree.
669
+ * Where a guarded entry's audit state persists: beside the manifest, never in the worktree.
656
670
  * Belt-and-braces to the loader's safe-name rule: a name that resolves anywhere but directly
657
- * under `<dir>/corp/` is refused — the manifest can lie, and a lie must never steer a write.
671
+ * under `<dir>/guarded/` is refused — the manifest can lie, and a lie must never steer a write.
658
672
  */
659
- declare function corpPersistenceRoot(manifest: FleetManifest, name: string): string;
673
+ declare function guardedPersistenceRoot(manifest: FleetManifest, name: string): string;
660
674
  /**
661
675
  * Validate the manifest pair itself: parse problems, dangling mappings (the live ghost-entry
662
676
  * class), duplicate names, privacy leaks, dead links, machine paths. Pure manifest truth —
@@ -673,12 +687,94 @@ declare function collectWallFindings(manifest: FleetManifest): Promise<{
673
687
  }>;
674
688
  /**
675
689
  * The fleet sweep: one read-only audit per resolved entry + the fleet-scope wall checks.
676
- * Invariants (each pinned by test): never creates `.etymd` anywhere; never writes into a corp
690
+ * Invariants (each pinned by test): never creates `.etymd` anywhere; never writes into a guarded
677
691
  * worktree regardless of flags or a stray `.etymd` there; unresolvable entries land in
678
692
  * `outOfScope` with a disclosure, never a silent skip.
679
693
  */
680
694
  declare function sweepFleet(manifest: FleetManifest, opts?: FleetSweepOptions): Promise<FleetSweepResult>;
681
695
 
696
+ /**
697
+ * `etymd propose` — the scoring step between the sweep and a filed proposal.
698
+ *
699
+ * The sweep already mints everything a proposal needs (every finding carries an action, an
700
+ * effort and a confidence; `recurringClasses` names the classes open in ≥2 projects). This
701
+ * module adds the two things that were missing: a rubric the FLEET authors (the tool ships
702
+ * none — with no rubric there is nothing to run) and a stable record shape (`proposal/1`)
703
+ * a planning surface can file mechanically.
704
+ *
705
+ * Everything here is a pure function of its inputs — no clocks, no randomness — so the same
706
+ * sweep plus the same rubric yields byte-identical output, and a filed proposal can be
707
+ * re-derived and compared later. Decision record: docs/decisions/012.
708
+ */
709
+ /** The record schema marker — experimental through 0.2.x with the rest of the fleet family. */
710
+ declare const PROPOSAL_SCHEMA = "proposal/1";
711
+ /**
712
+ * The criteria the tool can compute, each mapped to a 1–3 value. The vocabulary is closed: a
713
+ * rubric line naming anything else is refused, because a criterion this tool cannot derive
714
+ * mechanically would be an opinion wearing a number — the exact product anti-pattern. The
715
+ * WEIGHTS are the fleet's; the tool imposes none.
716
+ */
717
+ declare const RUBRIC_CRITERIA: readonly ["severity", "economy", "confidence", "breadth"];
718
+ type RubricCriterion = (typeof RUBRIC_CRITERIA)[number];
719
+ interface RubricLine {
720
+ criterion: RubricCriterion;
721
+ weight: number;
722
+ }
723
+ interface Rubric {
724
+ lines: RubricLine[];
725
+ }
726
+ /**
727
+ * Parse a rubric file: labeled lines, one criterion per line (`criterion: <weight>`), `#`
728
+ * comments and blanks ignored. The line is the unit of refusal — unknown criterion, malformed
729
+ * line, duplicate criterion, or a rubric with no criteria at all each name their line (or the
730
+ * file), never a silent skip and never a default weight.
731
+ */
732
+ declare function parseRubric(text: string, file: string): Rubric;
733
+ interface MatchedLine {
734
+ criterion: RubricCriterion;
735
+ weight: number;
736
+ /** The computed 1–3 value — carried beside the weight so the score is auditable. */
737
+ value: number;
738
+ }
739
+ interface Implications {
740
+ projects: string[];
741
+ files: string[];
742
+ gates: string[];
743
+ reversibility: "regenerable" | "git-reversible" | "undetermined";
744
+ }
745
+ interface Proposal {
746
+ id: string;
747
+ schema: typeof PROPOSAL_SCHEMA;
748
+ class: string;
749
+ kind: "finding" | "class";
750
+ projects: string[];
751
+ action: string;
752
+ effort: Effort;
753
+ confidence: Confidence;
754
+ score: number;
755
+ matched: MatchedLine[];
756
+ implications: Implications;
757
+ }
758
+ interface ProposeResult {
759
+ schema: typeof PROPOSAL_SCHEMA;
760
+ manifest: string;
761
+ rubric: string;
762
+ criteria: RubricLine[];
763
+ proposals: Proposal[];
764
+ disclosures: string[];
765
+ }
766
+ /**
767
+ * Build the proposals from a sweep result: every `kind: "improvement"` finding from every
768
+ * personal project, plus every recurring class recomputed over personal projects only. Guarded
769
+ * entries are excluded from the output entire (their findings, and their names inside class
770
+ * breadth) — a guarded improvement is the guarded side's backlog, not this fleet's proposal queue —
771
+ * and their exclusion is disclosed by name so absence is a stated policy, never a hole.
772
+ */
773
+ declare function buildProposals(sweep: {
774
+ manifest: string;
775
+ projects: FleetProjectSweep[];
776
+ }, rubricName: string, rubric: Rubric): ProposeResult;
777
+
682
778
  /**
683
779
  * The truth lens: does what the instruction files CLAIM still hold against the actual repo?
684
780
  * Commands must exist as scripts, paths must exist on disk, files must agree on the package
@@ -716,6 +812,10 @@ interface ClaimCounters {
716
812
  qualifiedRefsSkipped: number;
717
813
  /** Decision references with no `## D-NNN` ledger to resolve against. */
718
814
  unresolvableRefs: number;
815
+ /** Path claims whose every mention sits behind a namespace prefix (`pc:`) — another repo's. */
816
+ namespacedSkipped: number;
817
+ /** Missing paths starting at no directory of this repo — quoted from elsewhere (task only). */
818
+ outsideRepoSkipped: number;
719
819
  }
720
820
  declare function emptyCounters(): ClaimCounters;
721
821
  /**
@@ -749,6 +849,19 @@ interface TextClaimsOptions {
749
849
  actionCommand?: string;
750
850
  whyPath?: string;
751
851
  actionPath?: string;
852
+ /**
853
+ * Directories a missing path may start from and still be plausibly repo-relative — the root,
854
+ * workspace packages, and their src/ scripts/. Supplied by the task surface (`etymd premise`)
855
+ * only: a task quoting a path from ANOTHER repository (a clone in a scratchpad) starts where
856
+ * no directory of this repo does, and its absence here proves nothing. Instruction files keep
857
+ * the stricter reading — their references are written against this repo.
858
+ */
859
+ rootedFirstSegments?: ReadonlySet<string>;
860
+ /**
861
+ * Read namespace-prefixed path mentions (`pc: `src/x.ts``) as another repo's tree — the task
862
+ * surface only; instruction files keep every backticked span as a claim of this repo.
863
+ */
864
+ treatNamespacedPrefixes?: boolean;
752
865
  }
753
866
  interface TextClaimsResult {
754
867
  findings: Finding[];
@@ -825,6 +938,8 @@ interface PromotionSkips {
825
938
  hostnameLike: number;
826
939
  /** `input/output/` — a slash-joined phrase whose first segment is no directory here. */
827
940
  unrootedDirs: number;
941
+ /** `pc:src/x.ts`, `lk: src/x.ts` — a namespace-prefixed mention of ANOTHER repo's tree. */
942
+ namespaced: number;
828
943
  }
829
944
  interface PromotionContext {
830
945
  /** Directory names that exist at the root, in a workspace package, or under their src/ scripts/. */
@@ -882,16 +997,27 @@ interface PathClaims {
882
997
  paths: string[];
883
998
  /** Claims whose every mention sits in create-this prose — skipped, counted, disclosed. */
884
999
  prospective: string[];
1000
+ /** Claims whose every mention sits behind a namespace prefix (`pc:`) — another repo's tree. */
1001
+ namespaced: string[];
885
1002
  /** Naming stand-ins (`my-custom-skill`) — never real claims. */
886
1003
  placeholder: string[];
887
1004
  }
1005
+ interface PathClaimOptions {
1006
+ /**
1007
+ * Read namespace-prefixed mentions (`pc: `src/x.ts``) as another repo's tree — the task
1008
+ * surface, where prompts quote foreign repos behind a legend. Instruction files keep every
1009
+ * backticked span as a claim of this repo.
1010
+ */
1011
+ namespaces?: boolean;
1012
+ }
888
1013
  /**
889
1014
  * Repo-relative path claims from single-token inline spans, conservatively filtered. The
890
1015
  * load-bearing precision rule (learned from real corpus prose): an extensionless bare token
891
1016
  * (`research/trust`, `milestone/mNN`) is prose — a dir claim must end with `/`, a file claim
892
- * must carry an extension.
1017
+ * must carry an extension. With `namespaces`, a span whose every mention sits behind a
1018
+ * namespace prefix names another repo's tree, not this one.
893
1019
  */
894
- declare function extractPathClaims(text: string): PathClaims;
1020
+ declare function extractPathClaims(text: string, opts?: PathClaimOptions): PathClaims;
895
1021
 
896
1022
  /** Default total always-loaded words past which the footprint itself becomes a finding. */
897
1023
  declare const TOTAL_BUDGET_WORDS: number;
@@ -988,4 +1114,4 @@ declare const PACK_VERSION = "12";
988
1114
  declare const VERSION: string;
989
1115
  declare const NAME: string;
990
1116
 
991
- export { type ApplyResult, type ArtifactFreshness, type AuditOptions, type AuditResult, type Baseline, CONFIG_FILE, type ClaimCounters, type ClaimText, type ContextBudget, type ContextBudgets, type ContextFile, DECISIONS_FORMAT_MARKER, DEFAULT_CONFIG, type DecisionLedger, type DecisionRefsOptions, type DetectedArtifact, type DiscoveredCommands, EXTRACTION_THRESHOLD, type EtymdConfig, type ExaminedClaim, FLEET_JSON_SCHEMA, FLEET_LENS, type Finding, type FleetContract, type FleetEntry, type FleetManifest, type FleetProfile, type FleetProjectSweep, type FleetSweepOptions, type FleetSweepResult, type FreshnessFacts, type GateInventory, type GateTool, type GeneratedFile, type HookFacts, type InstructionFileSet, type InstructionScope, LENSES, type Ledger, type LedgerDiff, type LedgerEntry, type Lens, type LensReport, type LoadedConfig, type ManifestProblem, NAME, PACK_VERSION, PREMISE_BRIEF_FILE, PREMISE_LENS, type PackageManager, type PathClaims, type PlanOptions, type PremiseEntity, type PremiseOptions, type PremiseResult, type ProjectFacts, type PromotedText, type PromotionContext, type PromotionSkips, type RefsResult, type StateBudgets, TOTAL_BUDGET_WORDS, type TextClaimsOptions, type TextClaimsResult, type TruthEnv, VERSION, type WorkflowProfile, type WorkspaceKind, applyFiles, baselineCarriesMachinePath, baselinePath, buildGateInventory, buildTruthEnv, cacheFactsPath, checkDecisionRefs, checkDocRefs, checkManifest, checkTextClaims, collectWallFindings, configPath, contextEconomyLens, corpPersistenceRoot, deriveProfile, emptyCounters, expandTilde, extractCommandClaims, extractPathClaims, gateIntegrityLens, instructionTruthLens, isAlwaysAppliedCursorRule, listInstructionFiles, loadDecisionLedger, loadFleetManifest, measureContext, planWorkflow, promoteBareTokens, rankFindings, readBaseline, readCachedFacts, readConfig, readLedger, reconcileLedger, renderBrief, runAudit, runPremise, scanProject, stateFreshnessLens, sweepFleet, withoutMachinePath, writeBaseline, writeCachedFacts, writeLedger };
1117
+ export { type ApplyResult, type ArtifactFreshness, type AuditOptions, type AuditResult, type Baseline, CONFIG_FILE, type ClaimCounters, type ClaimText, type ContextBudget, type ContextBudgets, type ContextFile, DECISIONS_FORMAT_MARKER, DEFAULT_CONFIG, type DecisionLedger, type DecisionRefsOptions, type DetectedArtifact, type DiscoveredCommands, EXTRACTION_THRESHOLD, type EtymdConfig, type ExaminedClaim, FLEET_JSON_SCHEMA, FLEET_LENS, type Finding, type FleetContract, type FleetEntry, type FleetManifest, type FleetProfile, type FleetProjectSweep, type FleetSweepOptions, type FleetSweepResult, type FreshnessFacts, type GateInventory, type GateTool, type GeneratedFile, type HookFacts, type InstructionFileSet, type InstructionScope, LENSES, type Ledger, type LedgerDiff, type LedgerEntry, type Lens, type LensReport, type LoadedConfig, type ManifestProblem, NAME, PACK_VERSION, PREMISE_BRIEF_FILE, PREMISE_LENS, PROPOSAL_SCHEMA, type PackageManager, type PathClaims, type PlanOptions, type PremiseEntity, type PremiseOptions, type PremiseResult, type ProjectFacts, type PromotedText, type PromotionContext, type PromotionSkips, type Proposal, type ProposeResult, RUBRIC_CRITERIA, type RefsResult, type Rubric, type RubricCriterion, type RubricLine, type StateBudgets, TOTAL_BUDGET_WORDS, type TextClaimsOptions, type TextClaimsResult, type TruthEnv, VERSION, type WorkflowProfile, type WorkspaceKind, applyFiles, baselineCarriesMachinePath, baselinePath, buildGateInventory, buildProposals, buildTruthEnv, cacheFactsPath, checkDecisionRefs, checkDocRefs, checkManifest, checkTextClaims, collectWallFindings, configPath, contextEconomyLens, deriveProfile, emptyCounters, expandTilde, extractCommandClaims, extractPathClaims, gateIntegrityLens, guardedPersistenceRoot, instructionTruthLens, isAlwaysAppliedCursorRule, listInstructionFiles, loadDecisionLedger, loadFleetManifest, measureContext, parseRubric, planWorkflow, promoteBareTokens, rankFindings, readBaseline, readCachedFacts, readConfig, readLedger, reconcileLedger, renderBrief, runAudit, runPremise, scanProject, stateFreshnessLens, sweepFleet, withoutMachinePath, writeBaseline, writeCachedFacts, writeLedger };