codexspec 0.7.16__tar.gz → 0.7.17__tar.gz
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.
- {codexspec-0.7.16 → codexspec-0.7.17}/PKG-INFO +1 -1
- {codexspec-0.7.16 → codexspec-0.7.17}/pyproject.toml +1 -1
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/__init__.py +120 -1
- codexspec-0.7.17/src/codexspec/distill_review/__init__.py +13 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/app.js +938 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/ar.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/de.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/en.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/es.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/fr.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/hi.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/it.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/ja.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/ko.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/pt.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/ru.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/zh-CN.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/i18n/zh-TW.json +112 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/index.html +43 -0
- codexspec-0.7.17/src/codexspec/distill_review/assets/styles.css +824 -0
- codexspec-0.7.17/src/codexspec/distill_review/domain.py +585 -0
- codexspec-0.7.17/src/codexspec/distill_review/lease.py +101 -0
- codexspec-0.7.17/src/codexspec/distill_review/models.py +133 -0
- codexspec-0.7.17/src/codexspec/distill_review/records.py +399 -0
- codexspec-0.7.17/src/codexspec/distill_review/server.py +386 -0
- codexspec-0.7.17/src/codexspec/distill_review/session.py +323 -0
- codexspec-0.7.17/src/codexspec/distill_review/terminal.py +259 -0
- codexspec-0.7.17/src/codexspec/distill_review/transaction.py +932 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/distill.md +48 -4
- {codexspec-0.7.16 → codexspec-0.7.17}/.gitignore +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/LICENSE +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/README.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/codexspec-icon.svg +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/codexspec-logo-dark.svg +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/codexspec-logo-light.svg +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/check-i18n-completeness.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/check-i18n-structure.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/check-prerequisites.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/common.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/create-new-feature.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/bash/review-context.sh +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/powershell/common.ps1 +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/powershell/create-new-feature.ps1 +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/scripts/powershell/review-context.ps1 +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/automation.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/blueprint.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/commands/__init__.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/commands/installer.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/i18n.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/idea.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/integrations/__init__.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/integrations/base.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/integrations/claude.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/integrations/codex.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/profile.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/src/codexspec/translator.py +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/analyze.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/auto-dev.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/blueprint.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/checklist.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/clarify.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/commit-staged.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/config.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/constitution.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/debug.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/evolve.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/generate-spec.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/implement-tasks.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/onboard.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/plan-to-tasks.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/pr.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/quick.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/release-notes.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/reverse-spec.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/review-code.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/review-design.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/review-plan.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/review-spec.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/review-tasks.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/spec-to-design.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/spec-to-plan.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/specify.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/commands/tasks-to-issues.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/checklist-template.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/constitution-template.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/design-template.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/plan-template-detailed.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/plan-template-simple.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/requirements-template.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/spec-template-detailed.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/spec-template-simple.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/tasks-template-detailed.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/docs/tasks-template-simple.md +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/de.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/en.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/es.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/fr.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/ja.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/ko.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/pt-BR.json +0 -0
- {codexspec-0.7.16 → codexspec-0.7.17}/templates/translations/zh-CN.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: codexspec
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.17
|
|
4
4
|
Summary: CodexSpec - A Requirements-First SDD toolkit for Claude Code
|
|
5
5
|
Project-URL: Homepage, https://github.com/Zts0hg/codexspec
|
|
6
6
|
Project-URL: Repository, https://github.com/Zts0hg/codexspec
|
|
@@ -8,8 +8,10 @@ executable specifications that guide AI-assisted implementation.
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
import re
|
|
11
|
+
import secrets
|
|
11
12
|
import subprocess
|
|
12
13
|
import sys
|
|
14
|
+
import webbrowser
|
|
13
15
|
from datetime import datetime
|
|
14
16
|
from pathlib import Path
|
|
15
17
|
from typing import Optional
|
|
@@ -43,6 +45,12 @@ from .commands.installer import (
|
|
|
43
45
|
should_update_commands,
|
|
44
46
|
update_installed_command_frontmatter,
|
|
45
47
|
)
|
|
48
|
+
from .distill_review.domain import ReviewError, ReviewService
|
|
49
|
+
from .distill_review.lease import ActiveSessionError, ReviewLease
|
|
50
|
+
from .distill_review.server import create_server
|
|
51
|
+
from .distill_review.session import SessionError, SessionStore, ensure_runtime_ignored
|
|
52
|
+
from .distill_review.terminal import localized_error, localized_result, run_text_review, safe_terminal
|
|
53
|
+
from .distill_review.transaction import ProfileTransaction, TransactionError
|
|
46
54
|
from .i18n import (
|
|
47
55
|
generate_config_content,
|
|
48
56
|
get_explicit_language_key,
|
|
@@ -58,7 +66,7 @@ from .profile import ensure_profile_scaffold, inject_profile_block
|
|
|
58
66
|
from .translator import SUPPORTED_LANGUAGES, translate
|
|
59
67
|
|
|
60
68
|
# Version info
|
|
61
|
-
__version__ = "0.7.
|
|
69
|
+
__version__ = "0.7.17"
|
|
62
70
|
__author__ = "CodexSpec Team"
|
|
63
71
|
|
|
64
72
|
# Constitution file path constants
|
|
@@ -74,6 +82,97 @@ app = typer.Typer(
|
|
|
74
82
|
console = Console()
|
|
75
83
|
|
|
76
84
|
|
|
85
|
+
@app.command("_distill-review-helper", hidden=True)
|
|
86
|
+
def distill_review_helper(
|
|
87
|
+
project_root: Path = typer.Option(Path("."), "--project-root"),
|
|
88
|
+
mode: str = typer.Option("html", "--mode"),
|
|
89
|
+
manifest: Optional[Path] = typer.Option(None, "--manifest"),
|
|
90
|
+
no_open: bool = typer.Option(False, "--no-open"),
|
|
91
|
+
discard_draft: bool = typer.Option(False, "--discard-draft"),
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Run the deterministic local carrier used by the distill command."""
|
|
94
|
+
root = project_root.resolve()
|
|
95
|
+
language = get_interaction_language(root / ".codexspec" / "config.yml")
|
|
96
|
+
if mode not in {"html", "text"}:
|
|
97
|
+
_review_result(language, {"status": "invalid_input", "error": "invalid_mode"})
|
|
98
|
+
raise typer.Exit(2)
|
|
99
|
+
if not root.is_dir() or not (root / ".codexspec" / "profile").is_dir():
|
|
100
|
+
_review_result(language, {"status": "invalid_input", "error": "invalid_project_root"})
|
|
101
|
+
raise typer.Exit(2)
|
|
102
|
+
store = SessionStore(root)
|
|
103
|
+
lease = ReviewLease(root)
|
|
104
|
+
try:
|
|
105
|
+
lease.acquire({"state": "starting", "mode": mode})
|
|
106
|
+
except ActiveSessionError as exc:
|
|
107
|
+
# Machine output reports the running session, but its capability token and
|
|
108
|
+
# token-bearing URL belong to the session that printed them.
|
|
109
|
+
session = {key: value for key, value in exc.metadata.items() if key not in {"capability", "url"}}
|
|
110
|
+
_review_result(language, {"status": "active_session", "session": session})
|
|
111
|
+
return
|
|
112
|
+
except (AutomationError, SessionError, OSError) as exc:
|
|
113
|
+
_review_result(language, {"status": "invalid_input", "error": str(exc)})
|
|
114
|
+
raise typer.Exit(2) from exc
|
|
115
|
+
server = None
|
|
116
|
+
try:
|
|
117
|
+
try:
|
|
118
|
+
ProfileTransaction.recover(root, store)
|
|
119
|
+
except (TransactionError, SessionError, OSError):
|
|
120
|
+
if not discard_draft:
|
|
121
|
+
raise
|
|
122
|
+
# A failed recovery must not brick the documented escape hatch: an
|
|
123
|
+
# explicit discard abandons the draft and the stuck journal together.
|
|
124
|
+
if discard_draft:
|
|
125
|
+
store.discard()
|
|
126
|
+
store.discard_transaction()
|
|
127
|
+
_review_result(language, {"status": "discarded"})
|
|
128
|
+
return
|
|
129
|
+
draft = store.load()
|
|
130
|
+
service = ReviewService.from_project(
|
|
131
|
+
root,
|
|
132
|
+
manifest_path=manifest,
|
|
133
|
+
draft=draft,
|
|
134
|
+
interaction_language=language,
|
|
135
|
+
)
|
|
136
|
+
except (ReviewError, SessionError, TransactionError, OSError) as exc:
|
|
137
|
+
_review_result(language, {"status": "invalid_input", "error": str(exc)})
|
|
138
|
+
raise typer.Exit(2) from exc
|
|
139
|
+
if not service.records and not service.clusters and not (service.draft.decisions or service.draft.deferred):
|
|
140
|
+
_review_result(language, {"status": "nothing_to_review"})
|
|
141
|
+
return
|
|
142
|
+
try:
|
|
143
|
+
if mode == "text":
|
|
144
|
+
lease.update({"mode": "text"})
|
|
145
|
+
result = run_text_review(service, store)
|
|
146
|
+
typer.echo()
|
|
147
|
+
_machine_json(result)
|
|
148
|
+
return
|
|
149
|
+
token = secrets.token_urlsafe(32)
|
|
150
|
+
server = create_server(service, store, token=token)
|
|
151
|
+
url = f"http://127.0.0.1:{server.server_port}/#token={token}"
|
|
152
|
+
lease.update({"mode": "html", "port": server.server_port, "capability": token, "url": url})
|
|
153
|
+
try:
|
|
154
|
+
opened = False if no_open else webbrowser.open(url)
|
|
155
|
+
except (OSError, webbrowser.Error):
|
|
156
|
+
opened = False
|
|
157
|
+
if not opened:
|
|
158
|
+
typer.echo(url)
|
|
159
|
+
server.timeout = 0.5
|
|
160
|
+
while not server.stop_event.is_set():
|
|
161
|
+
server.handle_request()
|
|
162
|
+
_review_result(language, server.final_result or {"status": "finished"})
|
|
163
|
+
except (ReviewError, SessionError, TransactionError, OSError) as exc:
|
|
164
|
+
failure: dict[str, object] = {"status": "invalid_input", "error": str(exc)}
|
|
165
|
+
if isinstance(exc, TransactionError):
|
|
166
|
+
failure["records"] = exc.records
|
|
167
|
+
failure["failures"] = exc.failures
|
|
168
|
+
_review_result(language, failure)
|
|
169
|
+
raise typer.Exit(2) from exc
|
|
170
|
+
finally:
|
|
171
|
+
if server is not None:
|
|
172
|
+
server.server_close()
|
|
173
|
+
lease.release()
|
|
174
|
+
|
|
175
|
+
|
|
77
176
|
def get_version() -> str:
|
|
78
177
|
"""Return the current version of codexspec."""
|
|
79
178
|
return __version__
|
|
@@ -192,6 +291,25 @@ def _machine_json(value: object) -> None:
|
|
|
192
291
|
sys.stdout.write(json.dumps(value, sort_keys=True, separators=(",", ":")) + "\n")
|
|
193
292
|
|
|
194
293
|
|
|
294
|
+
def _review_result(language: str, value: dict[str, object]) -> None:
|
|
295
|
+
status = str(value.get("status", "invalid_input"))
|
|
296
|
+
if status in {"invalid_input", "conflict"}:
|
|
297
|
+
raw_records = value.get("records")
|
|
298
|
+
raw_failures = value.get("failures")
|
|
299
|
+
records = [str(item) for item in raw_records] if isinstance(raw_records, list) else None
|
|
300
|
+
failures = [str(item) for item in raw_failures] if isinstance(raw_failures, list) else None
|
|
301
|
+
message = localized_error(
|
|
302
|
+
language,
|
|
303
|
+
str(value.get("error", status)),
|
|
304
|
+
records=records,
|
|
305
|
+
failures=failures,
|
|
306
|
+
)
|
|
307
|
+
else:
|
|
308
|
+
message = localized_result(language, status)
|
|
309
|
+
typer.echo(safe_terminal(message))
|
|
310
|
+
_machine_json(value)
|
|
311
|
+
|
|
312
|
+
|
|
195
313
|
def _stdin_json() -> dict:
|
|
196
314
|
try:
|
|
197
315
|
value = json.loads(sys.stdin.read() or "{}")
|
|
@@ -885,6 +1003,7 @@ def init(
|
|
|
885
1003
|
# so knowledge distilled later is effective immediately with no re-init and
|
|
886
1004
|
# no dangling reference. Non-destructive: existing profile files are kept.
|
|
887
1005
|
ensure_profile_scaffold(target_dir)
|
|
1006
|
+
ensure_runtime_ignored(target_dir, install_managed_file=True)
|
|
888
1007
|
|
|
889
1008
|
# Copy helper scripts based on platform
|
|
890
1009
|
scripts_source_dir = get_scripts_dir()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Deterministic local review runtime for distilled profile knowledge."""
|
|
2
|
+
|
|
3
|
+
from .domain import ReviewError, ReviewService
|
|
4
|
+
from .records import RecordDocument, RecordError, discover_records, parse_record
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"RecordDocument",
|
|
8
|
+
"RecordError",
|
|
9
|
+
"ReviewError",
|
|
10
|
+
"ReviewService",
|
|
11
|
+
"discover_records",
|
|
12
|
+
"parse_record",
|
|
13
|
+
]
|