@spekn/cli 1.0.1 → 1.0.3

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.
Files changed (79) hide show
  1. package/dist/main.js +34856 -29545
  2. package/dist/prompts/governance-analysis.prompt.md +109 -0
  3. package/dist/resources/prompts/repo-analysis.prompt.md +28 -136
  4. package/dist/resources/prompts/repo-sync-analysis.prompt.md +31 -68
  5. package/dist/tui/app.d.ts +7 -0
  6. package/dist/tui/app.js +122 -0
  7. package/dist/tui/args.d.ts +8 -0
  8. package/dist/tui/args.js +57 -0
  9. package/dist/tui/capabilities/policy.d.ts +7 -0
  10. package/dist/tui/capabilities/policy.js +64 -0
  11. package/dist/tui/chunk-4WEASLXY.mjs +3444 -0
  12. package/dist/tui/chunk-755CADEG.mjs +3401 -0
  13. package/dist/tui/chunk-BUJQVTY5.mjs +3409 -0
  14. package/dist/tui/chunk-BZKKMGFB.mjs +1959 -0
  15. package/dist/tui/chunk-DJYOBCNM.mjs +3159 -0
  16. package/dist/tui/chunk-GTFTFDY4.mjs +3417 -0
  17. package/dist/tui/chunk-IMEBD2KA.mjs +3444 -0
  18. package/dist/tui/chunk-IX6DR5SW.mjs +3433 -0
  19. package/dist/tui/chunk-JKFOY4IF.mjs +2003 -0
  20. package/dist/tui/chunk-OXXZ3O5L.mjs +3378 -0
  21. package/dist/tui/chunk-SHJNIAAJ.mjs +1697 -0
  22. package/dist/tui/chunk-V4SNDRUS.mjs +1666 -0
  23. package/dist/tui/chunk-VXVHNZST.mjs +1666 -0
  24. package/dist/tui/chunk-WCTSFKTA.mjs +3459 -0
  25. package/dist/tui/chunk-X2XP5ACW.mjs +3443 -0
  26. package/dist/tui/chunk-YUYJ7VBG.mjs +2029 -0
  27. package/dist/tui/chunk-ZM3EI5IA.mjs +3384 -0
  28. package/dist/tui/chunk-ZYOX64HP.mjs +1653 -0
  29. package/dist/tui/components/frame.d.ts +8 -0
  30. package/dist/tui/components/frame.js +8 -0
  31. package/dist/tui/components/status-bar.d.ts +8 -0
  32. package/dist/tui/components/status-bar.js +8 -0
  33. package/dist/tui/index.d.ts +2 -0
  34. package/dist/tui/index.js +23 -0
  35. package/dist/tui/index.mjs +6999 -6938
  36. package/dist/tui/keymap/use-global-keymap.d.ts +19 -0
  37. package/dist/tui/keymap/use-global-keymap.js +82 -0
  38. package/dist/tui/navigation/nav-items.d.ts +3 -0
  39. package/dist/tui/navigation/nav-items.js +18 -0
  40. package/dist/tui/prompts/spec-creation-system.prompt.md +47 -0
  41. package/dist/tui/prompts/spec-refinement-system.prompt.md +81 -0
  42. package/dist/tui/screens/bridge.d.ts +8 -0
  43. package/dist/tui/screens/bridge.js +19 -0
  44. package/dist/tui/screens/decisions.d.ts +5 -0
  45. package/dist/tui/screens/decisions.js +28 -0
  46. package/dist/tui/screens/export.d.ts +5 -0
  47. package/dist/tui/screens/export.js +16 -0
  48. package/dist/tui/screens/home.d.ts +5 -0
  49. package/dist/tui/screens/home.js +33 -0
  50. package/dist/tui/screens/locked.d.ts +5 -0
  51. package/dist/tui/screens/locked.js +9 -0
  52. package/dist/tui/screens/specs.d.ts +5 -0
  53. package/dist/tui/screens/specs.js +31 -0
  54. package/dist/tui/services/client.d.ts +1 -0
  55. package/dist/tui/services/client.js +18 -0
  56. package/dist/tui/services/context-service.d.ts +19 -0
  57. package/dist/tui/services/context-service.js +246 -0
  58. package/dist/tui/shared-enums.d.ts +16 -0
  59. package/dist/tui/shared-enums.js +19 -0
  60. package/dist/tui/state/use-app-state.d.ts +35 -0
  61. package/dist/tui/state/use-app-state.js +177 -0
  62. package/dist/tui/types.d.ts +77 -0
  63. package/dist/tui/types.js +2 -0
  64. package/dist/tui/use-session-store-63YUGUFA.mjs +8 -0
  65. package/dist/tui/use-session-store-ACO2SMJC.mjs +8 -0
  66. package/dist/tui/use-session-store-BVFDAWOB.mjs +8 -0
  67. package/dist/tui/use-session-store-DJIZ3FQZ.mjs +9 -0
  68. package/dist/tui/use-session-store-EAIQA4UG.mjs +9 -0
  69. package/dist/tui/use-session-store-EFBAXC3G.mjs +8 -0
  70. package/dist/tui/use-session-store-FJOR4KTG.mjs +8 -0
  71. package/dist/tui/use-session-store-IJE5KVOC.mjs +8 -0
  72. package/dist/tui/use-session-store-KGAFXCKI.mjs +8 -0
  73. package/dist/tui/use-session-store-KS4DPNDY.mjs +8 -0
  74. package/dist/tui/use-session-store-MMHJENNL.mjs +8 -0
  75. package/dist/tui/use-session-store-OZ6HC4I2.mjs +9 -0
  76. package/dist/tui/use-session-store-PTMWISNJ.mjs +8 -0
  77. package/dist/tui/use-session-store-VCDECQMW.mjs +8 -0
  78. package/dist/tui/use-session-store-VOK5ML5J.mjs +9 -0
  79. package/package.json +6 -3
