raise-cli 2.2.1__py3-none-any.whl
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.
- raise_cli/__init__.py +38 -0
- raise_cli/__main__.py +30 -0
- raise_cli/adapters/__init__.py +91 -0
- raise_cli/adapters/declarative/__init__.py +26 -0
- raise_cli/adapters/declarative/adapter.py +267 -0
- raise_cli/adapters/declarative/discovery.py +94 -0
- raise_cli/adapters/declarative/expressions.py +150 -0
- raise_cli/adapters/declarative/reference/__init__.py +1 -0
- raise_cli/adapters/declarative/reference/github.yaml +143 -0
- raise_cli/adapters/declarative/schema.py +98 -0
- raise_cli/adapters/filesystem.py +299 -0
- raise_cli/adapters/mcp_bridge.py +10 -0
- raise_cli/adapters/mcp_confluence.py +246 -0
- raise_cli/adapters/mcp_jira.py +405 -0
- raise_cli/adapters/models.py +205 -0
- raise_cli/adapters/protocols.py +180 -0
- raise_cli/adapters/registry.py +90 -0
- raise_cli/adapters/sync.py +149 -0
- raise_cli/agents/__init__.py +14 -0
- raise_cli/agents/antigravity.yaml +8 -0
- raise_cli/agents/claude.yaml +8 -0
- raise_cli/agents/copilot.yaml +8 -0
- raise_cli/agents/copilot_plugin.py +124 -0
- raise_cli/agents/cursor.yaml +7 -0
- raise_cli/agents/roo.yaml +8 -0
- raise_cli/agents/windsurf.yaml +8 -0
- raise_cli/artifacts/__init__.py +30 -0
- raise_cli/artifacts/models.py +43 -0
- raise_cli/artifacts/reader.py +55 -0
- raise_cli/artifacts/renderer.py +104 -0
- raise_cli/artifacts/story_design.py +69 -0
- raise_cli/artifacts/writer.py +45 -0
- raise_cli/backlog/__init__.py +1 -0
- raise_cli/backlog/sync.py +115 -0
- raise_cli/cli/__init__.py +3 -0
- raise_cli/cli/commands/__init__.py +3 -0
- raise_cli/cli/commands/_resolve.py +153 -0
- raise_cli/cli/commands/adapters.py +362 -0
- raise_cli/cli/commands/artifact.py +137 -0
- raise_cli/cli/commands/backlog.py +333 -0
- raise_cli/cli/commands/base.py +31 -0
- raise_cli/cli/commands/discover.py +551 -0
- raise_cli/cli/commands/docs.py +130 -0
- raise_cli/cli/commands/doctor.py +177 -0
- raise_cli/cli/commands/gate.py +223 -0
- raise_cli/cli/commands/graph.py +1086 -0
- raise_cli/cli/commands/info.py +81 -0
- raise_cli/cli/commands/init.py +746 -0
- raise_cli/cli/commands/journal.py +167 -0
- raise_cli/cli/commands/mcp.py +524 -0
- raise_cli/cli/commands/memory.py +467 -0
- raise_cli/cli/commands/pattern.py +348 -0
- raise_cli/cli/commands/profile.py +59 -0
- raise_cli/cli/commands/publish.py +80 -0
- raise_cli/cli/commands/release.py +338 -0
- raise_cli/cli/commands/session.py +528 -0
- raise_cli/cli/commands/signal.py +410 -0
- raise_cli/cli/commands/skill.py +350 -0
- raise_cli/cli/commands/skill_set.py +145 -0
- raise_cli/cli/error_handler.py +158 -0
- raise_cli/cli/main.py +163 -0
- raise_cli/compat.py +66 -0
- raise_cli/config/__init__.py +41 -0
- raise_cli/config/agent_plugin.py +105 -0
- raise_cli/config/agent_registry.py +233 -0
- raise_cli/config/agents.py +120 -0
- raise_cli/config/ide.py +32 -0
- raise_cli/config/paths.py +379 -0
- raise_cli/config/settings.py +180 -0
- raise_cli/context/__init__.py +42 -0
- raise_cli/context/analyzers/__init__.py +16 -0
- raise_cli/context/analyzers/models.py +36 -0
- raise_cli/context/analyzers/protocol.py +43 -0
- raise_cli/context/analyzers/python.py +292 -0
- raise_cli/context/builder.py +1569 -0
- raise_cli/context/diff.py +213 -0
- raise_cli/context/extractors/__init__.py +13 -0
- raise_cli/context/extractors/skills.py +121 -0
- raise_cli/core/__init__.py +37 -0
- raise_cli/core/files.py +66 -0
- raise_cli/core/text.py +174 -0
- raise_cli/core/tools.py +441 -0
- raise_cli/discovery/__init__.py +50 -0
- raise_cli/discovery/analyzer.py +691 -0
- raise_cli/discovery/drift.py +355 -0
- raise_cli/discovery/scanner.py +1687 -0
- raise_cli/doctor/__init__.py +4 -0
- raise_cli/doctor/checks/__init__.py +1 -0
- raise_cli/doctor/checks/environment.py +110 -0
- raise_cli/doctor/checks/project.py +238 -0
- raise_cli/doctor/fix.py +80 -0
- raise_cli/doctor/models.py +56 -0
- raise_cli/doctor/protocol.py +43 -0
- raise_cli/doctor/registry.py +100 -0
- raise_cli/doctor/report.py +141 -0
- raise_cli/doctor/runner.py +95 -0
- raise_cli/engines/__init__.py +3 -0
- raise_cli/exceptions.py +215 -0
- raise_cli/gates/__init__.py +19 -0
- raise_cli/gates/builtin/__init__.py +1 -0
- raise_cli/gates/builtin/coverage.py +52 -0
- raise_cli/gates/builtin/lint.py +48 -0
- raise_cli/gates/builtin/tests.py +48 -0
- raise_cli/gates/builtin/types.py +48 -0
- raise_cli/gates/models.py +40 -0
- raise_cli/gates/protocol.py +41 -0
- raise_cli/gates/registry.py +141 -0
- raise_cli/governance/__init__.py +11 -0
- raise_cli/governance/extractor.py +412 -0
- raise_cli/governance/models.py +134 -0
- raise_cli/governance/parsers/__init__.py +35 -0
- raise_cli/governance/parsers/_convert.py +38 -0
- raise_cli/governance/parsers/adr.py +274 -0
- raise_cli/governance/parsers/backlog.py +356 -0
- raise_cli/governance/parsers/constitution.py +119 -0
- raise_cli/governance/parsers/epic.py +323 -0
- raise_cli/governance/parsers/glossary.py +316 -0
- raise_cli/governance/parsers/guardrails.py +345 -0
- raise_cli/governance/parsers/prd.py +112 -0
- raise_cli/governance/parsers/roadmap.py +118 -0
- raise_cli/governance/parsers/vision.py +116 -0
- raise_cli/graph/__init__.py +1 -0
- raise_cli/graph/backends/__init__.py +57 -0
- raise_cli/graph/backends/api.py +137 -0
- raise_cli/graph/backends/dual.py +139 -0
- raise_cli/graph/backends/pending.py +84 -0
- raise_cli/handlers/__init__.py +3 -0
- raise_cli/hooks/__init__.py +54 -0
- raise_cli/hooks/builtin/__init__.py +1 -0
- raise_cli/hooks/builtin/backlog.py +216 -0
- raise_cli/hooks/builtin/gate_bridge.py +83 -0
- raise_cli/hooks/builtin/jira_sync.py +127 -0
- raise_cli/hooks/builtin/memory.py +117 -0
- raise_cli/hooks/builtin/telemetry.py +72 -0
- raise_cli/hooks/emitter.py +184 -0
- raise_cli/hooks/events.py +262 -0
- raise_cli/hooks/protocol.py +38 -0
- raise_cli/hooks/registry.py +117 -0
- raise_cli/mcp/__init__.py +33 -0
- raise_cli/mcp/bridge.py +218 -0
- raise_cli/mcp/models.py +43 -0
- raise_cli/mcp/registry.py +77 -0
- raise_cli/mcp/schema.py +41 -0
- raise_cli/memory/__init__.py +58 -0
- raise_cli/memory/loader.py +247 -0
- raise_cli/memory/migration.py +241 -0
- raise_cli/memory/models.py +169 -0
- raise_cli/memory/writer.py +598 -0
- raise_cli/onboarding/__init__.py +103 -0
- raise_cli/onboarding/bootstrap.py +324 -0
- raise_cli/onboarding/claudemd.py +17 -0
- raise_cli/onboarding/conventions.py +742 -0
- raise_cli/onboarding/detection.py +374 -0
- raise_cli/onboarding/governance.py +443 -0
- raise_cli/onboarding/instructions.py +672 -0
- raise_cli/onboarding/manifest.py +201 -0
- raise_cli/onboarding/memory_md.py +399 -0
- raise_cli/onboarding/migration.py +207 -0
- raise_cli/onboarding/profile.py +624 -0
- raise_cli/onboarding/skill_conflict.py +100 -0
- raise_cli/onboarding/skill_manifest.py +176 -0
- raise_cli/onboarding/skills.py +437 -0
- raise_cli/onboarding/workflows.py +101 -0
- raise_cli/output/__init__.py +28 -0
- raise_cli/output/console.py +394 -0
- raise_cli/output/formatters/__init__.py +9 -0
- raise_cli/output/formatters/adapters.py +135 -0
- raise_cli/output/formatters/discover.py +439 -0
- raise_cli/output/formatters/skill.py +298 -0
- raise_cli/publish/__init__.py +3 -0
- raise_cli/publish/changelog.py +80 -0
- raise_cli/publish/check.py +179 -0
- raise_cli/publish/version.py +172 -0
- raise_cli/rai_base/__init__.py +22 -0
- raise_cli/rai_base/framework/__init__.py +7 -0
- raise_cli/rai_base/framework/methodology.yaml +233 -0
- raise_cli/rai_base/governance/__init__.py +1 -0
- raise_cli/rai_base/governance/architecture/__init__.py +1 -0
- raise_cli/rai_base/governance/architecture/domain-model.md +20 -0
- raise_cli/rai_base/governance/architecture/system-context.md +34 -0
- raise_cli/rai_base/governance/architecture/system-design.md +24 -0
- raise_cli/rai_base/governance/backlog.md +8 -0
- raise_cli/rai_base/governance/guardrails.md +17 -0
- raise_cli/rai_base/governance/prd.md +25 -0
- raise_cli/rai_base/governance/vision.md +16 -0
- raise_cli/rai_base/identity/__init__.py +8 -0
- raise_cli/rai_base/identity/core.md +119 -0
- raise_cli/rai_base/identity/perspective.md +119 -0
- raise_cli/rai_base/memory/__init__.py +7 -0
- raise_cli/rai_base/memory/patterns-base.jsonl +55 -0
- raise_cli/schemas/__init__.py +3 -0
- raise_cli/schemas/journal.py +49 -0
- raise_cli/schemas/session_state.py +117 -0
- raise_cli/session/__init__.py +5 -0
- raise_cli/session/bundle.py +820 -0
- raise_cli/session/close.py +268 -0
- raise_cli/session/journal.py +119 -0
- raise_cli/session/resolver.py +126 -0
- raise_cli/session/state.py +187 -0
- raise_cli/skills/__init__.py +44 -0
- raise_cli/skills/locator.py +141 -0
- raise_cli/skills/name_checker.py +199 -0
- raise_cli/skills/parser.py +145 -0
- raise_cli/skills/scaffold.py +212 -0
- raise_cli/skills/schema.py +132 -0
- raise_cli/skills/skillsets.py +195 -0
- raise_cli/skills/validator.py +197 -0
- raise_cli/skills_base/__init__.py +80 -0
- raise_cli/skills_base/contract-template.md +60 -0
- raise_cli/skills_base/preamble.md +37 -0
- raise_cli/skills_base/rai-architecture-review/SKILL.md +137 -0
- raise_cli/skills_base/rai-debug/SKILL.md +171 -0
- raise_cli/skills_base/rai-discover/SKILL.md +167 -0
- raise_cli/skills_base/rai-discover-document/SKILL.md +128 -0
- raise_cli/skills_base/rai-discover-scan/SKILL.md +147 -0
- raise_cli/skills_base/rai-discover-start/SKILL.md +145 -0
- raise_cli/skills_base/rai-discover-validate/SKILL.md +142 -0
- raise_cli/skills_base/rai-docs-update/SKILL.md +142 -0
- raise_cli/skills_base/rai-doctor/SKILL.md +120 -0
- raise_cli/skills_base/rai-epic-close/SKILL.md +165 -0
- raise_cli/skills_base/rai-epic-close/templates/retrospective.md +68 -0
- raise_cli/skills_base/rai-epic-design/SKILL.md +146 -0
- raise_cli/skills_base/rai-epic-design/templates/design.md +24 -0
- raise_cli/skills_base/rai-epic-design/templates/scope.md +76 -0
- raise_cli/skills_base/rai-epic-plan/SKILL.md +153 -0
- raise_cli/skills_base/rai-epic-plan/_references/sequencing-strategies.md +67 -0
- raise_cli/skills_base/rai-epic-plan/templates/plan-section.md +49 -0
- raise_cli/skills_base/rai-epic-run/SKILL.md +208 -0
- raise_cli/skills_base/rai-epic-start/SKILL.md +136 -0
- raise_cli/skills_base/rai-epic-start/templates/brief.md +34 -0
- raise_cli/skills_base/rai-mcp-add/SKILL.md +176 -0
- raise_cli/skills_base/rai-mcp-remove/SKILL.md +120 -0
- raise_cli/skills_base/rai-mcp-status/SKILL.md +147 -0
- raise_cli/skills_base/rai-problem-shape/SKILL.md +138 -0
- raise_cli/skills_base/rai-project-create/SKILL.md +144 -0
- raise_cli/skills_base/rai-project-onboard/SKILL.md +162 -0
- raise_cli/skills_base/rai-quality-review/SKILL.md +189 -0
- raise_cli/skills_base/rai-research/SKILL.md +143 -0
- raise_cli/skills_base/rai-research/references/research-prompt-template.md +317 -0
- raise_cli/skills_base/rai-session-close/SKILL.md +176 -0
- raise_cli/skills_base/rai-session-start/SKILL.md +110 -0
- raise_cli/skills_base/rai-story-close/SKILL.md +198 -0
- raise_cli/skills_base/rai-story-design/SKILL.md +203 -0
- raise_cli/skills_base/rai-story-design/references/tech-design-story-v2.md +293 -0
- raise_cli/skills_base/rai-story-implement/SKILL.md +115 -0
- raise_cli/skills_base/rai-story-plan/SKILL.md +135 -0
- raise_cli/skills_base/rai-story-review/SKILL.md +178 -0
- raise_cli/skills_base/rai-story-run/SKILL.md +282 -0
- raise_cli/skills_base/rai-story-start/SKILL.md +166 -0
- raise_cli/skills_base/rai-story-start/templates/story.md +38 -0
- raise_cli/skills_base/rai-welcome/SKILL.md +134 -0
- raise_cli/telemetry/__init__.py +42 -0
- raise_cli/telemetry/schemas.py +285 -0
- raise_cli/telemetry/writer.py +217 -0
- raise_cli/tier/__init__.py +0 -0
- raise_cli/tier/context.py +134 -0
- raise_cli/viz/__init__.py +7 -0
- raise_cli/viz/generator.py +406 -0
- raise_cli-2.2.1.dist-info/METADATA +433 -0
- raise_cli-2.2.1.dist-info/RECORD +264 -0
- raise_cli-2.2.1.dist-info/WHEEL +4 -0
- raise_cli-2.2.1.dist-info/entry_points.txt +40 -0
- raise_cli-2.2.1.dist-info/licenses/LICENSE +190 -0
- raise_cli-2.2.1.dist-info/licenses/NOTICE +4 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Pydantic models for adapter boundaries.
|
|
2
|
+
|
|
3
|
+
Shared data types consumed by adapter Protocols. These models define
|
|
4
|
+
the contracts at integration boundaries — what goes in and comes out
|
|
5
|
+
of adapters regardless of their concrete implementation.
|
|
6
|
+
|
|
7
|
+
Architecture: ADR-033 (Open-core adapter architecture), ADR-034 (Governance extensibility)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from enum import StrEnum
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, Field
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CoreArtifactType(StrEnum):
|
|
18
|
+
"""Core governance artifact types.
|
|
19
|
+
|
|
20
|
+
Protocols accept ``str`` — plugins are not restricted to this enum.
|
|
21
|
+
Use these constants for built-in artifact types.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
BACKLOG = "backlog"
|
|
25
|
+
ADR = "adr"
|
|
26
|
+
CONSTITUTION = "constitution"
|
|
27
|
+
PRD = "prd"
|
|
28
|
+
VISION = "vision"
|
|
29
|
+
GUARDRAILS = "guardrails"
|
|
30
|
+
GLOSSARY = "glossary"
|
|
31
|
+
ROADMAP = "roadmap"
|
|
32
|
+
EPIC_SCOPE = "epic_scope"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ArtifactLocator(BaseModel):
|
|
36
|
+
"""Points to a governance artifact for parsing."""
|
|
37
|
+
|
|
38
|
+
path: str = Field(..., description="Relative path from project root")
|
|
39
|
+
artifact_type: str = Field(
|
|
40
|
+
..., description="Artifact type (CoreArtifactType or custom str)"
|
|
41
|
+
)
|
|
42
|
+
metadata: dict[str, Any] = Field(
|
|
43
|
+
default_factory=dict, description="Type-specific context"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class IssueSpec(BaseModel):
|
|
48
|
+
"""Specification for creating a PM issue."""
|
|
49
|
+
|
|
50
|
+
summary: str = Field(..., description="Issue title")
|
|
51
|
+
description: str = Field(default="", description="Issue body (markdown)")
|
|
52
|
+
issue_type: str = Field(default="Task", description="Issue type name")
|
|
53
|
+
labels: list[str] = Field(default_factory=list)
|
|
54
|
+
metadata: dict[str, Any] = Field(
|
|
55
|
+
default_factory=dict, description="PM-specific fields"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class IssueRef(BaseModel):
|
|
60
|
+
"""Reference to an existing PM issue."""
|
|
61
|
+
|
|
62
|
+
key: str = Field(..., description="Issue key (e.g., 'PROJ-123')")
|
|
63
|
+
url: str = Field(default="", description="Web URL to the issue")
|
|
64
|
+
metadata: dict[str, Any] = Field(default_factory=dict)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class PublishResult(BaseModel):
|
|
68
|
+
"""Result of publishing documentation."""
|
|
69
|
+
|
|
70
|
+
success: bool = Field(..., description="Whether publish succeeded")
|
|
71
|
+
url: str = Field(default="", description="URL of published content")
|
|
72
|
+
message: str = Field(default="", description="Status or error message")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class IssueDetail(IssueRef):
|
|
76
|
+
"""Full issue details — extends IssueRef (inherits key, url, metadata).
|
|
77
|
+
|
|
78
|
+
Timestamps use ISO 8601 format (e.g. ``2026-02-27T10:30:00Z``).
|
|
79
|
+
Empty string means timestamp not available.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
summary: str = Field(..., description="Issue title")
|
|
83
|
+
description: str = Field(default="", description="Issue body (markdown)")
|
|
84
|
+
status: str = Field(..., description="Current status name")
|
|
85
|
+
issue_type: str = Field(..., description="Issue type (e.g., 'Story', 'Bug')")
|
|
86
|
+
parent_key: str | None = Field(default=None, description="Parent issue key")
|
|
87
|
+
labels: list[str] = Field(default_factory=list)
|
|
88
|
+
assignee: str | None = Field(default=None, description="Assignee identifier")
|
|
89
|
+
priority: str | None = Field(default=None, description="Priority name")
|
|
90
|
+
created: str = Field(default="", description="ISO 8601 creation timestamp")
|
|
91
|
+
updated: str = Field(default="", description="ISO 8601 last update timestamp")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class IssueSummary(BaseModel):
|
|
95
|
+
"""Compact issue for search results and listings."""
|
|
96
|
+
|
|
97
|
+
key: str = Field(..., description="Issue key (e.g., 'PROJ-123')")
|
|
98
|
+
summary: str = Field(..., description="Issue title")
|
|
99
|
+
status: str = Field(..., description="Current status name")
|
|
100
|
+
issue_type: str = Field(..., description="Issue type name")
|
|
101
|
+
parent_key: str | None = Field(default=None, description="Parent issue key")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class Comment(BaseModel):
|
|
105
|
+
"""Issue comment. Timestamps use ISO 8601 format."""
|
|
106
|
+
|
|
107
|
+
id: str = Field(..., description="Comment ID")
|
|
108
|
+
body: str = Field(..., description="Comment body (markdown)")
|
|
109
|
+
author: str = Field(..., description="Author identifier")
|
|
110
|
+
created: str = Field(..., description="ISO 8601 creation timestamp")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class CommentRef(BaseModel):
|
|
114
|
+
"""Reference to a created comment."""
|
|
115
|
+
|
|
116
|
+
id: str = Field(..., description="Comment ID")
|
|
117
|
+
url: str = Field(default="", description="Web URL to the comment")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class FailureDetail(BaseModel):
|
|
121
|
+
"""A single failure in a batch operation."""
|
|
122
|
+
|
|
123
|
+
key: str = Field(..., description="Issue key that failed")
|
|
124
|
+
error: str = Field(..., description="Error description")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class BatchResult(BaseModel):
|
|
128
|
+
"""Result of a batch operation."""
|
|
129
|
+
|
|
130
|
+
succeeded: list[IssueRef] = Field(default_factory=lambda: list[IssueRef]())
|
|
131
|
+
failed: list[FailureDetail] = Field(default_factory=lambda: list[FailureDetail]())
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class PageContent(BaseModel):
|
|
135
|
+
"""Full page content from documentation target."""
|
|
136
|
+
|
|
137
|
+
id: str = Field(..., description="Page ID")
|
|
138
|
+
title: str = Field(..., description="Page title")
|
|
139
|
+
content: str = Field(..., description="Page content (markdown)")
|
|
140
|
+
url: str = Field(default="", description="Web URL to the page")
|
|
141
|
+
space_key: str = Field(default="", description="Space key (e.g., 'DEV')")
|
|
142
|
+
version: int = Field(default=1, description="Page version number")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class PageSummary(BaseModel):
|
|
146
|
+
"""Compact page for search results. Timestamps use ISO 8601 format."""
|
|
147
|
+
|
|
148
|
+
id: str = Field(..., description="Page ID")
|
|
149
|
+
title: str = Field(..., description="Page title")
|
|
150
|
+
url: str = Field(default="", description="Web URL to the page")
|
|
151
|
+
space_key: str = Field(default="", description="Space key")
|
|
152
|
+
updated: str = Field(default="", description="ISO 8601 last update timestamp")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class AdapterHealth(BaseModel):
|
|
156
|
+
"""Health check result for an adapter."""
|
|
157
|
+
|
|
158
|
+
name: str = Field(..., description="Adapter name (e.g., 'jira')")
|
|
159
|
+
healthy: bool = Field(..., description="Whether the adapter is healthy")
|
|
160
|
+
message: str = Field(default="", description="Status or error message")
|
|
161
|
+
latency_ms: int | None = Field(
|
|
162
|
+
default=None, description="Response latency in milliseconds"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ---------------------------------------------------------------------------
|
|
167
|
+
# YAML store models (S347.2 — FileAdapter parity)
|
|
168
|
+
# ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class BacklogLink(BaseModel):
|
|
172
|
+
"""Link from one backlog item to another."""
|
|
173
|
+
|
|
174
|
+
target: str = Field(..., description="Target issue key")
|
|
175
|
+
link_type: str = Field(..., description="Relationship type (blocks, depends_on, relates_to)")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class BacklogComment(BaseModel):
|
|
179
|
+
"""Comment embedded in a backlog item YAML file."""
|
|
180
|
+
|
|
181
|
+
id: str = Field(..., description="Comment ID ({KEY}-{N})")
|
|
182
|
+
body: str = Field(..., description="Comment body text")
|
|
183
|
+
author: str = Field(..., description="Author identifier")
|
|
184
|
+
created: str = Field(..., description="ISO 8601 creation timestamp")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class BacklogItem(BaseModel):
|
|
188
|
+
"""Single backlog item stored as .raise/backlog/items/{KEY}.yaml."""
|
|
189
|
+
|
|
190
|
+
key: str = Field(..., description="Issue key (E1, S1.1, etc.)")
|
|
191
|
+
summary: str = Field(..., description="Issue title")
|
|
192
|
+
issue_type: str = Field(..., description="Epic, Story, Task")
|
|
193
|
+
status: str = Field(..., description="pending, in_progress, complete")
|
|
194
|
+
parent: str | None = Field(default=None, description="Parent issue key")
|
|
195
|
+
description: str = Field(default="", description="Issue description")
|
|
196
|
+
labels: list[str] = Field(default_factory=list)
|
|
197
|
+
priority: str | None = Field(default=None, description="Priority level")
|
|
198
|
+
assignee: str | None = Field(default=None, description="Assignee identifier")
|
|
199
|
+
comments: list[BacklogComment] = Field(default_factory=list) # pyright: ignore[reportUnknownVariableType]
|
|
200
|
+
links: list[BacklogLink] = Field(default_factory=list) # pyright: ignore[reportUnknownVariableType]
|
|
201
|
+
created: str = Field(default="", description="ISO 8601 creation timestamp")
|
|
202
|
+
updated: str = Field(default="", description="ISO 8601 last update timestamp")
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
# BackendHealth moved to raise_core.graph.backends.models (E275)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Protocol contracts for raise-cli adapters.
|
|
2
|
+
|
|
3
|
+
Defines the typed interfaces that adapter implementations must satisfy.
|
|
4
|
+
All Protocols are ``@runtime_checkable`` for isinstance() checks.
|
|
5
|
+
|
|
6
|
+
**Sync vs Async:**
|
|
7
|
+
- ``AsyncProjectManagementAdapter`` / ``AsyncDocumentationTarget`` are the primary
|
|
8
|
+
protocols. Concrete adapters (JiraAdapter, ConfluenceTarget) implement these.
|
|
9
|
+
- ``ProjectManagementAdapter`` / ``DocumentationTarget`` are the sync facades.
|
|
10
|
+
CLI commands consume these. Use ``SyncPMAdapter`` / ``SyncDocsAdapter`` wrappers
|
|
11
|
+
(from ``adapters.sync``) to bridge async adapters to sync consumption.
|
|
12
|
+
|
|
13
|
+
Architecture: ADR-033 (PM), ADR-034 (Governance)
|
|
14
|
+
Note: KnowledgeGraphBackend moved to raise_core.graph.backends.protocol (E275)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any, Protocol, runtime_checkable
|
|
20
|
+
|
|
21
|
+
from raise_cli.adapters.models import (
|
|
22
|
+
AdapterHealth,
|
|
23
|
+
ArtifactLocator,
|
|
24
|
+
BatchResult,
|
|
25
|
+
Comment,
|
|
26
|
+
CommentRef,
|
|
27
|
+
IssueDetail,
|
|
28
|
+
IssueRef,
|
|
29
|
+
IssueSpec,
|
|
30
|
+
IssueSummary,
|
|
31
|
+
PageContent,
|
|
32
|
+
PageSummary,
|
|
33
|
+
PublishResult,
|
|
34
|
+
)
|
|
35
|
+
from raise_core.graph.models import GraphNode
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
# Sync protocols (CLI consumption)
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@runtime_checkable
|
|
43
|
+
class ProjectManagementAdapter(Protocol):
|
|
44
|
+
"""Sync PM adapter contract. CLI commands consume this.
|
|
45
|
+
|
|
46
|
+
For concrete adapters, implement ``AsyncProjectManagementAdapter`` and wrap
|
|
47
|
+
with ``SyncPMAdapter`` for CLI consumption.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
# CRUD
|
|
51
|
+
def create_issue(self, project_key: str, issue: IssueSpec) -> IssueRef: ...
|
|
52
|
+
|
|
53
|
+
def get_issue(self, key: str) -> IssueDetail: ...
|
|
54
|
+
|
|
55
|
+
def update_issue(self, key: str, fields: dict[str, Any]) -> IssueRef: ...
|
|
56
|
+
|
|
57
|
+
def transition_issue(self, key: str, status: str) -> IssueRef: ...
|
|
58
|
+
|
|
59
|
+
# Batch
|
|
60
|
+
def batch_transition(self, keys: list[str], status: str) -> BatchResult: ...
|
|
61
|
+
|
|
62
|
+
# Relationships
|
|
63
|
+
def link_to_parent(self, child_key: str, parent_key: str) -> None: ...
|
|
64
|
+
|
|
65
|
+
def link_issues(self, source: str, target: str, link_type: str) -> None: ...
|
|
66
|
+
|
|
67
|
+
# Comments
|
|
68
|
+
def add_comment(self, key: str, body: str) -> CommentRef: ...
|
|
69
|
+
|
|
70
|
+
def get_comments(self, key: str, limit: int = 10) -> list[Comment]: ...
|
|
71
|
+
|
|
72
|
+
# Query — query is adapter-specific (JQL for Jira, etc.)
|
|
73
|
+
def search(self, query: str, limit: int = 50) -> list[IssueSummary]: ...
|
|
74
|
+
|
|
75
|
+
# Health
|
|
76
|
+
def health(self) -> AdapterHealth: ...
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@runtime_checkable
|
|
80
|
+
class GovernanceSchemaProvider(Protocol):
|
|
81
|
+
"""ADR-034: Declares what artifact types exist and where to find them.
|
|
82
|
+
|
|
83
|
+
Implementations: RaiSEDefaultSchema (built-in), OrgSchema (raise-pro).
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def list_artifact_types(self) -> list[str]: ...
|
|
87
|
+
|
|
88
|
+
def locate(self, artifact_type: str) -> list[ArtifactLocator]: ...
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@runtime_checkable
|
|
92
|
+
class GovernanceParser(Protocol):
|
|
93
|
+
"""ADR-034: Parses a governance artifact into graph nodes.
|
|
94
|
+
|
|
95
|
+
Implementations: BacklogParser, AdrParser, etc. (S211.3 wraps existing).
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def can_parse(self, locator: ArtifactLocator) -> bool: ...
|
|
99
|
+
|
|
100
|
+
def parse(self, locator: ArtifactLocator) -> list[GraphNode]: ...
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@runtime_checkable
|
|
104
|
+
class DocumentationTarget(Protocol):
|
|
105
|
+
"""Sync docs target contract. CLI commands consume this.
|
|
106
|
+
|
|
107
|
+
For concrete targets, implement ``AsyncDocumentationTarget`` and wrap
|
|
108
|
+
with ``SyncDocsAdapter`` for CLI consumption.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def can_publish(self, doc_type: str, metadata: dict[str, Any]) -> bool: ...
|
|
112
|
+
|
|
113
|
+
def publish(
|
|
114
|
+
self, doc_type: str, content: str, metadata: dict[str, Any]
|
|
115
|
+
) -> PublishResult: ...
|
|
116
|
+
|
|
117
|
+
def get_page(self, identifier: str) -> PageContent: ...
|
|
118
|
+
|
|
119
|
+
def search(self, query: str, limit: int = 10) -> list[PageSummary]: ...
|
|
120
|
+
|
|
121
|
+
def health(self) -> AdapterHealth: ...
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
# Async protocols (adapter implementation target)
|
|
126
|
+
# ---------------------------------------------------------------------------
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@runtime_checkable
|
|
130
|
+
class AsyncProjectManagementAdapter(Protocol):
|
|
131
|
+
"""Async PM adapter contract. Concrete adapters implement this.
|
|
132
|
+
|
|
133
|
+
Consumed directly by async contexts (rai-server) or via ``SyncPMAdapter``
|
|
134
|
+
wrapper for CLI.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
# CRUD
|
|
138
|
+
async def create_issue(self, project_key: str, issue: IssueSpec) -> IssueRef: ...
|
|
139
|
+
|
|
140
|
+
async def get_issue(self, key: str) -> IssueDetail: ...
|
|
141
|
+
|
|
142
|
+
async def update_issue(self, key: str, fields: dict[str, Any]) -> IssueRef: ...
|
|
143
|
+
|
|
144
|
+
async def transition_issue(self, key: str, status: str) -> IssueRef: ...
|
|
145
|
+
|
|
146
|
+
# Batch
|
|
147
|
+
async def batch_transition(self, keys: list[str], status: str) -> BatchResult: ...
|
|
148
|
+
|
|
149
|
+
# Relationships
|
|
150
|
+
async def link_to_parent(self, child_key: str, parent_key: str) -> None: ...
|
|
151
|
+
|
|
152
|
+
async def link_issues(self, source: str, target: str, link_type: str) -> None: ...
|
|
153
|
+
|
|
154
|
+
# Comments
|
|
155
|
+
async def add_comment(self, key: str, body: str) -> CommentRef: ...
|
|
156
|
+
|
|
157
|
+
async def get_comments(self, key: str, limit: int = 10) -> list[Comment]: ...
|
|
158
|
+
|
|
159
|
+
# Query — query is adapter-specific (JQL for Jira, etc.)
|
|
160
|
+
async def search(self, query: str, limit: int = 50) -> list[IssueSummary]: ...
|
|
161
|
+
|
|
162
|
+
# Health
|
|
163
|
+
async def health(self) -> AdapterHealth: ...
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@runtime_checkable
|
|
167
|
+
class AsyncDocumentationTarget(Protocol):
|
|
168
|
+
"""Async docs target contract. Concrete targets implement this."""
|
|
169
|
+
|
|
170
|
+
async def can_publish(self, doc_type: str, metadata: dict[str, Any]) -> bool: ...
|
|
171
|
+
|
|
172
|
+
async def publish(
|
|
173
|
+
self, doc_type: str, content: str, metadata: dict[str, Any]
|
|
174
|
+
) -> PublishResult: ...
|
|
175
|
+
|
|
176
|
+
async def get_page(self, identifier: str) -> PageContent: ...
|
|
177
|
+
|
|
178
|
+
async def search(self, query: str, limit: int = 10) -> list[PageSummary]: ...
|
|
179
|
+
|
|
180
|
+
async def health(self) -> AdapterHealth: ...
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Entry point registry for adapter discovery.
|
|
2
|
+
|
|
3
|
+
Discovers adapter implementations registered via Python entry points
|
|
4
|
+
(``[project.entry-points]`` in pyproject.toml). Each group maps to a
|
|
5
|
+
Protocol contract from ``raise_cli.adapters.protocols``.
|
|
6
|
+
|
|
7
|
+
Trust model: entry point loading inherits the ``pip install`` trust boundary.
|
|
8
|
+
If a package is installed in the environment, its entry points are trusted.
|
|
9
|
+
There is no allowlist or sandboxing — this is consistent with how pytest,
|
|
10
|
+
stevedore, and the broader Python ecosystem handle plugin discovery.
|
|
11
|
+
|
|
12
|
+
Architecture: ADR-033 (PM), ADR-034 (Governance), ADR-036 (Graph Backend)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import inspect
|
|
18
|
+
import logging
|
|
19
|
+
from importlib.metadata import entry_points
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
# Entry point group names — stable contract for external packages.
|
|
25
|
+
EP_PM_ADAPTERS: str = "rai.adapters.pm"
|
|
26
|
+
EP_GOVERNANCE_SCHEMAS: str = "rai.governance.schemas"
|
|
27
|
+
EP_GOVERNANCE_PARSERS: str = "rai.governance.parsers"
|
|
28
|
+
EP_DOC_TARGETS: str = "rai.docs.targets"
|
|
29
|
+
EP_GRAPH_BACKENDS: str = "rai.graph.backends"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _dist_name(ep: Any) -> str:
|
|
33
|
+
"""Best-effort extraction of the distribution name that provides an entry point."""
|
|
34
|
+
try:
|
|
35
|
+
return ep.dist.name # type: ignore[union-attr]
|
|
36
|
+
except AttributeError:
|
|
37
|
+
return "unknown"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _discover(group: str) -> dict[str, type]:
|
|
41
|
+
"""Load all entry points for a group. Skips broken or non-class ones with warning."""
|
|
42
|
+
result: dict[str, type] = {}
|
|
43
|
+
for ep in entry_points(group=group):
|
|
44
|
+
try:
|
|
45
|
+
loaded: Any = ep.load()
|
|
46
|
+
except Exception as exc: # noqa: BLE001
|
|
47
|
+
logger.warning(
|
|
48
|
+
"Skipping entry point '%s' from '%s' in group '%s': %s",
|
|
49
|
+
ep.name,
|
|
50
|
+
_dist_name(ep),
|
|
51
|
+
group,
|
|
52
|
+
exc,
|
|
53
|
+
)
|
|
54
|
+
continue
|
|
55
|
+
if not inspect.isclass(loaded):
|
|
56
|
+
logger.warning(
|
|
57
|
+
"Skipping entry point '%s' from '%s' in group '%s': expected a class, got %s",
|
|
58
|
+
ep.name,
|
|
59
|
+
_dist_name(ep),
|
|
60
|
+
group,
|
|
61
|
+
type(loaded).__name__,
|
|
62
|
+
)
|
|
63
|
+
continue
|
|
64
|
+
result[ep.name] = loaded
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_pm_adapters() -> dict[str, type]:
|
|
69
|
+
"""Discover ProjectManagementAdapter implementations."""
|
|
70
|
+
return _discover(EP_PM_ADAPTERS)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_governance_schemas() -> dict[str, type]:
|
|
74
|
+
"""Discover GovernanceSchemaProvider implementations."""
|
|
75
|
+
return _discover(EP_GOVERNANCE_SCHEMAS)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def get_governance_parsers() -> dict[str, type]:
|
|
79
|
+
"""Discover GovernanceParser implementations."""
|
|
80
|
+
return _discover(EP_GOVERNANCE_PARSERS)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_doc_targets() -> dict[str, type]:
|
|
84
|
+
"""Discover DocumentationTarget implementations."""
|
|
85
|
+
return _discover(EP_DOC_TARGETS)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_graph_backends() -> dict[str, type]:
|
|
89
|
+
"""Discover KnowledgeGraphBackend implementations."""
|
|
90
|
+
return _discover(EP_GRAPH_BACKENDS)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""Sync wrappers for async adapter protocols.
|
|
2
|
+
|
|
3
|
+
Bridges async adapters to sync consumption. Safe to call from both sync
|
|
4
|
+
contexts (CLI) and async contexts (hooks, server) — uses a thread-based
|
|
5
|
+
fallback when an event loop is already running.
|
|
6
|
+
|
|
7
|
+
Usage::
|
|
8
|
+
|
|
9
|
+
from raise_cli.adapters.sync import SyncPMAdapter
|
|
10
|
+
|
|
11
|
+
async_adapter = JiraAdapter(config)
|
|
12
|
+
sync_adapter = SyncPMAdapter(async_adapter)
|
|
13
|
+
issue = sync_adapter.get_issue("RAISE-301") # sync call
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import asyncio
|
|
19
|
+
import concurrent.futures
|
|
20
|
+
from collections.abc import Coroutine
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from raise_cli.adapters.models import (
|
|
24
|
+
AdapterHealth,
|
|
25
|
+
BatchResult,
|
|
26
|
+
Comment,
|
|
27
|
+
CommentRef,
|
|
28
|
+
IssueDetail,
|
|
29
|
+
IssueRef,
|
|
30
|
+
IssueSpec,
|
|
31
|
+
IssueSummary,
|
|
32
|
+
PageContent,
|
|
33
|
+
PageSummary,
|
|
34
|
+
PublishResult,
|
|
35
|
+
)
|
|
36
|
+
from raise_cli.adapters.protocols import (
|
|
37
|
+
AsyncDocumentationTarget,
|
|
38
|
+
AsyncProjectManagementAdapter,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _run_sync[T](coro: Coroutine[Any, Any, T], closeable: Any = None) -> T:
|
|
43
|
+
"""Run a coroutine synchronously, safe from both sync and async contexts.
|
|
44
|
+
|
|
45
|
+
- **No running loop:** uses ``asyncio.run()`` directly.
|
|
46
|
+
- **Loop already running:** runs ``asyncio.run()`` in a separate thread
|
|
47
|
+
so each thread gets its own event loop, avoiding the
|
|
48
|
+
``RuntimeError: asyncio.run() cannot be called from a running event loop``.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
coro: The coroutine to run.
|
|
52
|
+
closeable: Optional object with ``aclose()`` method. Called in a
|
|
53
|
+
``finally`` block within the same event loop to prevent
|
|
54
|
+
asyncgen finalizer tracebacks (RAISE-324).
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
async def _wrapped() -> T:
|
|
58
|
+
try:
|
|
59
|
+
return await coro
|
|
60
|
+
finally:
|
|
61
|
+
if closeable is not None:
|
|
62
|
+
aclose = getattr(closeable, "aclose", None)
|
|
63
|
+
if aclose:
|
|
64
|
+
await aclose()
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
asyncio.get_running_loop()
|
|
68
|
+
except RuntimeError:
|
|
69
|
+
# No loop running — safe to use asyncio.run()
|
|
70
|
+
return asyncio.run(_wrapped())
|
|
71
|
+
else:
|
|
72
|
+
# Loop already running — delegate to a thread with its own loop
|
|
73
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
|
|
74
|
+
future = pool.submit(asyncio.run, _wrapped())
|
|
75
|
+
return future.result()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class SyncPMAdapter:
|
|
79
|
+
"""Wraps ``AsyncProjectManagementAdapter`` for sync CLI consumption.
|
|
80
|
+
|
|
81
|
+
Satisfies ``ProjectManagementAdapter`` protocol via structural typing.
|
|
82
|
+
Each method delegates to the async adapter via ``_run_sync()``.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def __init__(self, async_adapter: AsyncProjectManagementAdapter) -> None:
|
|
86
|
+
self._adapter = async_adapter
|
|
87
|
+
|
|
88
|
+
def create_issue(self, project_key: str, issue: IssueSpec) -> IssueRef:
|
|
89
|
+
return _run_sync(self._adapter.create_issue(project_key, issue), self._adapter)
|
|
90
|
+
|
|
91
|
+
def get_issue(self, key: str) -> IssueDetail:
|
|
92
|
+
return _run_sync(self._adapter.get_issue(key), self._adapter)
|
|
93
|
+
|
|
94
|
+
def update_issue(self, key: str, fields: dict[str, Any]) -> IssueRef:
|
|
95
|
+
return _run_sync(self._adapter.update_issue(key, fields), self._adapter)
|
|
96
|
+
|
|
97
|
+
def transition_issue(self, key: str, status: str) -> IssueRef:
|
|
98
|
+
return _run_sync(self._adapter.transition_issue(key, status), self._adapter)
|
|
99
|
+
|
|
100
|
+
def batch_transition(self, keys: list[str], status: str) -> BatchResult:
|
|
101
|
+
return _run_sync(self._adapter.batch_transition(keys, status), self._adapter)
|
|
102
|
+
|
|
103
|
+
def link_to_parent(self, child_key: str, parent_key: str) -> None:
|
|
104
|
+
_run_sync(self._adapter.link_to_parent(child_key, parent_key), self._adapter)
|
|
105
|
+
|
|
106
|
+
def link_issues(self, source: str, target: str, link_type: str) -> None:
|
|
107
|
+
_run_sync(self._adapter.link_issues(source, target, link_type), self._adapter)
|
|
108
|
+
|
|
109
|
+
def add_comment(self, key: str, body: str) -> CommentRef:
|
|
110
|
+
return _run_sync(self._adapter.add_comment(key, body), self._adapter)
|
|
111
|
+
|
|
112
|
+
def get_comments(self, key: str, limit: int = 10) -> list[Comment]:
|
|
113
|
+
return _run_sync(self._adapter.get_comments(key, limit), self._adapter)
|
|
114
|
+
|
|
115
|
+
def search(self, query: str, limit: int = 50) -> list[IssueSummary]:
|
|
116
|
+
return _run_sync(self._adapter.search(query, limit), self._adapter)
|
|
117
|
+
|
|
118
|
+
def health(self) -> AdapterHealth:
|
|
119
|
+
return _run_sync(self._adapter.health(), self._adapter)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class SyncDocsAdapter:
|
|
123
|
+
"""Wraps ``AsyncDocumentationTarget`` for sync CLI consumption.
|
|
124
|
+
|
|
125
|
+
Satisfies ``DocumentationTarget`` protocol via structural typing.
|
|
126
|
+
Each method delegates to the async target via ``_run_sync()``.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
def __init__(self, async_target: AsyncDocumentationTarget) -> None:
|
|
130
|
+
self._target = async_target
|
|
131
|
+
|
|
132
|
+
def can_publish(self, doc_type: str, metadata: dict[str, Any]) -> bool:
|
|
133
|
+
return _run_sync(self._target.can_publish(doc_type, metadata), self._target)
|
|
134
|
+
|
|
135
|
+
def publish(
|
|
136
|
+
self, doc_type: str, content: str, metadata: dict[str, Any]
|
|
137
|
+
) -> PublishResult:
|
|
138
|
+
return _run_sync(
|
|
139
|
+
self._target.publish(doc_type, content, metadata), self._target
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def get_page(self, identifier: str) -> PageContent:
|
|
143
|
+
return _run_sync(self._target.get_page(identifier), self._target)
|
|
144
|
+
|
|
145
|
+
def search(self, query: str, limit: int = 10) -> list[PageSummary]:
|
|
146
|
+
return _run_sync(self._target.search(query, limit), self._target)
|
|
147
|
+
|
|
148
|
+
def health(self) -> AdapterHealth:
|
|
149
|
+
return _run_sync(self._target.health(), self._target)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Built-in agent configuration package.
|
|
2
|
+
|
|
3
|
+
Contains YAML config files for the 5 Tier-1 built-in agents:
|
|
4
|
+
- claude.yaml (Claude Code)
|
|
5
|
+
- cursor.yaml (Cursor 2.4+)
|
|
6
|
+
- windsurf.yaml (Windsurf)
|
|
7
|
+
- copilot.yaml (GitHub Copilot — has CopilotPlugin)
|
|
8
|
+
- antigravity.yaml (Antigravity)
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
from importlib.resources import files
|
|
12
|
+
agents_pkg = files("raise_cli.agents")
|
|
13
|
+
claude_yaml = (agents_pkg / "claude.yaml").read_text(encoding="utf-8")
|
|
14
|
+
"""
|