/** * TrellisVCS Type Definitions * * VCS-specific operation kinds, payloads, and entity types * that extend the trellis-core kernel primitives. */ import type { Fact, Link } from '../core/store/eav-store.js'; export type VcsOpKind = 'vcs:fileAdd' | 'vcs:fileModify' | 'vcs:fileDelete' | 'vcs:fileRename' | 'vcs:dirAdd' | 'vcs:dirDelete' | 'vcs:branchCreate' | 'vcs:branchDelete' | 'vcs:branchAdvance' | 'vcs:milestoneCreate' | 'vcs:checkpointCreate' | 'vcs:merge' | 'vcs:symbolRename' | 'vcs:symbolMove' | 'vcs:symbolExtract' | 'vcs:signatureChange' | 'vcs:issueCreate' | 'vcs:issueUpdate' | 'vcs:issueStart' | 'vcs:issuePause' | 'vcs:issueResume' | 'vcs:issueClose' | 'vcs:issueReopen' | 'vcs:issueClaim' | 'vcs:issueClaimRelease' | 'vcs:criterionAdd' | 'vcs:criterionUpdate' | 'vcs:criterionRemove' | 'vcs:testRun' | 'vcs:zoneDefine' | 'vcs:zoneRename' | 'vcs:grantSet' | 'vcs:grantRetract' | 'vcs:issueBlock' | 'vcs:issueUnblock' | 'vcs:decisionRecord' | 'vcs:laneCreate' | 'vcs:laneDrop' | 'vcs:lanePromoteStart' | 'vcs:lanePromoteComplete' | 'vcs:lanePromoteAbort' | 'vcs:remotePush' | 'vcs:remotePull' | 'vcs:storeAssert' | 'vcs:storeRetract' | 'vcs:storeLink' | 'vcs:storeUnlink'; /** * What kind of thing an issue is (ADR 0026). * * Bounded and enumerable on purpose: that is what lets `decompose` delete every * prior value exhaustively (ADR 0022 §2's safe-register test) instead of relying * on insertion order. */ export type IssueType = 'epic' | 'issue' | 'spike' | 'msg'; /** Every `IssueType`, for exhaustive delete-then-add in `decompose`. */ export declare const ISSUE_TYPES: readonly IssueType[]; export interface VcsPayload { /** * Who asserted this op and over what surface (ADR 0021 §2). * * Lives inside `vcs` deliberately: `hashVcsOp` hashes the `vcs` payload * wholesale, so provenance is covered by the op hash with no preimage change * and no migration — ops minted before this field still verify, since their * payload simply lacks the key. */ provenance?: import('../core/persist/canonical-op.js').OpProvenance; filePath?: string; oldFilePath?: string; contentHash?: string; oldContentHash?: string; size?: number; language?: string; branchName?: string; targetOpHash?: string; sourceBranch?: string; baseBranch?: string; baseOpHash?: string; milestoneId?: string; message?: string; fromOpHash?: string; toOpHash?: string; trigger?: 'green-build' | 'interval' | 'op-count' | 'manual'; signature?: string; signedBy?: string; /** Device id that held the private key (`root` or paired deviceId). ADR 0020. */ signedWith?: string; issueId?: string; issueTitle?: string; /** * What KIND of thing this issue is (ADR 0026). `epic` is a container of * intent; leaves roll up to one via `parentIssueId`, which is how an agent * walks from a task to the reason it exists. * * A real field rather than an `Epic:` title prefix — the same lesson ADR 0022 * applied to zones: a name must not do the work of a type, or you cannot query * it and a rename breaks it. Absent ⇒ `issue`. */ issueType?: IssueType; /** Prior type, so a change is delete-then-add over a bounded domain. */ oldIssueType?: IssueType; issueStatus?: 'backlog' | 'queue' | 'in_progress' | 'paused' | 'closed'; oldIssueStatus?: 'backlog' | 'queue' | 'in_progress' | 'paused' | 'closed'; issuePriority?: 'critical' | 'high' | 'medium' | 'low'; issueLabels?: string[]; parentIssueId?: string; /** Previous parent when re-parenting or clearing via issueUpdate. */ oldParentIssueId?: string; issueDescription?: string; issueAssignee?: string; pauseNote?: string; blockedByIssueId?: string; decisionId?: string; decisionContext?: string; decisionRationale?: string; decisionAlternatives?: string; decisionToolName?: string; decisionToolInput?: string; decisionToolOutput?: string; criterionId?: string; criterionDescription?: string; criterionCommand?: string; /** Manifest suite id from `.trellis/tests.json` when command is omitted. */ criterionSuite?: string; criterionStatus?: 'pending' | 'passed' | 'failed'; criterionOutput?: string; testRunId?: string; testRunSuite?: string; testRunCommand?: string; testRunStatus?: 'passed' | 'failed'; testRunOutput?: string; testRunExitCode?: number; testRunDurationMs?: number; testRunTrigger?: 'manual' | 'watch' | 'pre-promote' | 'pre-close' | 'criterion'; remoteName?: string; remoteRepoId?: string; remoteTailHash?: string; remoteByteLength?: number; laneId?: string; laneStatus?: 'active' | 'promoting' | 'promoted' | 'dropped'; targetBranch?: string; parentLaneId?: string; forkKind?: 'sibling' | 'child'; virtualBaseOpHash?: string; sessionId?: string; claimedLaneId?: string; claimedSessionId?: string; claimedAt?: string; /** Immutable, authority-bearing zone id: `turtle:///zone/`. */ zoneId?: string; /** Mutable human name. Renaming edits only this — never the id or grants. */ zoneAlias?: string; /** Prior alias, so rename is delete-then-add rather than an append. */ oldZoneAlias?: string; /** Opaque parent zoneId for nesting → grant inheritance closure. */ zoneParent?: string; /** Level granted to anon (Reader = public, None = private). */ zoneDefaultVisibility?: number; /** Principal a grant applies to (Agent Ed25519 did:key entity id). */ grantPrincipal?: string; /** Granted level. `None` is never persisted — retraction removes the fact. */ grantLevel?: number; /** Prior level, so a grant change is delete-then-add over a bounded domain. */ oldGrantLevel?: number; facts?: Fact[]; links?: Link[]; } /** * A VcsOp mirrors KernelOp but widens `kind` to accept VCS-specific strings. * We don't extend KernelOp directly because the kernel types `kind` as a * narrow union; our VCS kinds are a superset. */ /** * A VCS operation. * * ENVELOPE vs PAYLOAD (TRL-102). `hashVcsOp` hashes exactly * `{kind, timestamp, agentId, previousHash, vcs}` — so `vcs` is the payload * (identity-bearing) and any other top-level field is envelope (not hashed). * That split was previously accidental; it is now deliberate. Do not add a * top-level field expecting it to be covered by the hash — put it in `vcs`. */ export interface VcsOp { hash: string; kind: VcsOpKind | string; timestamp: string; agentId: string; previousHash?: string; vcs?: VcsPayload; /** * Envelope: local annotations attached to an op we did not mint. NOT hashed. * * `RemoteManager.prefixOp` tags pulled ops with `{e:'op', a:'remote', v:}` * so `trellis log --remote/--all` can filter them. Being outside the preimage * is the point: we annotate another peer's op without invalidating its hash. * * Not to be confused with `vcs.facts`, which IS payload — that is where * `vcs:storeAssert` puts graph facts, and it is hashed. */ facts?: import('../core/store/eav-store.js').Fact[]; links?: import('../core/store/eav-store.js').Link[]; /** * Envelope: the lane this op was minted in. NOT hashed (TRL-102). * * Ambient context, not identity — the same semantic op minted in two lanes * must produce the same hash, or peers lose dedup and cherry-picking across * lanes rewrites op identity, which breaks set-reconciliation. Lane * membership is also already implied by the journal the op lives in. * * Distinct from `vcs.laneId`, which is *subject* data for `vcs:laneCreate` / * `vcs:laneDrop` / `vcs:testRun` — those ops are ABOUT a lane, pass laneId at * mint, and must keep it inside the preimage or `laneCreate lane-A` would * hash identically to `laneCreate lane-B`. */ laneId?: string; } export interface FileChangeEvent { type: 'add' | 'modify' | 'delete' | 'rename'; path: string; oldPath?: string; contentHash?: string; oldContentHash?: string; size?: number; timestamp: string; } /** * Writer identity for an op: the signed Ed25519 principal, falling back to the * self-asserted `agentId` for unsigned ops (ADR 0022 §4). * * Lives here, not in `branch.ts`, because it is a pure function of the op and * `decompose` needs it. `branch.ts` imports `fs`, so importing this from there * dragged Node's `fs`/`path` into every consumer of `decompose` — including a * browser peer, which cannot bundle it at all. */ export declare function writerPrincipal(op: VcsOp): string; /** * Entity id of a per-writer branch head ("ref zone", ADR 0022 §4). `integration` * and the default branch collapse to the shared `branch:NAME`; every other * branch gets `branch:NAME@` so two writers never share a pointer. */ export declare function branchHeadEntity(branchName: string, principal?: string, defaultBranch?: string): string; export declare function fileEntityId(path: string): string; export declare function dirEntityId(path: string): string; export declare function branchEntityId(name: string): string; export declare function milestoneEntityId(hash: string): string; export declare function checkpointEntityId(hash: string): string; export declare function issueEntityId(id: string): string; export declare function criterionEntityId(issueId: string, index: number): string; export declare function testRunEntityId(id: string): string; export declare function decisionEntityId(id: string): string; export declare function laneEntityId(id: string): string; export interface TrellisVcsConfig { /** Absolute path to the repository root. */ rootPath: string; /** Glob patterns to ignore (e.g. ['node_modules', '.git', '*.log']). */ ignorePatterns: string[]; /** Debounce interval for file watcher in ms. */ debounceMs: number; /** Name of the default branch. */ defaultBranch: string; /** Path to the .trellis database file. */ dbPath: string; /** Whether init/watch should reconcile existing workspace files by default. */ indexWorkspace: boolean; /** Agent lane filesystem bind (ADR 0014 Phase 2). */ lanes?: { /** Provision git worktrees per lane; default true on init. */ worktreeBind?: boolean; }; /** Git mirror adapter — sync integration to main at promote/close. */ git?: { /** Auto-commit on lane promote (default true on init). */ syncOnPromote?: boolean; /** Push on issue close when --push or this flag is set. */ pushOnClose?: boolean; /** Remote name for push (default origin). */ remote?: string; /** Branch to commit on (default defaultBranch). */ branch?: string; }; /** Milestone → git commit automation. */ milestones?: { /** Auto-commit integration to git (with the milestone message) on create. */ autoCommit?: boolean; }; } export declare const DEFAULT_CONFIG: Omit; //# sourceMappingURL=types.d.ts.map