@@ -0,0 +1,109 @@
1
+ You are a governance analyst evaluating a repository's governance health. You have full access to the repository filesystem.
2
+
3
+ ## Repository Context:
4
+ - Path: {{REPO_PATH}}{{LANG_CONTEXT}}{{SIZE_CONTEXT}}
5
+ - **Static baseline score: {{STATIC_SCORE}}/100**
6
+ - Per-check static scores:
7
+ {{CHECK_SCORES}}
8
+
9
+ ## Governance Dimensions
10
+
11
+ Evaluate the repository across these 6 governance dimensions. For each, read the relevant files and score independently.
12
+
13
+ ### 1. Agent Context Depth (`agent-context-depth`, maxScore: 143, weight: {{WEIGHT_AGENT_CONTEXT}})
14
+ Evaluates how well the repo provides context to AI coding agents — regardless of which agent tools are used. Discover and read any agent context files present (common examples: AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md, GEMINI.md, or similar). Then evaluate the **quality of the context provided**, not which specific files exist:
15
+ - Build/test/lint commands with runnable code blocks
16
+ - Project structure / module map with annotated directories
17
+ - Debugging / troubleshooting / known issues guidance
18
+ - Current phase or focus indicator
19
+ - Per-subsystem verification commands (not just one global test command)
20
+ - Machine-parseable structure (headings, code blocks, YAML frontmatter)
21
+ - Multi-directory coverage: does context mention all major source directories?
22
+ - Modular context: is guidance split into focused files/sections, or one monolithic blob?
23
+ - Nested/per-package context for monorepo subdirectories
24
+ - Low content duplication across files (repeated sentences waste tokens)
25
+ - Reasonable total size (avoid bloating agent context windows)
26
+
27
+ Do NOT prescribe specific filenames, directory layouts, or tool-specific features. Evaluate what IS there and how useful it would be to any AI coding agent.
28
+
29
+ ### 2. Spec-Driven Traceability (`spec-traceability`, maxScore: 75, weight: {{WEIGHT_SPEC_TRACEABILITY}})
30
+ Evaluates how well specifications drive development. Look for:
31
+ - specs/ directory with markdown specification documents
32
+ - Spec anchors (structured references like `auth.login.requirements`)
33
+ - Code referencing spec anchors in comments
34
+ - Spec generations (integer generation number in frontmatter)
35
+ - Spec-to-code traceability links
36
+
37
+ ### 3. Governance Structure (`governance-structure`, maxScore: 70, weight: {{WEIGHT_GOVERNANCE_STRUCTURE}})
38
+ Evaluates structural governance patterns. Look for:
39
+ - .speknrc.json or equivalent config
40
+ - CI/CD governance hooks (pre-commit, PR checks)
41
+ - CODEOWNERS or equivalent ownership definitions
42
+ - Contribution guidelines (CONTRIBUTING.md)
43
+ - License file
44
+ - Well-organized directory structure
45
+
46
+ ### 4. Decision Governance (`decision-governance`, maxScore: 60, weight: {{WEIGHT_DECISION_GOVERNANCE}})
47
+ Evaluates architectural decision tracking. Look for:
48
+ - decisions/ directory with decision records (ADRs/DRs)
49
+ - Decision index file
50
+ - Proper decision status tracking (proposed/accepted/deprecated)
51
+ - Decision dating (createdAt, decidedAt timestamps)
52
+ - Cross-references between decisions and specs
53
+ - Decision templates
54
+
55
+ ### 5. Terminology Consistency (`terminology`, maxScore: 100, weight: {{WEIGHT_TERMINOLOGY}})
56
+ Evaluates naming consistency across docs and code. Look for:
57
+ - Consistent product name usage
58
+ - No spelling/casing variants of key terms
59
+ - Consistent component naming across docs and code
60
+ - Code comments using correct terminology
61
+
62
+ ### 6. Specification Frontmatter Quality (`frontmatter-quality`, maxScore: 50, weight: {{WEIGHT_FRONTMATTER}})
63
+ Evaluates the quality of YAML frontmatter in spec files. Look for:
64
+ - Required fields: title, type
65
+ - Optional: generation (positive integer)
66
+ - Valid type values (intent, capability, architectural, workflow, operational, decision)
67
+ - Valid status values (draft, review, active, archived)
68
+ - Content hints (constraints, requirements, technical, guidance)
69
+ - Relationships (dependsOn, extends, compatibleWith, conflictsWith)
70
+
71
+ ## Task
72
+
73
+ 1. Discover and read the repository's governance files — agent context files, specs/, decisions/, and any other governance artifacts
74
+ 2. Score each dimension independently (0 to maxScore)
75
+ 3. For each dimension, list specific findings with severity (error/warning/info) and actionable messages
76
+ 4. Provide strategic recommendations
77
+
78
+ Respond ONLY with valid JSON (no markdown fences, no explanation outside JSON):
79
+ {
80
+ "checkScores": [
81
+ {
82
+ "checkId": "string (one of the 6 IDs above)",
83
+ "score": "number (0 to maxScore for that check)",
84
+ "maxScore": "number (the maxScore listed above)",
85
+ "weight": "number (the weight listed above)",
86
+ "summary": "string (1-2 sentence assessment)",
87
+ "findings": [
88
+ {
89
+ "checkId": "string (same as parent)",
90
+ "severity": "error|warning|info",
91
+ "message": "string (specific, actionable finding)",
92
+ "file": "string (optional, relative file path)",
93
+ "autoFixable": false,
94
+ "speknCta": "string (optional, how Spekn helps)"
95
+ }
96
+ ]
97
+ }
98
+ ],
99
+ "rootCauses": "string (2-3 sentences: why do these governance gaps exist?)",
100
+ "priorities": [{"finding": "string", "reason": "string", "files": ["string"], "timeEstimate": "string", "scoreImpact": "string"}],
101
+ "quickWins": [{"action": "string", "steps": ["string"], "timeEstimate": "string", "scoreImpact": "string"}],
102
+ "architecturalRec": {"recommendation": "string", "implementation": ["string"], "scoreImpact": "string"},
103
+ "governanceImpact": {"currentScore": {{STATIC_SCORE}}, "potentialScore": "number (0-100 projected score after ALL recommended fixes)", "improvement": "number (potentialScore minus currentScore)"}
104
+ }
105
+
106
+ IMPORTANT:
107
+ - governanceImpact.currentScore is FIXED at {{STATIC_SCORE}} (the actual static baseline). Do NOT recompute it.
108
+ - governanceImpact.potentialScore should reflect your realistic estimate after all recommended fixes are applied. Must be 0-100.
109
+ - Each check is normalized (score/maxScore) then weighted, so the headline score is a weighted average percentage, NOT a sum of raw scores.
@@ -1,151 +1,43 @@
1
1
  You are analyzing a repository to register it with a Spekn project.
