Skip to content

Commit 793d057

Browse files
tbitcsoz-agent
andcommitted
feat(#177): patent-prosecution type + github-health-check skill + prosecution phases
Patent prosecution project type (issue #177): - config.py: add PATENT_PROSECUTION = 'patent-prosecution' to ProjectType enum - config.py: add fallback_type field to ProjectConfig (allows older specsmith to degrade gracefully to spec-document while recording intended type) - config.py: add IP prosecution fields — ip_families, claim_themes, provisional_app_number, non_provisional_deadline, entity_status, assignee, counsel, inventors, specs_dir, prosecution_dir, strategy_dir, filings_dir - config.py: add PATENT_PROSECUTION to _TYPE_LABELS - phase.py: add 7-phase IP prosecution lifecycle as PROSECUTION_PHASES (provisional-draft → filing → prior-art-search → claim-hardening → non-provisional-draft → examination → allowance). Merged into PHASE_MAP so read_phase() correctly handles cpsc-core's aee_phase: claim-hardening - tools.py: add PATENT_PROSECUTION tool entry (vale, cspell, pandoc, claim-ref-check) Skills catalog (5 new): - github-health-check (devops): systematic CI/PR/CodeQL/Dependabot triage — ordered triage playbook, gh api commands for all alert types, full health snapshot one-liner - patent-prosecution-workflow (governance): prior-art protocol, MCP server selection matrix, PPUBS→PatentsView fallback, PAR ID format, claim theme tracking, ledger entry format, prosecution phases table, roles, invariants - github-actions-ci, gh-ci-polling, terminal-awareness (already committed) Docs: - skills-index.md: 62→67 skills, updated Governance (10) and DevOps (6) and Cross-Platform (3) - api_surface.json fixture regenerated Architecture decision: - CI/CD health → SKILL (github-health-check): agents need knowledge of triage order, not new CLI commands - Patent prosecution → BOTH code (type registration, phases) AND skill (protocol knowledge) Closes #177 Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent cccde17 commit 793d057

6 files changed

Lines changed: 559 additions & 7 deletions

File tree

docs/site/skills-index.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Built-in Skills Index
22

3-
specsmith ships with **62 built-in skills** across 11 domains.
3+
specsmith ships with **67 built-in skills** across 11 domains.
44
Each skill is a curated `SKILL.md` injected into the agent context with
55
`specsmith skill activate <slug>` or auto-matched by project type.
66

@@ -16,15 +16,18 @@ Each skill is a curated `SKILL.md` injected into the agent context with
1616

1717
---
1818

19-
## Governance (6)
19+
## Governance (10)
2020

21-
Skills for project governance workflows, verification, and release management.
21+
Skills for project governance workflows, verification, release management, ESDB, CI polling, and IP prosecution.
2222

2323
| Slug | Name | Key tags |
2424
|------|------|----------|
25+
| `chronomemory-esdb` | ChronoMemory ESDB — epistemic state database (v0.1.1) | esdb, chronomemory, wal, query, context-pack |
2526
| `diff-reviewer` | Diff Reviewer — surface changes for approval | git, review, pr |
27+
| `gh-ci-polling` | GitHub Actions CI polling — smart wait (no sleep) | ci, gh, polling, github-actions |
2628
| `issue-triage` | Issue Triage — classify and prioritise GitHub issues | github, issues, labels |
2729
| `onboarding-coach` | Onboarding Coach — guided first session | onboarding, first-run |
30+
| `patent-prosecution-workflow` | Patent Prosecution Workflow — prior-art, USPTO MCP, PAR | patent, uspto, ppubs, claim-themes, ip |
2831
| `planner` | Planner — propose-then-execute | planning, aee, governance |
2932
| `release-pilot` | Release Pilot — gitflow release cut | git, semver, release, gitflow |
3033
| `verifier` | Verifier — five-gate verification | audit, tests, verification |
@@ -119,14 +122,16 @@ Cloud CLI and infrastructure skills.
119122

120123
---
121124

122-
## DevOps (4)
125+
## DevOps (6)
123126

124-
Container, orchestration, and CI/CD skills.
127+
Container, orchestration, CI/CD, and GitHub health skills.
125128

126129
| Slug | Name | Key tags |
127130
|------|------|----------|
128131
| `ci-cd-github-actions` | GitHub Actions — workflows, matrix, secrets, caching | github-actions, ci, yaml |
129132
| `docker-workflow` | Docker — multi-stage builds, Compose, registries | docker, compose, dockerfile |
133+
| `github-actions-ci` | GitHub Actions CI — Layer1Labs pattern (zero-trust, parallel) | ci, permissions, zero-trust, matrix |
134+
| `github-health-check` | GitHub Health Check — CI/PR/security/code-quality triage | ci, codeql, dependabot, pr, triage |
130135
| `kubernetes` | Kubernetes — kubectl, Helm, namespaces, GitOps | kubernetes, helm, gitops |
131136
| `terraform` | Terraform — init/plan/apply, state, modules | terraform, iac, hcl |
132137

@@ -145,14 +150,15 @@ iOS, Android, Flutter, and React Native skills.
145150

146151
---
147152

148-
## Cross-Platform (2)
153+
## Cross-Platform (3)
149154

150-
Cross-platform build and package manager skills.
155+
Cross-platform build, package manager, and shell awareness skills.
151156

152157
| Slug | Name | Key tags |
153158
|------|------|----------|
154159
| `cmake-cross-platform` | CMake — cross-platform builds, vcpkg, conan, presets | cmake, vcpkg, conan |
155160
| `package-managers` | Package Managers — brew, winget, scoop, apt, nix | brew, winget, apt, nix |
161+
| `terminal-awareness` | Terminal Awareness — PowerShell 5/7, cmd.exe, bash/zsh/fish, PID | powershell, pwsh, cmd, bash, pid, subprocess |
156162

157163
---
158164

src/specsmith/config.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class ProjectType(str, Enum):
6666
EMBEDDED_PYTHON_HMI = "embedded-python-hmi" # #109: hardware-interfacing kiosk/HMI
6767
RESEARCH_PYTHON = "research-python" # #153: experiment/research packages (no CLI)
6868
SAFETY_CRITICAL = "safety-critical" # #129: IEC 60204-1/62061/61508 safety-critical
69+
# IP / Patent
70+
PATENT_PROSECUTION = "patent-prosecution" # #177: IP prosecution with USPTO MCP lifecycle
6971

7072

7173
class Platform(str, Enum):
@@ -194,6 +196,67 @@ class ProjectConfig(BaseModel):
194196
),
195197
)
196198

