Skip to content

Commit f37e523

Browse files
authored
feat(pq-key-fingerprint/ts): phase 1 - rebuild source API surface (ENG-1760) (#22)
## Summary <!-- What does this PR do? Keep it brief. --> ## Package(s) <!-- Which package(s) are modified? --> ## Languages - [ ] TypeScript - [ ] Rust ## Checklist - [ ] Tests pass for all modified packages - [ ] Linting/formatting passes (`biome check`, `cargo fmt`) - [ ] Both language implementations are consistent (or noted as follow-up) - [ ] Package README updated if public API changed - [ ] No unnecessary dependencies added ## Related Issues <!-- Link any related issues: Fixes #123, Closes #456 -->
1 parent d7f3384 commit f37e523

9 files changed

Lines changed: 114 additions & 22 deletions

File tree

.claude/skills/create-plan-linear/SKILL.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: create-plan-linear
3-
description: "Create detailed implementation plans with codebase research and, after explicit user approval, publish the approved phased plan to Linear by creating a project under a chosen initiative plus phase and subphase issues assigned to Timur Guvenkaya."
3+
description: "Create detailed implementation plans with codebase research and, after explicit user approval, publish the approved phased plan to Linear by creating a project under a chosen initiative plus phase and subphase issues assigned to a user chosen at runtime."
44
argument-hint: "[ticket-or-file-path]"
55
---
66

@@ -11,7 +11,7 @@ Create a detailed implementation plan first. Only after explicit user approval,
1111
## Intake
1212

1313
- Read any provided ticket, plan, or file paths fully before planning.
14-
- If key inputs are missing, ask for them: objective, constraints, references, and preferred project name.
14+
- If key inputs are missing, ask for them: objective, constraints, references, preferred project name, target assignee, and plan file path.
1515
- Capture initiative and team context early when available.
1616
- Ask only questions that cannot be answered from the codebase or provided context.
1717

@@ -128,8 +128,9 @@ Create a detailed implementation plan first. Only after explicit user approval,
128128
- Set `summary` to a concise one-line overview from the plan.
129129

130130
4. Resolve assignee
131-
- Resolve Timur via `mcp__linear__get_user` with query `timur guvenkaya`.
132-
- If no exact match is found, ask the user before assigning to another user.
131+
- Ask the user which assignee to use if not already provided.
132+
- Resolve the provided assignee via `mcp__linear__get_user`.
133+
- If no exact match is found, ask the user to confirm the intended user before creating issues.
133134

134135
5. Prepare labels and severity
135136
- Derive labels from phase scope (for example: `consensus`, `execution`, `networking`, `docs`, `testing`).
@@ -148,7 +149,7 @@ Create a detailed implementation plan first. Only after explicit user approval,
148149
- Create one Linear issue per top-level phase under the created project.
149150
- Set issue title to the phase title.
150151
- Set issue description to the phase plan content (scope, changes, and success criteria).
151-
- Assign each issue to Timur.
152+
- Assign each issue to the resolved assignee.
152153
- Add derived labels, severity label, and priority.
153154

154155
7. Create subphase sub-issues
@@ -160,6 +161,7 @@ Create a detailed implementation plan first. Only after explicit user approval,
160161
8. Return sync summary
161162
- Report created project identifier/name.
162163
- Report each created phase issue and sub-issue with identifiers.
164+
- Report the plan file path used for sync.
163165
- Call out any assumptions made (team inference, severity defaults, inferred labels).
164166

165167
## Execution Rules

.claude/skills/implement-plan-linear/SKILL.md

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,30 +93,50 @@ Please run the manual verification steps for this phase and confirm when complet
9393

9494
## Graphite Workflow
9595

96-
After manual confirmation for a phase, run these three steps in order:
96+
Phases form a **Graphite stack** — each phase branch stacks on top of the previous one. The stack is created incrementally: phase 1 branches off trunk, phase 2 branches off phase 1, and so on. The entire stack is merged together after all phases are complete and reviewed.
9797

98-
1. **Sync trunk and clean up merged branches:**
99-
- `gt sync` — pulls latest trunk, restacks open branches, prompts to delete merged branches (accept deletions when prompted).
98+
After manual confirmation for a phase, run these steps in order:
99+
100+
1. **Sync trunk and restack:**
101+
- `gt sync` — pulls latest trunk, restacks open branches, accepts deletion of merged branches. Safe to run whether on trunk or on an existing stack branch.
100102

101103
2. **Create the branch with all changes committed:**
102104
- Fetch the branch name from the Linear issue via `mcp__linear__get_issue` (the `gitBranchName` field).
103-
- `gt create -am "<phase commit message>" <linear-branch-name>`
104-
- This stages all changes, commits them, and creates a new Graphite branch in one step. The branch name MUST be the one from the Linear issue (e.g. `feature/eng-1242`).
105+
- `gt create -am "<type>(<package>/<language>): phase <N> - <description> (<issue-key>)" <linear-branch-name>`
106+
- `gt create` stacks on whatever branch you are currently on — trunk for phase 1, the previous phase's branch for phase 2+.
107+
- Commit message format:
108+
- `<type>`: conventional commit type derived from the phase's intent:
109+
- `feat` — new functionality, new API surface, new exports
110+
- `fix` — bug fixes, correcting broken behavior
111+
- `refactor` — restructuring without behavior change
112+
- `test` — adding/updating tests only
113+
- `docs` — documentation, README, comments only
114+
- `chore` — build config, CI, package metadata, tooling
115+
- `<package>`: package folder name under `packages/` (e.g. `pq-jws`, `pq-oid`, `pq-key-encoder`)
116+
- `<language>`: language folder under the package (`ts`, `rust`, or `python`)
117+
- `<N>`: phase number from the plan
118+
- `<description>`: concise summary of the phase scope
119+
- `<issue-key>`: Linear issue key provided at invocation (e.g. `ENG-1640`)
120+
- Determine `<type>` by reading the phase title and scope from the plan — pick the type that best describes the primary intent of the phase.
121+
- Examples:
122+
- `feat(pq-jws/ts): phase 1 - define public contracts (ENG-1640)`
123+
- `test(pq-jws/ts): phase 4 - comprehensive test suite (ENG-1643)`
124+
- `fix(pq-oid/rust): phase 2 - correct DER length encoding (ENG-1500)`
105125

106126
3. **Submit and publish the stack:**
107-
- `gt submit --publish`
127+
- `gt submit --publish` — pushes all branches in the stack and creates/updates PRs for each.
108128

109129
4. **Trigger automated review:**
110-
- After the PR is created/updated, post a review trigger comment:
111130
- `gh pr comment <PR-number> --body "@codex review"`
112131

113132
Rules:
114133

115-
- Always run `gt sync` first to avoid "already merged" errors blocking submit.
134+
- Always run `gt sync` before `gt create` — it is safe on stack branches and keeps the stack rebased on latest trunk.
116135
- The branch name comes from Linear's `gitBranchName` field — never invent branch names.
117136
- `gt create -am` handles staging, committing, and branch creation — do not use `git add` or `git commit` separately.
118-
- Use commit messages tied to phase scope, not generic text.
137+
- Commit message must follow: `<type>(<package>/<language>): phase <N> - <description> (<issue-key>)` — derive type from the phase intent, package/language from the plan path, phase number from the plan, and issue key from the input.
119138
- Do not run `gt submit --publish` before manual confirmation.
139+
- Do **not** merge individual phase PRs — the entire stack is merged together after all phases are complete.
120140
- If a `gt` command fails, report the exact command and error output.
121141

122142
## When to Use Sub-agents
@@ -150,4 +170,4 @@ For each completed phase, report:
150170
- Re-read relevant plan and code before assuming root cause.
151171
- Consider whether the codebase evolved since the plan was written.
152172
- Surface blockers with exact command errors or plan/code mismatches.
153-
- Ask one focused question to unblock.
173+
- Ask one focused question to unblock.

bun.lock

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/pq-key-encoder/ts/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"module": "ESNext",
55
"moduleResolution": "bundler",
66
"declaration": true,
7+
"composite": true,
78
"outDir": "./dist",
89
"rootDir": "./src",
910
"strict": true,

packages/pq-key-fingerprint/ts/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"dist"
1010
],
1111
"scripts": {
12-
"build": "tsc",
12+
"build": "tsc -b",
13+
"test": "bun test",
1314
"prepublishOnly": "npm run build"
1415
},
1516
"keywords": [
@@ -19,6 +20,9 @@
1920
],
2021
"author": "",
2122
"license": "MIT",
23+
"dependencies": {
24+
"pq-key-encoder": "^1.0.3"
25+
},
2226
"devDependencies": {
2327
"typescript": "^5.0.0"
2428
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/** Base error for pq-key-fingerprint failures. */
2+
export class FingerprintError extends Error {
3+
constructor(message: string) {
4+
super(message);
5+
this.name = 'FingerprintError';
6+
Object.setPrototypeOf(this, new.target.prototype);
7+
}
8+
}
9+
10+
/** Error for invalid or missing fingerprint input values. */
11+
export class InvalidFingerprintInputError extends FingerprintError {
12+
constructor(message: string) {
13+
super(message);
14+
this.name = 'InvalidFingerprintInputError';
15+
}
16+
}
17+
18+
/** Error for key-type mismatches, such as passing private keys. */
19+
export class InvalidKeyTypeError extends FingerprintError {
20+
constructor(message: string) {
21+
super(message);
22+
this.name = 'InvalidKeyTypeError';
23+
}
24+
}
25+
26+
/** Error for unsupported digest algorithm selections. */
27+
export class UnsupportedDigestError extends FingerprintError {
28+
constructor(message: string) {
29+
super(message);
30+
this.name = 'UnsupportedDigestError';
31+
}
32+
}
33+
34+
/** Error for missing runtime cryptographic capabilities. */
35+
export class RuntimeCapabilityError extends FingerprintError {
36+
constructor(message: string) {
37+
super(message);
38+
this.name = 'RuntimeCapabilityError';
39+
}
40+
}
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
// pq-key-fingerprint - Generate fingerprints/hashes of PQ public keys
2-
// Implementation coming soon
3-
4-
export {};
1+
export * from './errors';
2+
export * from './types';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { AlgorithmName as EncoderAlgorithmName, KeyData, PQJwk } from 'pq-key-encoder';
2+
3+
export type { AlgorithmName } from 'pq-key-encoder';
4+
5+
export type FingerprintDigest = 'SHA-256' | 'SHA-384' | 'SHA-512';
6+
7+
export type FingerprintEncoding = 'hex' | 'base64' | 'base64url' | 'bytes';
8+
9+
export interface FingerprintOptions {
10+
digest?: FingerprintDigest;
11+
encoding?: FingerprintEncoding;
12+
}
13+
14+
export type PublicKeyData = Omit<KeyData, 'type' | 'alg'> & {
15+
alg: EncoderAlgorithmName;
16+
type: 'public';
17+
};
18+
19+
export type PublicKeyInput = PublicKeyData | { alg: EncoderAlgorithmName; bytes: Uint8Array };
20+
21+
export type FingerprintInput = PublicKeyInput | Uint8Array | string | PQJwk;
22+
23+
export type FingerprintResult = string | Uint8Array;

packages/pq-key-fingerprint/ts/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"esModuleInterop": true,
1111
"skipLibCheck": true
1212
},
13+
"references": [{ "path": "../../pq-key-encoder/ts" }],
1314
"include": ["src"]
1415
}

0 commit comments

Comments
 (0)