2
- You have been given Spekn MCP tools to create specifications and decisions.
2
+ You have Spekn MCP tools available to create specifications and decisions.
3
3
 
4
4
  PROJECT ID: {{PROJECT_ID}}{{ORG_INSTRUCTION}}
5
5
  REPO PATH: {{REPO_PATH}}
6
6
 
7
- DISCOVERED FILES:
8
- {{FILE_LIST}}
9
-
10
- STEP 0 — VERIFY TOOLS:
11
- Before doing anything else, list the available MCP tools to confirm you have
12
- access to spekn_spec_create, spekn_spec_list, and spekn_decision_create. If these tools are NOT available,
13
- output "ERROR: Spekn MCP tools not available. Cannot proceed with analysis." and stop.
7
+ DETECTED TECH STACK:
8
+ {{TECH_STACK}}
14
9
 
15
- STEP 1 — READ AND UNDERSTAND THE REPOSITORY:
16
- Read the governance files (CLAUDE.md, AGENTS.md, README.md), package manifests
17
- (package.json, Cargo.toml, pyproject.toml, etc.), and key source directories
18
- to understand what this project does, its tech stack, and architecture.
19
-
20
- STEP 2 — CREATE MAIN PROJECT SPECIFICATION:
21
- Use spekn_spec_create to create a main project overview spec:
22
- - Title: "Project Overview" — short, no repo name prefix
23
- - Content MUST start with a YAML frontmatter block:
24
- ---
25
- title: "Project Overview"
26
- type: intent
27
- version: "1.0.0"
28
- status: draft
29
- author: "repo ingestor"
30
- tags: [overview, project]
31
- hints:
32
- constraints: ["Key project invariants and boundaries"]
33
- requirements: ["Core project goals and capabilities"]
34
- technical: ["Tech stack, architecture patterns, build system"]
35
- guidance: ["Development conventions and contribution guidelines"]
36
- ---
37
- - After the frontmatter, include a comprehensive explanation of what the project does,
38
- tech stack, directory structure, build system, development conventions, and key decisions
39
- - This becomes the primary context for the engineering manager agent
10
+ DISCOVERED DOCUMENTATION FILES:
11
+ {{FILE_LIST}}
40
12
 
41
- STEP 3 IMPORT EXISTING SPECS:
42
- For each file categorized as "spec" in the DISCOVERED FILES list:
43
- - Read the file content
44
- - Use spekn_spec_create to create a Specification record
45
- - Use the first # heading as the title (must be unique, 3-100 chars)
46
- - If the file already has a YAML frontmatter block (---), preserve it but ensure author is set:
47
- - author: "repo ingestor" (add it when missing)
48
- - If no frontmatter exists, prepend one with:
49
- - type: "capability"
50
- - version: "1.0.0"
51
- - author: "repo ingestor"
52
- - hints: populate from the file content (constraints, requirements, technical, guidance)
53
- - Set version to "1.0.0"
13
+ NOTE: The list above contains only governance, spec, decision, and documentation files.
14
+ You MUST explore source code directories yourself using your filesystem tools (ls, Glob, Read).
15
+ The source code is your PRIMARY input for understanding the project and creating domain specs.
54
16
 