199+
# Fallback type — used when this project type is not yet supported
200+
# by the installed specsmith version. specsmith silently falls back to
201+
# this type for scaffolding purposes while still recording the intended type.
202+
fallback_type: str = Field(
203+
default="",
204+
description=(
205+
"Fallback project type for scaffold generation when `type` is not yet "
206+
"supported by the installed specsmith version (e.g. 'spec-document' as "
207+
"fallback for 'patent-prosecution')."
208+
),
209+
)
210+
211+
# IP prosecution fields (used when type == 'patent-prosecution')
212+
provisional_app_number: str = Field(
213+
default="", description="USPTO provisional application number (e.g. '63/980,251')"
214+
)
215+
provisional_filed_date: str = Field(
216+
default="", description="Date the provisional was filed (YYYY-MM-DD)"
217+
)
218+
non_provisional_deadline: str = Field(
219+
default="",
220+
description="12-month non-provisional conversion deadline (YYYY-MM-DD)",
221+
)
222+
entity_status: str = Field(default="", description="USPTO entity status: small, micro, large")
223+
assignee: str = Field(default="", description="Patent assignee / rights holder")
224+
counsel: str = Field(default="", description="Patent counsel firm name")
225+
inventors: list[dict[str, str]] = Field(
226+
default_factory=list,
227+
description="List of inventors with name and role keys",
228+
)
229+
ip_families: list[dict[str, Any]] = Field(
230+
default_factory=list,
231+
description=(
232+
"IP patent families. Each entry: {id, name, phase, provisional, themes, "
233+
"anchor_spec, ...}."
234+
),
235+
)
236+
claim_themes: list[dict[str, Any]] = Field(
237+
default_factory=list,
238+
description=(
239+
"Claim themes for the primary IP family. Each entry: {id, name, description, "
240+
"risk, primary_comparator, last_par_run}."
241+
),
242+
)
243+
specs_dir: str = Field(
244+
default="docs/ip/specs",
245+
description="Normative specification directory for IP repos",
246+
)
247+
prosecution_dir: str = Field(
248+
default="docs/ip/prosecution",
249+
description="Prior-art protocol and prosecution planning directory",
250+
)
251+
strategy_dir: str = Field(
252+
default="docs/ip/strategy",
253+
description="IP strategy documents directory",
254+
)
255+
filings_dir: str = Field(
256+
default="docs/ip/filings",
257+
description="Immutable filed artifacts directory",
258+
)
259+
197260
# FPGA-specific
198261
fpga_vendor: str = Field(
199262
default="",
@@ -471,6 +534,8 @@ def project_type_enum(self) -> ProjectType | None:
471534
ProjectType.EMBEDDED_PYTHON_HMI: "Embedded Python HMI / kiosk (hardware-interfacing)",
472535
ProjectType.RESEARCH_PYTHON: "Research Python (experiments, no CLI distribution)",
473536
ProjectType.SAFETY_CRITICAL: "Safety-critical embedded (IEC 60204-1/62061/61508)",
537+
# IP / Patent
538+
ProjectType.PATENT_PROSECUTION: "Patent prosecution repository (USPTO IP lifecycle)",
474539
}
475540