55
- For each file categorized as "decision" in the DISCOVERED FILES list:
56
- - Read the file content
57
- - First create/import its parent specification with spekn_spec_create if needed (type: "decision", author: "repo ingestor")
58
- - Then perform ACP DECISION DETECTION before creating records:
59
- - Extract one normalized decision object per explicit decision/ADR entry
60
- - Ignore vague notes that do not state a concrete choice
61
- - If one file contains multiple explicit ADR entries, create one decision record per entry
62
- - Use this normalized structure for each extracted decision:
63
- {
64
- "title": "<3-100 chars, imperative/statement form>",
65
- "description": "<what was decided, specific and concrete>",
66
- "rationale": "<why this option was chosen>",
67
- "alternatives": ["<rejected option 1>", "<rejected option 2>"]
68
- }
69
- - Formatting requirements:
70
- - title must NOT include prefixes like "Decision:", "ADR-001:", markdown symbols, or file names
71
- - description and rationale must be plain text (no markdown headings/bullets)
72
- - alternatives must be plain option strings; use [] when none are explicit
73
- - If rationale is missing, infer a concise rationale from nearby context (trade-offs/constraints)
74
- - Create each record with spekn_decision_create using:
75
- - projectId: PROJECT ID
76
- - specificationId: parent decision specification ID
77
- - title, description, rationale, alternatives from normalized object
17
+ ────────────────────────────────────────────────────────────────────────
18
+ INSTRUCTIONS
19
+ ────────────────────────────────────────────────────────────────────────
78
20
 
79
- STEP 4 ANALYZE PDF DOCUMENTS:
80
- If any files categorized as "pdf" appear in the DISCOVERED FILES list:
81
- - Check whether you have a tool that can read or extract text from PDF files
82
- (e.g. `read_file` with PDF support, a `pdf` skill, or any PDF extraction tool)
83
- - If you DO have PDF capability:
84
- - Read each PDF file to extract its text content
85
- - Determine what the document covers (architecture diagrams, requirements, RFCs,
86
- compliance docs, contracts, design documents, etc.)
87
- - For each PDF that contains specification-worthy content, use spekn_spec_create:
88
- - Title: short descriptive name derived from the PDF content (NOT the filename)
89
- - Content MUST start with a YAML frontmatter block:
90
- - type: choose the best fit ("capability", "architectural", "intent", "operational")
91
- - status: "draft"
92
- - author: "repo ingestor"
93
- - tags: ["pdf-import", ...relevant tags]
94
- - hints: summarize key content in each layer
95
- - After frontmatter, include the extracted content reformatted as clean markdown
96
- - For PDFs containing decision records or ADRs, create decisions following STEP 3 rules
97
- - If you do NOT have PDF capability:
98
- - Log: "PDF files found but no PDF reading tool available — skipping PDF analysis"
99
- - List the PDF files that were skipped so the user knows
100
- - Do NOT fail the entire analysis if PDF reading is unavailable
21
+ Before starting work, load the Spekn specification format and workflow
22
+ instructions from the MCP server. Load each of these prompts in order:
101
23
 
102
- STEP 5ASSESS GOVERNANCE AND CREATE IMPROVEMENT SPECS:
103
- Assess governance quality does the repo have CI/CD, tests, security guidelines,
104
- contribution guidelines, documentation structure?
105
- For each significant gap, use spekn_spec_create to create a draft improvement spec:
106
- - Descriptive title (e.g. "CI/CD Pipeline", "Testing Strategy")
107
- - Content MUST start with a YAML frontmatter block:
108
- - type: "capability" for new features, "operational" for ops/process improvements
109
- - status: "draft"
110
- - author: "repo ingestor"
111
- - tags: reflecting the gap area (e.g., [ci-cd, automation] or [testing, quality])
112
- - hints: summarize what the spec covers in each context layer
113
- - After frontmatter, describe what the repo SHOULD have (best practices)
114
- - Focus on quality over quantity — only create specs for real gaps
24
+ 1. spekn-spec-formatfull specification format reference (frontmatter, body, YAML rules)
25
+ 2. spekn-anchor-formatanchor heading rules and per-anchor required fields
26
+ 3. spekn-quality-scoring self-scoring checklist and quality rules
27
+ 4. spekn-repo-analysis (with args: { "projectId": "{{PROJECT_ID}}" }) 6-step repo analysis workflow
115
28
 
116
- STEP 6 FEATURE COVERAGE AND PLAN GAP ANALYSIS:
117
- Analyze feature implementation coverage against specs/FEATURE_MAP.md and related feature docs.
118
- - Read specs/FEATURE_MAP.md and list all rows marked "Planned", "Draft", "Active", "~95%", "pending", or "deferred"
119
- - For each such row, verify whether the repo has:
120
- - implementation evidence in code (routers/services/components/tests)
121
- - a corresponding feature document in specs/features/
122
- - an implementation plan (IMPLEMENTATION_PLAN.md) when feature status implies planning/active build
123
- - For missing or weakly-covered items, create improvement specs with spekn_spec_create:
124
- - Title: short descriptive name of the feature gap (e.g. "Flatpak Governance Enforcement", "Network Egress Policy")
125
- - Do NOT prefix titles with the repo name, "Gap:", or any other prefix
126
- - type: "capability" for product/runtime gaps, "operational" for process/governance gaps
127
- - tags must include "feature-coverage" and "plan-gap"
128
- - hints must explicitly include missing code surfaces and missing planning artifacts
129
- - Do not duplicate if an equivalent gap spec already exists; update existing draft instead when possible
29
+ HOW TO LOAD PROMPTS (try in order):
30
+ A) Use the MCP prompts protocol: prompts/get with name "spekn-spec-format", etc.
31
+ B) If prompts are not available, call the tool: spekn_prompt_get(name: "spekn-spec-format"), etc.
32
+ C) If both fail, report the failure and continue — do NOT stop the workflow entirely.
130
33
 
131
- STEP 7 SUMMARY:
132
- Print a summary of what you created:
133
- - Number of specs imported from existing files
134
- - Number of specs imported from PDF documents (or skipped if no PDF tool)
135
- - Number of decisions created from decision files
136
- - Number of improvement specs created
137
- - Overall governance assessment (strengths and gaps)
138
- - Feature coverage summary (implemented vs partial vs missing)
139
- - Missing plan features summary
140
- - Include a "FEATURE_COVERAGE" section in this exact line format:
141
- - FEATURE | <id-or-name> | <status> | <evidence-or-missing>
142
- - Include a "MISSING_PLAN_FEATURES" section in this exact line format:
143
- - PLAN_GAP | <id-or-name> | <missing-artifact> | <recommended-spec-title>
144
- - Include a "DECISIONS_CREATED" section in this exact line format:
145
- - DECISION | <source-file> | <title> | <specificationId>
34
+ Read and internalize each prompt's content, then follow the workflow
35
+ steps from spekn-repo-analysis using the runtime context above (tech
36
+ stack, discovered files, repo path) as your input data.
146
37
 
147
38
  RULES:
148
- - ALWAYS use Spekn MCP create tools (spekn_spec_create / spekn_decision_create) — never just describe what you would create
149
- - Each spec title must be unique within the project use short descriptive titles, never prefix with repo name
150
- - Do NOT create specs for governance files (CLAUDE.md, AGENTS.md, .cursorrules) those are context, not specs
39
+ - ALWAYS use MCP tools (spekn_spec_create / spekn_decision_create) — never just describe what you would create
40
+ - Every spec MUST follow the format from spekn-spec-format
41
+ - Every spec MUST score at least B (75+) per the spekn-quality-scoring checklist
151
42
  - If a tool call fails, report the error and continue with the next item
43
+ - Do NOT create specs for governance files (CLAUDE.md, AGENTS.md, .cursorrules)
@@ -3,83 +3,46 @@ Your role is to detect drift, decide what to update, and avoid duplicate specs.
3
3
 
4
4
  PROJECT ID: {{PROJECT_ID}}{{ORG_INSTRUCTION}}
5
5
  REPO PATH: {{REPO_PATH}}
6
+
6
7
  COMMIT CONTEXT:
7
8
  {{COMMIT_CONTEXT}}
8
9
 
9
- DISCOVERED FILES:
10
- {{FILE_LIST}}
11
-
12
- STEP 0 — VERIFY TOOLS:
13
- List available tools and confirm you have:
14
- - spekn_spec_list
15
- - spekn_spec_create
16
- - spekn_spec_update
17
- - spekn_decision_create
18
- - spekn_decision_update
19
- If missing critical tools, output an error and stop.
10
+ DETECTED TECH STACK:
11
+ {{TECH_STACK}}
20
12
 
21
- STEP 1 — LOAD CURRENT SaaS STATE FIRST:
22
- Before touching anything:
23
- 1. Call spekn_spec_list for the project using pagination.
24
- - API limit is max 100 items per page.
25
- - Use `limit <= 100` and increment `offset` until no more items are returned.
26
- 2. Build a map of existing specs by:
27
- - exact title
28
- - normalized title (case/spacing/punctuation insensitive)
29
- 3. Treat locked specs as canonical. Never create a duplicate just because content differs.
13
+ DISCOVERED DOCUMENTATION FILES:
14
+ {{FILE_LIST}}
30
15
 
31
- STEP 2 FILTER NON-SOURCE EXPORT ARTIFACTS:
32
- Files under `spekn/context/specs/**` and `spekn/context/decisions/**` are export artifacts.
33
- Do NOT re-import these as new specs by default.
34
- Only use them as evidence for drift, not as direct create input.
16
+ NOTE: The list above contains only governance, spec, decision, and documentation files.
17
+ You have full filesystem access — use ls, Glob, and Read to explore source code directories
18
+ when you need to understand code changes, detect new modules, or verify drift.
35
19
 