476541
_SECTION_REFS: dict[str, str] = {

src/specsmith/phase.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,153 @@ def _check(root: Path) -> bool:
398398
PHASE_MAP: dict[str, Phase] = {p.key: p for p in PHASES}
399399
PHASE_ORDER: list[str] = [p.key for p in PHASES]
400400

401+
# ---------------------------------------------------------------------------
402+
# IP Prosecution phases (patent-prosecution project type — issue #177)
403+
# ---------------------------------------------------------------------------
404+
405+
PROSECUTION_PHASES: list[Phase] = [
406+
Phase(
407+
key="provisional-draft",
408+
label="Provisional Draft",
409+
emoji="\U0001f4dd",
410+
description="Invention disclosure and provisional specification being written.",
411+
checks=[
412+
PhaseCheck("AGENTS.md exists", _file_exists("AGENTS.md")),
413+
PhaseCheck("docs/ip/specs/ exists", _file_exists("docs/ip/specs")),
414+
PhaseCheck("scaffold.yml has ip_families field", _scaffold_field("ip_families")),
415+
],
416+
commands=["specsmith audit", 'specsmith ledger add "Provisional draft in progress"'],
417+
next_phase="filing",
418+
),
419+
Phase(
420+
key="filing",
421+
label="Filing",
422+
emoji="\U0001f4e8",
423+
description="Provisional application prepared and submitted to USPTO.",
424+
checks=[
425+
PhaseCheck("docs/ip/filings/ exists", _file_exists("docs/ip/filings")),
426+
PhaseCheck(
427+
"scaffold.yml has provisional_app_number",
428+
_scaffold_field("provisional_app_number"),
429+
),
430+
PhaseCheck(
431+
"scaffold.yml has provisional_filed_date",
432+
_scaffold_field("provisional_filed_date"),
433+
),
434+
],
435+
commands=[
436+
'specsmith ledger add "Provisional filed at USPTO — App. <number>"',
437+
'specsmith trace seal milestone "Provisional filed"',
438+
],
439+
next_phase="prior-art-search",
440+
),
441+
Phase(
442+
key="prior-art-search",
443+
label="Prior-Art Search",
444+
emoji="\U0001f50e",
445+
description="Systematic prior-art protocol executed across all claim themes.",
446+
checks=[
447+
PhaseCheck(
448+
"scaffold.yml has provisional_app_number",
449+
_scaffold_field("provisional_app_number"),
450+
),
451+
PhaseCheck(
452+
"LEDGER.md has PAR run entry",
453+
lambda root: any(
454+
"PAR-" in (root / c).read_text(encoding="utf-8", errors="ignore")
455+
for c in ["docs/LEDGER.md", "LEDGER.md"]
456+
if (root / c).exists()
457+
),
458+
),
459+
PhaseCheck("docs/ip/prosecution/ exists", _file_exists("docs/ip/prosecution")),
460+
],
461+
commands=[
462+
"prior-art protocol: start Themes A-H (USPTO MCP)",
463+
'specsmith ledger add "PAR-YYYY-MM-DD-001 complete — Themes A-H"',
464+
],
465+
next_phase="claim-hardening",
466+
),
467+
Phase(
468+
key="claim-hardening",
469+
label="Claim Hardening",
470+
emoji="\U0001f527",
471+
description="Claim language refined based on prior-art findings; §101/§102/§103 addressed.",
472+
checks=[
473+
PhaseCheck(
474+
"LEDGER.md has PAR run entry",
475+
lambda root: any(
476+
"PAR-" in (root / c).read_text(encoding="utf-8", errors="ignore")
477+
for c in ["docs/LEDGER.md", "LEDGER.md"]
478+
if (root / c).exists()
479+
),
480+
),
481+
PhaseCheck("docs/ip/specs/ has content", _file_min_lines("docs/ip/specs", 1)),
482+
PhaseCheck("docs/ip/strategy/ exists", _file_exists("docs/ip/strategy")),
483+
],
484+
commands=[
485+
'specsmith ledger add "Claim hardening session — Theme <X> hardened"',
486+
'specsmith trace seal decision "Claim strategy approved by counsel"',
487+
],
488+
next_phase="non-provisional-draft",
489+
),
490+
Phase(
491+
key="non-provisional-draft",
492+
label="Non-Provisional Draft",
493+
emoji="\U0001f4c4",
494+
description="Anchor non-provisional and continuation drafts being prepared by counsel.",
495+
checks=[
496+
PhaseCheck(
497+
"scaffold.yml has non_provisional_deadline",
498+
_scaffold_field("non_provisional_deadline"),
499+
),
500+
PhaseCheck("docs/ip/filings/ exists", _file_exists("docs/ip/filings")),
501+
PhaseCheck("docs/ip/strategy/ exists", _file_exists("docs/ip/strategy")),
502+
],
503+
commands=[
504+
'specsmith ledger add "Non-provisional draft v<N> submitted to counsel"',
505+
],
506+
next_phase="examination",
507+
),
508+
Phase(
509+
key="examination",
510+
label="Examination",
511+
emoji="\U0001f50d",
512+
description="Application under examination at USPTO. Responding to office actions.",
513+
checks=[
514+
PhaseCheck("docs/ip/filings/ exists", _file_exists("docs/ip/filings")),
515+
PhaseCheck(
516+
"scaffold.yml has provisional_app_number",
517+
_scaffold_field("provisional_app_number"),
518+
),
519+
],
520+
commands=[
521+
'specsmith ledger add "OA response filed — <date>"',
522+
'specsmith trace seal milestone "Office action response submitted"',
523+
],
524+
next_phase="allowance",
525+
),
526+
Phase(
527+
key="allowance",
528+
label="Allowance",
529+
emoji="\u2705",
530+
description="Patent allowed or continuation strategy in execution.",
531+
checks=[
532+
PhaseCheck("docs/ip/filings/ exists", _file_exists("docs/ip/filings")),
533+
PhaseCheck("Trace vault has seals", _trace_vault_exists()),
534+
],
535+
commands=[
536+
'specsmith ledger add "NOA received — patent allowed"',
537+
'specsmith trace seal milestone "Patent allowed"',
538+
],
539+
next_phase=None,
540+
),
541+
]
542+
543+
# Merge prosecution phases into PHASE_MAP so read_phase() can find them.
544+
# Prosecution phases are intentionally NOT in PHASE_ORDER (the AEE sequence).
545+
PROSECUTION_PHASE_MAP: dict[str, Phase] = {p.key: p for p in PROSECUTION_PHASES}
546+
PHASE_MAP.update(PROSECUTION_PHASE_MAP)
547+
401548

402549
# ---------------------------------------------------------------------------
403550
# scaffold.yml I/O

0 commit comments

Comments
 (0)