36
- STEP 3 — FOR EACH DISCOVERED SOURCE FILE, DECIDE ACTION:
37
- For each relevant source file, choose exactly one:
38
- - SKIP: no meaningful drift
39
- - UPDATE_EXISTING: matching spec exists and should be updated
40
- - CREATE_NEW: truly new capability/intent/decision area with no equivalent existing spec
20
+ ────────────────────────────────────────────────────────────────────────
21
+ INSTRUCTIONS
22
+ ────────────────────────────────────────────────────────────────────────
41
23
 
42
- Decision policy:
43
- - Prefer UPDATE_EXISTING over CREATE_NEW when a semantically equivalent spec exists.
44
- - CREATE_NEW only when no reasonable existing target exists.
45
- - Never create a “repo ingestor import ...” duplicate of an existing locked/canonical spec.
46
- - If uncertain between update and create, choose update and explain rationale.
47
- - Give extra weight to commit-range changes since LAST_SYNC_COMMIT when deciding drift.
48
- - If code/protocol files changed, verify corresponding specs/decisions were updated; if not, propose targeted updates.
24
+ Before starting work, load the Spekn specification format and workflow
25
+ instructions from the MCP server. Load each of these prompts in order:
49
26
 
50
- STEP 4APPLY CHANGES:
51
- - Use spekn_spec_update for UPDATE_EXISTING actions.
52
- - Use spekn_spec_create only for CREATE_NEW actions.
53
- - Use decision create/update tools similarly with dedupe intent.
54
- - Keep titles stable for existing specs; avoid generating near-duplicate titles.
55
- - For UPDATE_EXISTING calls, include version/history intent:
56
- - prefer `changeType: "patch"` for small clarifications
57
- - use `changeType: "minor"` for new requirements/constraints
58
- - set concise `changeDescription` referencing commit-range drift rationale
27
+ 1. spekn-spec-formatfull specification format reference (frontmatter, body, YAML rules)
28
+ 2. spekn-anchor-format anchor heading rules and per-anchor required fields
29
+ 3. spekn-quality-scoring self-scoring checklist and quality rules
30
+ 4. spekn-repo-sync (with args: { "projectId": "{{PROJECT_ID}}" }) 5-step repo sync workflow
59
31
 
60
- STEP 4.5 ASK FOR APPROVAL WHEN CONFIDENCE IS LOW:
61
- Before applying a low-confidence update/create (for example: weak evidence, ambiguous target mapping, or conflicting interpretation):
62
- - trigger an interactive ACP question to the client (`session/prompt`) with explicit options:
63
- - approve
64
- - skip
65
- - if approval is not explicit, skip the low-confidence change
66
- - mention each prompted item again in REVIEW_NOTES
32
+ HOW TO LOAD PROMPTS (try in order):
33
+ A) Use the MCP prompts protocol: prompts/get with name "spekn-spec-format", etc.
34
+ B) If prompts are not available, call the tool: spekn_prompt_get(name: "spekn-spec-format"), etc.
35
+ C) If both fail, report the failure and continue — do NOT stop the workflow entirely.
67
36
 
68
- STEP 5 OUTPUT SUMMARY:
69
- Output:
70
- 1. DRIFT_SUMMARY
71
- - file, drift type, severity, target spec (if any)
72
- 2. SYNC_ACTION_PLAN
73
- - ACTION | SKIP/UPDATE_EXISTING/CREATE_NEW | file | target/new title | reason
74
- 3. SYNC_APPLIED
75
- - APPLIED | update/create/skip | entity type | id/title
76
- 4. REVIEW_NOTES
77
- - low-confidence updates that should be human-reviewed
78
- - missing spec/decision coverage for changed code/protocol files
37
+ Read and internalize each prompt's content, then follow the workflow
38
+ steps from spekn-repo-sync using the runtime context above (tech stack,
39
+ discovered files, repo path, commit context) as your input data.
79
40
 
80
41
  RULES:
81
- - Do not mass-create specs.
82
- - Minimize churn.
83
- - Respect existing canonical spec set.
84
- - Every tool call must include projectId and organizationId when required.
85
- - Spec titles must be short and descriptive never prefix with the repo name, "Gap:", or other prefixes.
42
+ - ALWAYS use MCP tools (spekn_spec_create / spekn_spec_update / spekn_decision_create) — never just describe what you would create
43
+ - Every spec MUST follow the format from spekn-spec-format
44
+ - Every spec MUST score at least B (75+) per the spekn-quality-scoring checklist
45
+ - Frontmatter MUST stay under 2048 bytes — if a tool call fails with size limit, trim and retry
46
+ - Minimize churnprefer updates over new specs
47
+ - Respect existing canonical spec set
48
+ - If a tool call fails for other reasons, report the error and continue with the next item
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { TuiScreenId } from './types';
3
+ export declare function TuiApp({ apiUrl, initialScreen, projectId }: {
4
+ apiUrl: string;
5
+ initialScreen: TuiScreenId;
6
+ projectId?: string;
7
+ }): React.JSX.Element;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TuiApp = TuiApp;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const ink_1 = require("ink");
6
+ const ui_1 = require("@inkjs/ui");
7
+ const use_app_state_1 = require("./state/use-app-state");
8
+ const use_global_keymap_1 = require("./keymap/use-global-keymap");
9
+ const frame_1 = require("./components/frame");
10
+ const status_bar_1 = require("./components/status-bar");
11
+ const home_1 = require("./screens/home");
12
+ const specs_1 = require("./screens/specs");
13
+ const export_1 = require("./screens/export");
14
+ const decisions_1 = require("./screens/decisions");
15
+ const bridge_1 = require("./screens/bridge");
16
+ const locked_1 = require("./screens/locked");
17
+ /** Brand-aligned theme: Electric Indigo spinner, semantic colors via component defaults */
18
+ const speknTheme = (0, ui_1.extendTheme)(ui_1.defaultTheme, {
19
+ components: {
20
+ Spinner: {
21
+ styles: {
22
+ frame: () => ({ color: '#6366F1' }),
23
+ },
24
+ },
25
+ },
26
+ });
27
+ function renderMainScreen(screen, state) {
28
+ if (screen === 'home')
29
+ return (0, jsx_runtime_1.jsx)(home_1.HomeScreen, { state: state });
30
+ if (screen === 'specs')
31
+ return (0, jsx_runtime_1.jsx)(specs_1.SpecsScreen, { state: state });
32
+ if (screen === 'export')
33
+ return (0, jsx_runtime_1.jsx)(export_1.ExportScreen, { state: state });
34
+ if (screen === 'decisions')
35
+ return (0, jsx_runtime_1.jsx)(decisions_1.DecisionsScreen, { state: state });
36
+ if (screen === 'bridge')
37
+ return (0, jsx_runtime_1.jsx)(bridge_1.BridgeScreen, { state: state });
38
+ const nav = state.navPolicy.find((item) => item.id === screen);
39
+ return (0, jsx_runtime_1.jsx)(locked_1.LockedScreen, { item: nav });
40
+ }
41
+ function TuiApp({ apiUrl, initialScreen, projectId }) {
42
+ const { state, refresh, setScreen, toggleHelp, setSearchQuery, setCommandMode, setExportFormat, previewExport, generateExport, bridgeStart, bridgeStop, appendLog, } = (0, use_app_state_1.useAppState)(apiUrl, initialScreen, projectId);
43
+ (0, use_global_keymap_1.useGlobalKeymap)({
44
+ screen: state.screen,
45
+ navPolicy: state.navPolicy,
46
+ commandMode: state.commandMode,
47
+ showHelp: state.showHelp,
48
+ onNavigate: setScreen,
49
+ onHelpToggle: toggleHelp,
50
+ onSearchToggle: () => setSearchQuery(state.searchQuery ? '' : '*'),
51
+ onSearchClear: () => setSearchQuery(''),
52
+ onCommandModeToggle: setCommandMode,
53
+ onRefresh: () => {
54
+ void refresh();
55
+ },
56
+ onExportPreview: () => {
57
+ void previewExport();
58
+ },
59
+ onExportGenerate: () => {
60
+ void generateExport();
61
+ },
62
+ onBridgeStart: bridgeStart,
63
+ onBridgeStop: () => {
64
+ void bridgeStop();
65
+ },
66
+ });
67
+ const handleCommandSubmit = (command) => {
68
+ const normalized = command.trim().toLowerCase();
69
+ setCommandMode(false);
70
+ if (!normalized)
71
+ return;
72
+ if (normalized === 'help') {
73
+ toggleHelp();
74
+ return;
75
+ }
76
+ if (normalized === 'refresh' || normalized === 'r') {
77
+ void refresh();
78
+ return;
79
+ }
80
+ if (normalized.startsWith('goto ')) {
81
+ const target = normalized.replace('goto ', '').trim();
82
+ setScreen(target);
83
+ appendLog(`[nav] goto ${target}`);
84
+ return;
85
+ }
86
+ if (normalized === 'show specs') {
87
+ setScreen('specs');
88
+ return;
89
+ }
90
+ if (normalized === 'show export') {
91
+ setScreen('export');
92
+ return;
93
+ }
94
+ if (normalized === 'run export') {
95
+ void generateExport();
96
+ return;
97
+ }
98
+ if (normalized === 'format claude') {
99
+ setExportFormat('claude-md');
100
+ appendLog('[export] Format switched to claude-md');
101
+ return;
102
+ }
103
+ if (normalized === 'format cursor') {
104
+ setExportFormat('cursorrules');
105
+ appendLog('[export] Format switched to cursorrules');
106
+ return;
107
+ }
108
+ if (normalized === 'bridge start') {
109
+ bridgeStart();
110
+ return;
111
+ }
112
+ if (normalized === 'bridge stop') {
113
+ void bridgeStop();
114
+ return;
115
+ }
116
+ appendLog(`[command] Unknown: ${command}`);
117
+ };
118
+ const left = `${state.boot?.organizationName ?? '...'} / ${state.boot?.projectName ?? '...'}`;
119
+ const center = state.loading ? 'Loading...' : state.statusLine;
120
+ const right = `${state.screen} | phase:${state.workflow.currentPhase ?? 'n/a'} | role:${state.boot?.role ?? 'n/a'} | tier:${state.boot?.plan ?? 'n/a'}`;
121
+ return ((0, jsx_runtime_1.jsx)(ui_1.ThemeProvider, { theme: speknTheme, children: (0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { bold: true, color: "cyan", children: "Spekn TUI - Technical Cockpit" }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Shortcuts: j/k/h/l nav, : commands, ? help, r refresh, Ctrl+C quit" }), state.error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ui_1.Alert, { variant: "error", children: state.error }) })) : null, (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { width: "28%", flexDirection: "column", children: (0, jsx_runtime_1.jsx)(frame_1.Frame, { title: "Navigation", children: state.navPolicy.map((item, index) => ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: state.screen === item.id ? 'green' : item.state === 'locked' ? 'yellow' : item.state === 'disabled' ? 'gray' : undefined, children: [state.screen === item.id ? '>' : ' ', " ", index + 1, ". ", item.label, item.state === 'locked' ? ' (locked)' : item.state === 'disabled' ? ' (disabled)' : ''] }, item.id))) }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { width: "52%", flexDirection: "column", children: (0, jsx_runtime_1.jsx)(frame_1.Frame, { title: "Context", children: renderMainScreen(state.screen, state) }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { width: "20%", flexDirection: "column", children: (0, jsx_runtime_1.jsx)(frame_1.Frame, { title: "Event Log", dim: true, children: (state.logs.length === 0 ? ['[system] ready'] : state.logs.slice(0, 7)).map((line, index) => ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: line }, `log-${index}`))) }) })] }), state.showHelp ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ui_1.Alert, { variant: "info", children: "Help: j/k/h/l navigate | :help | :goto specs | :run export | format claude/cursor | bridge start/stop" }) })) : null, state.commandMode ? ((0, jsx_runtime_1.jsxs)(ink_1.Box, { marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "green", children: ":" }), (0, jsx_runtime_1.jsx)(ui_1.TextInput, { placeholder: "command...", onSubmit: handleCommandSubmit })] })) : null, (0, jsx_runtime_1.jsx)(status_bar_1.StatusBar, { left: left, center: center, right: right })] }) }));
122
+ }
@@ -0,0 +1,8 @@
1
+ import type { TuiScreenId } from './types';
2
+ export interface TuiCliOptions {
3
+ projectId?: string;
4
+ apiUrl: string;
5
+ initialView: TuiScreenId;
6
+ noColor: boolean;
7
+ }
8
+ export declare function parseTuiArgs(args: string[]): TuiCliOptions;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTuiArgs = parseTuiArgs;
4
+ const VIEW_ALIASES = {
5
+ home: 'home',
6
+ specs: 'specs',
7
+ export: 'export',
8
+ decisions: 'decisions',
9
+ bridge: 'bridge',
10
+ };
11
+ function parseTuiArgs(args) {
12
+ let projectId;
13
+ let apiUrl = process.env.SPEKN_API_URL ?? 'http://localhost:3000';
14
+ let initialView = 'home';
15
+ let noColor = false;
16
+ for (let i = 0; i < args.length; i++) {
17
+ const arg = args[i];
18
+ if ((arg === '--project-id' || arg === '--project') && args[i + 1]) {
19
+ projectId = args[++i];
20
+ continue;
21
+ }
22
+ if (arg.startsWith('--project-id=')) {
23
+ projectId = arg.slice('--project-id='.length);
24
+ continue;
25
+ }
26
+ if (arg === '--api-url' && args[i + 1]) {
27
+ apiUrl = args[++i];
28
+ continue;
29
+ }
30
+ if (arg.startsWith('--api-url=')) {
31
+ apiUrl = arg.slice('--api-url='.length);
32
+ continue;
33
+ }
34
+ if (arg === '--view' && args[i + 1]) {
35
+ const candidate = VIEW_ALIASES[String(args[++i]).toLowerCase()];
36
+ if (candidate)
37
+ initialView = candidate;
38
+ continue;
39
+ }
40
+ if (arg.startsWith('--view=')) {
41
+ const candidate = VIEW_ALIASES[arg.slice('--view='.length).toLowerCase()];
42
+ if (candidate)
43
+ initialView = candidate;
44
+ continue;
45
+ }
46
+ if (arg === '--no-color') {
47
+ noColor = true;
48
+ continue;
49
+ }
50
+ }
51
+ return {
52
+ projectId,
53
+ apiUrl,
54
+ initialView,
55
+ noColor,
56
+ };
57
+ }
@@ -0,0 +1,7 @@
1
+ import { OrganizationPlan } from '../shared-enums';
2
+ import type { CapabilityContext, NavItemPolicy } from '../types';
3
+ type OrganizationPlanType = (typeof OrganizationPlan)[keyof typeof OrganizationPlan];
4
+ export declare function meetsMinimumTier(current: OrganizationPlanType, required: OrganizationPlanType): boolean;
5
+ export declare function resolveNavPolicy(ctx: CapabilityContext): NavItemPolicy[];
6
+ export declare function isActionAllowed(policy: NavItemPolicy): boolean;
7
+ export {};