ideapress 0.1.0__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.
- ideapress-0.1.0/.editorconfig +23 -0
- ideapress-0.1.0/.github/workflows/ci.yml +159 -0
- ideapress-0.1.0/.github/workflows/release.yml +30 -0
- ideapress-0.1.0/.gitignore +106 -0
- ideapress-0.1.0/.importlinter +40 -0
- ideapress-0.1.0/.pre-commit-config.yaml +22 -0
- ideapress-0.1.0/CHANGELOG.md +104 -0
- ideapress-0.1.0/CONTRIBUTING.md +50 -0
- ideapress-0.1.0/LICENSE +201 -0
- ideapress-0.1.0/PKG-INFO +103 -0
- ideapress-0.1.0/README.md +52 -0
- ideapress-0.1.0/SECURITY.md +39 -0
- ideapress-0.1.0/docs/README.md +9 -0
- ideapress-0.1.0/docs/apps/ideapress/api.md +102 -0
- ideapress-0.1.0/docs/apps/ideapress/data-model.md +212 -0
- ideapress-0.1.0/docs/apps/ideapress/development-plan.md +433 -0
- ideapress-0.1.0/docs/apps/ideapress/risks.md +108 -0
- ideapress-0.1.0/docs/apps/ideapress/spec.md +322 -0
- ideapress-0.1.0/docs/apps/ideapress/workflows.md +310 -0
- ideapress-0.1.0/pyproject.toml +146 -0
- ideapress-0.1.0/requirements/.gitkeep +1 -0
- ideapress-0.1.0/src/ideapress/__about__.py +1 -0
- ideapress-0.1.0/src/ideapress/__main__.py +8 -0
- ideapress-0.1.0/src/ideapress/bootstrap.py +58 -0
- ideapress-0.1.0/src/ideapress/cli/commands/backend.py +129 -0
- ideapress-0.1.0/src/ideapress/cli/commands/config.py +113 -0
- ideapress-0.1.0/src/ideapress/cli/commands/db.py +129 -0
- ideapress-0.1.0/src/ideapress/cli/commands/export.py +49 -0
- ideapress-0.1.0/src/ideapress/cli/commands/plan.py +106 -0
- ideapress-0.1.0/src/ideapress/cli/commands/project.py +164 -0
- ideapress-0.1.0/src/ideapress/cli/commands/prompts.py +92 -0
- ideapress-0.1.0/src/ideapress/cli/commands/stage.py +112 -0
- ideapress-0.1.0/src/ideapress/cli/commands/system.py +134 -0
- ideapress-0.1.0/src/ideapress/cli/commands/unit.py +162 -0
- ideapress-0.1.0/src/ideapress/cli/commands/workflow.py +69 -0
- ideapress-0.1.0/src/ideapress/cli/main.py +75 -0
- ideapress-0.1.0/src/ideapress/config.py +725 -0
- ideapress-0.1.0/src/ideapress/content_types/article/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/content_types/registry.py +137 -0
- ideapress-0.1.0/src/ideapress/content_types/report/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/domain/audit.py +138 -0
- ideapress-0.1.0/src/ideapress/domain/commit.py +233 -0
- ideapress-0.1.0/src/ideapress/domain/context_assembly.py +348 -0
- ideapress-0.1.0/src/ideapress/domain/critique.py +62 -0
- ideapress-0.1.0/src/ideapress/domain/exporters/html.py +165 -0
- ideapress-0.1.0/src/ideapress/domain/exporters/json.py +99 -0
- ideapress-0.1.0/src/ideapress/domain/exporters/markdown.py +92 -0
- ideapress-0.1.0/src/ideapress/domain/exporters/model.py +143 -0
- ideapress-0.1.0/src/ideapress/domain/inference.py +355 -0
- ideapress-0.1.0/src/ideapress/domain/plan.py +150 -0
- ideapress-0.1.0/src/ideapress/domain/project.py +132 -0
- ideapress-0.1.0/src/ideapress/domain/requirements.py +444 -0
- ideapress-0.1.0/src/ideapress/domain/revision_policy.py +149 -0
- ideapress-0.1.0/src/ideapress/domain/stage_state.py +110 -0
- ideapress-0.1.0/src/ideapress/domain/stages.py +189 -0
- ideapress-0.1.0/src/ideapress/domain/validation.py +158 -0
- ideapress-0.1.0/src/ideapress/domain/validators/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/domain/validators/__init__.py +45 -0
- ideapress-0.1.0/src/ideapress/domain/validators/consistency.py +67 -0
- ideapress-0.1.0/src/ideapress/domain/validators/content.py +114 -0
- ideapress-0.1.0/src/ideapress/domain/validators/formatting.py +80 -0
- ideapress-0.1.0/src/ideapress/domain/validators/length.py +62 -0
- ideapress-0.1.0/src/ideapress/domain/validators/reference.py +124 -0
- ideapress-0.1.0/src/ideapress/domain/validators/safety.py +99 -0
- ideapress-0.1.0/src/ideapress/domain/validators/structural.py +156 -0
- ideapress-0.1.0/src/ideapress/errors.py +179 -0
- ideapress-0.1.0/src/ideapress/infrastructure/backends/_modelrack.py +402 -0
- ideapress-0.1.0/src/ideapress/infrastructure/backends/fake.py +248 -0
- ideapress-0.1.0/src/ideapress/infrastructure/backends/loadcoach.py +4 -0
- ideapress-0.1.0/src/ideapress/infrastructure/backends/ollama.py +207 -0
- ideapress-0.1.0/src/ideapress/infrastructure/backends/openai_compatible.py +175 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/env.py +34 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/script.py.mako +26 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/versions/0001_initial_schema.py +99 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/versions/0002_plan_tables.py +227 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/versions/0003_unit_versions.py +152 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/versions/0004_review_tables.py +87 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/migrations/versions/0005_stage_run_ownership.py +40 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/models.py +495 -0
- ideapress-0.1.0/src/ideapress/infrastructure/db/repositories/projects.py +162 -0
- ideapress-0.1.0/src/ideapress/observability/logging.py +157 -0
- ideapress-0.1.0/src/ideapress/prompts/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/prompts/manifest.json +59 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/audit_deep.review.v1.json +38 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/audit_fast.review.v1.json +33 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/critique.judge.v1.json +48 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/draft.write.v1.json +28 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/hello.v1.json +28 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/outline.plan.v1.json +43 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/project_review.consistency.v1.json +28 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/repair.fix.v1.json +38 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/requirements.compile.v1.json +34 -0
- ideapress-0.1.0/src/ideapress/prompts/stages/revise.improve.v1.json +38 -0
- ideapress-0.1.0/src/ideapress/services/backends.py +181 -0
- ideapress-0.1.0/src/ideapress/services/database.py +250 -0
- ideapress-0.1.0/src/ideapress/services/diagnostics.py +121 -0
- ideapress-0.1.0/src/ideapress/services/events.py +197 -0
- ideapress-0.1.0/src/ideapress/services/export.py +262 -0
- ideapress-0.1.0/src/ideapress/services/feedback.py +4 -0
- ideapress-0.1.0/src/ideapress/services/inference.py +310 -0
- ideapress-0.1.0/src/ideapress/services/plan.py +346 -0
- ideapress-0.1.0/src/ideapress/services/project_archive.py +4 -0
- ideapress-0.1.0/src/ideapress/services/project_review.py +143 -0
- ideapress-0.1.0/src/ideapress/services/projects.py +332 -0
- ideapress-0.1.0/src/ideapress/services/prompts.py +91 -0
- ideapress-0.1.0/src/ideapress/services/requirements.py +323 -0
- ideapress-0.1.0/src/ideapress/services/review.py +375 -0
- ideapress-0.1.0/src/ideapress/services/review_loop.py +410 -0
- ideapress-0.1.0/src/ideapress/services/runtime.py +224 -0
- ideapress-0.1.0/src/ideapress/services/stage_bodies.py +193 -0
- ideapress-0.1.0/src/ideapress/services/stage_registry.py +63 -0
- ideapress-0.1.0/src/ideapress/services/stage_reports.py +137 -0
- ideapress-0.1.0/src/ideapress/services/stages.py +457 -0
- ideapress-0.1.0/src/ideapress/services/unit_loop.py +426 -0
- ideapress-0.1.0/src/ideapress/services/unit_reports.py +192 -0
- ideapress-0.1.0/src/ideapress/services/units.py +297 -0
- ideapress-0.1.0/src/ideapress/web/app.py +290 -0
- ideapress-0.1.0/src/ideapress/web/csrf.py +50 -0
- ideapress-0.1.0/src/ideapress/web/limits.py +89 -0
- ideapress-0.1.0/src/ideapress/web/rendering.py +69 -0
- ideapress-0.1.0/src/ideapress/web/routes/backends.py +57 -0
- ideapress-0.1.0/src/ideapress/web/routes/export.py +59 -0
- ideapress-0.1.0/src/ideapress/web/routes/plan.py +32 -0
- ideapress-0.1.0/src/ideapress/web/routes/projects.py +199 -0
- ideapress-0.1.0/src/ideapress/web/routes/settings.py +151 -0
- ideapress-0.1.0/src/ideapress/web/routes/stages.py +178 -0
- ideapress-0.1.0/src/ideapress/web/routes/system.py +106 -0
- ideapress-0.1.0/src/ideapress/web/routes/units.py +122 -0
- ideapress-0.1.0/src/ideapress/web/routes/workspace.py +4 -0
- ideapress-0.1.0/src/ideapress/web/static/js/diff.js +1 -0
- ideapress-0.1.0/src/ideapress/web/static/js/workspace.js +1 -0
- ideapress-0.1.0/src/ideapress/web/templates/.gitkeep +0 -0
- ideapress-0.1.0/src/ideapress/web/templates/backends/index.html +38 -0
- ideapress-0.1.0/src/ideapress/web/templates/base.html +6 -0
- ideapress-0.1.0/src/ideapress/web/templates/error.html +14 -0
- ideapress-0.1.0/src/ideapress/web/templates/plan/index.html +63 -0
- ideapress-0.1.0/src/ideapress/web/templates/projects/detail.html +23 -0
- ideapress-0.1.0/src/ideapress/web/templates/projects/index.html +42 -0
- ideapress-0.1.0/src/ideapress/web/templates/system/index.html +20 -0
- ideapress-0.1.0/src/ideapress/web/templates/units/detail.html +127 -0
- ideapress-0.1.0/tests/accessibility/test_ui_checklist.py +4 -0
- ideapress-0.1.0/tests/conftest.py +59 -0
- ideapress-0.1.0/tests/contract/test_backend_conformance.py +247 -0
- ideapress-0.1.0/tests/contract/test_envelope_conformance.py +276 -0
- ideapress-0.1.0/tests/contract/test_loadcoach_backend.py +4 -0
- ideapress-0.1.0/tests/e2e/test_backends_surface.py +151 -0
- ideapress-0.1.0/tests/e2e/test_cli_skeleton.py +125 -0
- ideapress-0.1.0/tests/e2e/test_export_dialog.py +4 -0
- ideapress-0.1.0/tests/e2e/test_full_project_journey.py +4 -0
- ideapress-0.1.0/tests/e2e/test_plan_cli.py +256 -0
- ideapress-0.1.0/tests/e2e/test_plan_editing.py +4 -0
- ideapress-0.1.0/tests/e2e/test_project_crud.py +197 -0
- ideapress-0.1.0/tests/e2e/test_stage_stream.py +334 -0
- ideapress-0.1.0/tests/e2e/test_system.py +159 -0
- ideapress-0.1.0/tests/e2e/test_workspace.py +4 -0
- ideapress-0.1.0/tests/integration/test_atomic_commit.py +299 -0
- ideapress-0.1.0/tests/integration/test_backend_parity.py +277 -0
- ideapress-0.1.0/tests/integration/test_draft_to_commit.py +335 -0
- ideapress-0.1.0/tests/integration/test_export.py +352 -0
- ideapress-0.1.0/tests/integration/test_loadcoach_degradation.py +4 -0
- ideapress-0.1.0/tests/integration/test_migrations.py +105 -0
- ideapress-0.1.0/tests/integration/test_plan_stage.py +521 -0
- ideapress-0.1.0/tests/integration/test_project_service.py +159 -0
- ideapress-0.1.0/tests/integration/test_review_loop.py +374 -0
- ideapress-0.1.0/tests/live/test_backend_live.py +161 -0
- ideapress-0.1.0/tests/live/test_core_loop_live.py +109 -0
- ideapress-0.1.0/tests/live/test_loadcoach_live.py +4 -0
- ideapress-0.1.0/tests/performance/.gitkeep +0 -0
- ideapress-0.1.0/tests/security/.gitkeep +0 -0
- ideapress-0.1.0/tests/unit/test_ci_workflow.py +114 -0
- ideapress-0.1.0/tests/unit/test_commit_gate.py +191 -0
- ideapress-0.1.0/tests/unit/test_config.py +209 -0
- ideapress-0.1.0/tests/unit/test_content_types.py +117 -0
- ideapress-0.1.0/tests/unit/test_context_budget.py +274 -0
- ideapress-0.1.0/tests/unit/test_diminishing_returns.py +4 -0
- ideapress-0.1.0/tests/unit/test_escalation.py +4 -0
- ideapress-0.1.0/tests/unit/test_exporters.py +308 -0
- ideapress-0.1.0/tests/unit/test_import_boundaries.py +142 -0
- ideapress-0.1.0/tests/unit/test_logging.py +85 -0
- ideapress-0.1.0/tests/unit/test_plan_gates.py +121 -0
- ideapress-0.1.0/tests/unit/test_project_domain.py +80 -0
- ideapress-0.1.0/tests/unit/test_prompt_pack.py +126 -0
- ideapress-0.1.0/tests/unit/test_repair_loop.py +4 -0
- ideapress-0.1.0/tests/unit/test_requirement_checks.py +221 -0
- ideapress-0.1.0/tests/unit/test_requirement_compilation.py +362 -0
- ideapress-0.1.0/tests/unit/test_revision_stop.py +207 -0
- ideapress-0.1.0/tests/unit/test_single_model_invariant.py +305 -0
- ideapress-0.1.0/tests/unit/test_stage_state.py +106 -0
- ideapress-0.1.0/tests/unit/test_stage_vocabulary.py +138 -0
- ideapress-0.1.0/tests/unit/test_validators.py +407 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
indent_style = space
|
|
9
|
+
indent_size = 4
|
|
10
|
+
|
|
11
|
+
[*.py]
|
|
12
|
+
indent_size = 4
|
|
13
|
+
max_line_length = 100
|
|
14
|
+
|
|
15
|
+
[*.{toml,yml,yaml,json}]
|
|
16
|
+
indent_size = 2
|
|
17
|
+
|
|
18
|
+
[*.md]
|
|
19
|
+
trim_trailing_whitespace = false
|
|
20
|
+
max_line_length = off
|
|
21
|
+
|
|
22
|
+
[Makefile]
|
|
23
|
+
indent_style = tab
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
format:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with: { python-version: "3.12" }
|
|
15
|
+
- run: pip install ruff
|
|
16
|
+
- run: ruff format --check .
|
|
17
|
+
|
|
18
|
+
lint:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with: { python-version: "3.12" }
|
|
24
|
+
- run: pip install ruff
|
|
25
|
+
- run: ruff check .
|
|
26
|
+
|
|
27
|
+
types:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- uses: actions/setup-python@v5
|
|
32
|
+
with: { python-version: "3.12" }
|
|
33
|
+
- run: pip install -e ".[dev]"
|
|
34
|
+
- run: mypy src tests
|
|
35
|
+
|
|
36
|
+
boundaries:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- uses: actions/setup-python@v5
|
|
41
|
+
with: { python-version: "3.12" }
|
|
42
|
+
- run: pip install -e ".[dev]"
|
|
43
|
+
- run: lint-imports
|
|
44
|
+
|
|
45
|
+
tests:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
strategy:
|
|
48
|
+
matrix:
|
|
49
|
+
python-version: ["3.12", "3.13"]
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: actions/setup-python@v5
|
|
53
|
+
with: { python-version: "${{ matrix.python-version }}" }
|
|
54
|
+
- run: pip install -e ".[dev]"
|
|
55
|
+
- run: pytest -m "not live and not performance" --cov --cov-report=xml
|
|
56
|
+
|
|
57
|
+
tests-314-early-warning:
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
continue-on-error: true
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
- uses: actions/setup-python@v5
|
|
63
|
+
with: { python-version: "3.14" }
|
|
64
|
+
- run: pip install -e ".[dev]"
|
|
65
|
+
- run: pytest -m "not live and not performance"
|
|
66
|
+
|
|
67
|
+
db-matrix:
|
|
68
|
+
name: tests (PostgreSQL)
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
services:
|
|
71
|
+
postgres:
|
|
72
|
+
image: postgres:16
|
|
73
|
+
# Credentials and database name match `weightsdb.testing`'s documented default URL, so the
|
|
74
|
+
# service this job starts is the one the package looks for. The scaffold named a
|
|
75
|
+
# `postgres`/`postgres` server nothing ever connected to, and passed it as
|
|
76
|
+
# `DATABASE_URL` — a variable `temporary_postgres` does not read — in the bare
|
|
77
|
+
# `postgresql://` form, which resolves to the psycopg2 driver this project does not
|
|
78
|
+
# install. LoadCoach fixed the same three defects in its own job.
|
|
79
|
+
env:
|
|
80
|
+
POSTGRES_USER: weightsdb
|
|
81
|
+
POSTGRES_PASSWORD: weightsdb
|
|
82
|
+
POSTGRES_DB: weightsdb_test
|
|
83
|
+
ports: ["5432:5432"]
|
|
84
|
+
options: >-
|
|
85
|
+
--health-cmd "pg_isready -U weightsdb -d weightsdb_test" --health-interval 5s --health-timeout 5s --health-retries 10
|
|
86
|
+
steps:
|
|
87
|
+
- uses: actions/checkout@v4
|
|
88
|
+
- uses: actions/setup-python@v5
|
|
89
|
+
with: { python-version: "3.12" }
|
|
90
|
+
- run: pip install -e ".[dev,postgres]"
|
|
91
|
+
# `-m integration` selects on a marker this repo never declares or applies, so it collected
|
|
92
|
+
# zero tests and exited 5 — the job would be red on every commit while appearing to test
|
|
93
|
+
# PostgreSQL (M4 handoff HR2, defect 2, which is why both siblings select by path).
|
|
94
|
+
- run: pytest -m "not live and not performance" tests/integration
|
|
95
|
+
env:
|
|
96
|
+
# A silently skipped dialect is an untested dialect: this turns the skip into a failure.
|
|
97
|
+
WEIGHTSDB_REQUIRE_POSTGRES: "1"
|
|
98
|
+
WEIGHTSDB_POSTGRES_URL: postgresql+psycopg://weightsdb:weightsdb@localhost:5432/weightsdb_test
|
|
99
|
+
|
|
100
|
+
coverage:
|
|
101
|
+
needs: [tests]
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@v4
|
|
105
|
+
- uses: actions/setup-python@v5
|
|
106
|
+
with: { python-version: "3.12" }
|
|
107
|
+
- run: pip install -e ".[dev]"
|
|
108
|
+
- run: pytest -m "not live and not performance" --cov --cov-report=term-missing --cov-fail-under=85
|
|
109
|
+
|
|
110
|
+
contracts:
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/checkout@v4
|
|
114
|
+
- uses: actions/setup-python@v5
|
|
115
|
+
with: { python-version: "3.12" }
|
|
116
|
+
- run: pip install -e ".[dev]"
|
|
117
|
+
- run: pytest -m contract
|
|
118
|
+
|
|
119
|
+
security:
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
steps:
|
|
122
|
+
- uses: actions/checkout@v4
|
|
123
|
+
# gitleaks scans *history*, and `actions/checkout` fetches a single commit by default.
|
|
124
|
+
# For a push it is handed `<first-pushed>^..<last-pushed>`, so the parent of the first
|
|
125
|
+
# pushed commit has to be in the object store; in a depth-1 clone it is not, and git
|
|
126
|
+
# answers "unknown revision", which the action reports as exit code 1. It fails the same
|
|
127
|
+
# way whether or not a secret exists, so a green run would not have meant anything either.
|
|
128
|
+
with: { fetch-depth: 0 }
|
|
129
|
+
- uses: actions/setup-python@v5
|
|
130
|
+
with: { python-version: "3.12" }
|
|
131
|
+
- run: pip install pip-audit
|
|
132
|
+
- run: pip-audit
|
|
133
|
+
- uses: gitleaks/gitleaks-action@v2
|
|
134
|
+
env:
|
|
135
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
136
|
+
|
|
137
|
+
build:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
steps:
|
|
140
|
+
- uses: actions/checkout@v4
|
|
141
|
+
- uses: actions/setup-python@v5
|
|
142
|
+
with: { python-version: "3.12" }
|
|
143
|
+
- run: pip install build twine
|
|
144
|
+
- run: python -m build
|
|
145
|
+
- run: twine check dist/*
|
|
146
|
+
- uses: actions/upload-artifact@v4
|
|
147
|
+
with: { name: dist, path: dist/ }
|
|
148
|
+
|
|
149
|
+
install-check:
|
|
150
|
+
needs: [build]
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
steps:
|
|
153
|
+
- uses: actions/checkout@v4
|
|
154
|
+
- uses: actions/setup-python@v5
|
|
155
|
+
with: { python-version: "3.12" }
|
|
156
|
+
- uses: actions/download-artifact@v4
|
|
157
|
+
with: { name: dist, path: dist/ }
|
|
158
|
+
- run: pip install dist/*.whl
|
|
159
|
+
- run: python -c "import ideapress"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*.*.*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write # required for PyPI Trusted Publishing
|
|
9
|
+
contents: write # required to create the GitHub release
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with: { python-version: "3.12" }
|
|
19
|
+
- run: pip install build twine
|
|
20
|
+
- run: python -m build
|
|
21
|
+
- run: twine check dist/*
|
|
22
|
+
- run: pip install "dist/$(ls dist | grep .whl)[dev]"
|
|
23
|
+
- run: pytest -m "not live and not performance"
|
|
24
|
+
- name: Publish to PyPI
|
|
25
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
26
|
+
- name: Create GitHub release
|
|
27
|
+
uses: softprops/action-gh-release@v2
|
|
28
|
+
with:
|
|
29
|
+
generate_release_notes: true
|
|
30
|
+
files: dist/*
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# ---- Python ----
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# ---- Packaging / build backends ----
|
|
25
|
+
pip-wheel-metadata/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
|
|
28
|
+
# ---- Testing / coverage ----
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.cache
|
|
31
|
+
.coverage
|
|
32
|
+
.coverage.*
|
|
33
|
+
coverage.xml
|
|
34
|
+
*.cover
|
|
35
|
+
*.py,cover
|
|
36
|
+
htmlcov/
|
|
37
|
+
nosetests.xml
|
|
38
|
+
.hypothesis/
|
|
39
|
+
|
|
40
|
+
# ---- Type checking / linting ----
|
|
41
|
+
.mypy_cache/
|
|
42
|
+
.dmypy.json
|
|
43
|
+
dmypy.json
|
|
44
|
+
.ruff_cache/
|
|
45
|
+
.pytype/
|
|
46
|
+
|
|
47
|
+
# ---- Virtual environments ----
|
|
48
|
+
.venv/
|
|
49
|
+
venv/
|
|
50
|
+
ENV/
|
|
51
|
+
env/
|
|
52
|
+
env.bak/
|
|
53
|
+
venv.bak/
|
|
54
|
+
.python-version
|
|
55
|
+
|
|
56
|
+
# ---- Distribution / dependency locking ----
|
|
57
|
+
# requirements/*.lock is deliberately NOT ignored. The lock files are committed
|
|
58
|
+
# inputs: CI and release jobs install from them with --require-hashes (Packaging
|
|
59
|
+
# and Release Standards §4, Security Standards §11), so an ignored lock file
|
|
60
|
+
# means a checkout that cannot build.
|
|
61
|
+
|
|
62
|
+
# ---- Editors / OS ----
|
|
63
|
+
.vscode/
|
|
64
|
+
.idea/
|
|
65
|
+
*.swp
|
|
66
|
+
*.swo
|
|
67
|
+
.DS_Store
|
|
68
|
+
Thumbs.db
|
|
69
|
+
|
|
70
|
+
# ---- Suite runtime state (this component's local data) ----
|
|
71
|
+
# The application writes to XDG paths at runtime (~/.config, ~/.local/share,
|
|
72
|
+
# ~/.local/state per Master Architecture §1.2), never inside the repository.
|
|
73
|
+
# These entries only guard against a developer pointing XDG_* at the repo
|
|
74
|
+
# during local testing.
|
|
75
|
+
.local/
|
|
76
|
+
.config/
|
|
77
|
+
*.sqlite3
|
|
78
|
+
*.sqlite3-journal
|
|
79
|
+
*.sqlite3-wal
|
|
80
|
+
*.sqlite3-shm
|
|
81
|
+
/data/
|
|
82
|
+
/logs/
|
|
83
|
+
/backups/
|
|
84
|
+
/artifacts/
|
|
85
|
+
/exports/
|
|
86
|
+
|
|
87
|
+
# ---- Secrets ----
|
|
88
|
+
# Per Security Standards §8: secrets are never committed. Config files may
|
|
89
|
+
# only name where a secret comes from (*_env / *_file), never the value.
|
|
90
|
+
.env
|
|
91
|
+
.env.*
|
|
92
|
+
*.key
|
|
93
|
+
*.pem
|
|
94
|
+
secrets.toml
|
|
95
|
+
|
|
96
|
+
# ---- Node-free JS assets (MirrorWall consumers may still use a local tool) ----
|
|
97
|
+
node_modules/
|
|
98
|
+
|
|
99
|
+
# ---- Build artifacts from docs generation ----
|
|
100
|
+
docs/api/openapi-v1.json.tmp
|
|
101
|
+
|
|
102
|
+
# ---- Milestone evidence (transcripts, exports and hashes from a build run) ----
|
|
103
|
+
# M7's exit condition is a demonstration, and the artefacts it produces — briefs, generated
|
|
104
|
+
# documents, three export formats, hash comparisons, resident-model polls — are evidence for a
|
|
105
|
+
# handoff, not source. They stay on disk for the reader of that handoff and out of the history.
|
|
106
|
+
.m7-evidence/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[importlinter]
|
|
2
|
+
root_package = ideapress
|
|
3
|
+
include_external_packages = True
|
|
4
|
+
|
|
5
|
+
[importlinter:contract:layers]
|
|
6
|
+
name = IdeaPress internal layering
|
|
7
|
+
type = layers
|
|
8
|
+
layers =
|
|
9
|
+
web
|
|
10
|
+
cli
|
|
11
|
+
services
|
|
12
|
+
domain
|
|
13
|
+
containers = ideapress
|
|
14
|
+
|
|
15
|
+
[importlinter:contract:web-cli-independence]
|
|
16
|
+
name = Web and CLI never import each other
|
|
17
|
+
type = independence
|
|
18
|
+
modules =
|
|
19
|
+
ideapress.web
|
|
20
|
+
ideapress.cli
|
|
21
|
+
|
|
22
|
+
[importlinter:contract:domain-purity]
|
|
23
|
+
name = Domain imports no frameworks
|
|
24
|
+
type = forbidden
|
|
25
|
+
source_modules = ideapress.domain
|
|
26
|
+
forbidden_modules =
|
|
27
|
+
fastapi
|
|
28
|
+
starlette
|
|
29
|
+
sqlalchemy
|
|
30
|
+
typer
|
|
31
|
+
httpx
|
|
32
|
+
jinja2
|
|
33
|
+
|
|
34
|
+
[importlinter:contract:no-other-applications]
|
|
35
|
+
name = IdeaPress must not import other applications
|
|
36
|
+
type = forbidden
|
|
37
|
+
source_modules = ideapress
|
|
38
|
+
forbidden_modules =
|
|
39
|
+
freeweight
|
|
40
|
+
loadcoach
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.6.9
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
9
|
+
rev: v4.6.0
|
|
10
|
+
hooks:
|
|
11
|
+
- id: trailing-whitespace
|
|
12
|
+
- id: end-of-file-fixer
|
|
13
|
+
- id: check-toml
|
|
14
|
+
- id: check-json
|
|
15
|
+
- id: check-added-large-files
|
|
16
|
+
- id: check-merge-conflict
|
|
17
|
+
- id: mixed-line-ending
|
|
18
|
+
args: [--fix=lf]
|
|
19
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
20
|
+
rev: v8.18.4
|
|
21
|
+
hooks:
|
|
22
|
+
- id: gitleaks
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `ideapress` are documented here.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/), pre-1.0 per
|
|
6
|
+
packaging and release standards §3.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `GET`/`PUT /settings`, `GET /workflows/{id}`, `POST /projects/{id}/units/{unit_id}/revise`, and
|
|
12
|
+
the `workflow` and `prompts` command groups — the four endpoints and two groups the specification
|
|
13
|
+
lists that the phases had not yet built.
|
|
14
|
+
- Exporters for Markdown, HTML and JSON, byte-identical for the same committed project across
|
|
15
|
+
repeats, locales, timezones and hash seeds. The HTML is a single self-contained file with no
|
|
16
|
+
external reference of any kind, so it opens with no network.
|
|
17
|
+
- Export format versioning, recorded on every export and embedded in every rendered document.
|
|
18
|
+
- `GET`/`POST /projects/{id}/export`, `GET /export/formats`, and `ideapress export run|formats`.
|
|
19
|
+
- The `project_review` stage: cross-unit consistency findings, advisory by design.
|
|
20
|
+
- The open content-type registry, with `article` and `report` shipped.
|
|
21
|
+
- Review: `audit_fast`, `audit_deep` (escalation only, once per unit per round), `critique` with
|
|
22
|
+
"leave it alone" as a first-class verdict, and `revise` bounded by the round limit or by
|
|
23
|
+
diminishing returns computed from deterministic finding counts. Which stop applied is recorded.
|
|
24
|
+
- A revision that increases validation failures is rejected and the previous version kept.
|
|
25
|
+
- Migration `0004`: `audit_findings`, `critiques`. The findings, their severity and evidence, and
|
|
26
|
+
what changed between rounds, on the unit page.
|
|
27
|
+
- The core loop: draft, validate, repair (bounded, then pause the unit), coverage and an atomic
|
|
28
|
+
commit, with complete provenance on every committed version.
|
|
29
|
+
- Migration `0003`: `unit_versions`, `validations`, `coverage`, `exports`.
|
|
30
|
+
- The unit page and `ideapress unit list|show|history`, showing content, coverage, validation and
|
|
31
|
+
the attempts that produced it.
|
|
32
|
+
- Deterministic validation: all seven families from workflows §4 — structural, length, format,
|
|
33
|
+
content constraints, reference integrity, consistency and safety — with failures classed blocking
|
|
34
|
+
or advisory, and no model involved anywhere.
|
|
35
|
+
- Context assembly to a token budget, with the reduction order as data. Requirements and the unit
|
|
36
|
+
specification are never dropped; when they alone exceed the budget the stage fails carrying both
|
|
37
|
+
the required figure and the budget.
|
|
38
|
+
- The stage runner: a background thread per stage, the unit state machine as a transition table,
|
|
39
|
+
persisted gap-free stage events, and SSE that replays from `Last-Event-ID` after a disconnect.
|
|
40
|
+
- `POST /projects/{id}/plan`, `POST /projects/{id}/stages/{stage}/run`, the task and stream
|
|
41
|
+
endpoints, `GET /workflows`, and the plan page showing each requirement beside its quotation.
|
|
42
|
+
- `ideapress plan build|show` and `ideapress stage run|list|status|cancel`.
|
|
43
|
+
- Migration `0002`: `requirements`, `units`, `stage_runs`, `attempts`, `stage_events`.
|
|
44
|
+
- Requirement compilation: every requirement carries a verbatim quotation from the author material,
|
|
45
|
+
and one that cannot be quoted is refused and shown as refused. Check kinds are a closed set of
|
|
46
|
+
literal-string and numeric comparisons; there is deliberately no pattern check.
|
|
47
|
+
- The plan gate: every blocking requirement must be assigned to at least one unit, and an empty
|
|
48
|
+
requirement list or an empty plan does not satisfy it.
|
|
49
|
+
- The inference port (`InferenceBackend`, `StageRequest`, `StageResult`, `StageEvent`,
|
|
50
|
+
`BackendHealth`) and three adapters: Ollama over ModelRack, a deterministic offline fake, and an
|
|
51
|
+
OpenAI-compatible one. Switching between them is configuration.
|
|
52
|
+
- One generation runs at a time, through one function, and the resident model is unloaded before a
|
|
53
|
+
different one loads (ADR-0038).
|
|
54
|
+
- The prompt pack on `setspec.prompts`: versioned JSON records with a hashed manifest.
|
|
55
|
+
- `GET /backends`, `POST /backends/test`, a backend page that states where content goes, and
|
|
56
|
+
`ideapress backend list|test|switch`.
|
|
57
|
+
- Projects: create, list, open, update, archive, and delete with a preview of exactly what will be
|
|
58
|
+
removed. Slugs are derived from the title and never taken from input, and a project's artifact
|
|
59
|
+
directory is created private and containment-checked.
|
|
60
|
+
- Migration `0001` on WeightsDB's runner: `projects`, `sources`, `settings`, `api_tokens`, verified
|
|
61
|
+
against both SQLite and PostgreSQL 16 including the Alembic-to-models parity check.
|
|
62
|
+
- `ideapress project create|list|show|archive|delete` and `ideapress db upgrade|status|backup|restore`.
|
|
63
|
+
- Project list and detail pages, with the shared CSRF token on every form.
|
|
64
|
+
- Application skeleton on the shared packages: typed settings with the documented precedence and
|
|
65
|
+
refusals, structured logging with the suite's correlation fields, `/health`, `/version`,
|
|
66
|
+
`/system/status`, the system page, and the `serve`/`health`/`doctor`/`version`/`config` commands.
|
|
67
|
+
- `[execution]` configuration: `max_concurrent_stages` (only 1 is accepted; a higher value is
|
|
68
|
+
refused at startup) and `unload_before_model_switch`.
|
|
69
|
+
- A startup check that `[models.stages]`, `StageId` and workflows §2 name the same stages, and
|
|
70
|
+
refuses a binding for a stage that does not exist or a model-using stage with none.
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
- An export's recorded `sha256` is now the file's own digest, so `sha256sum` on the exported file
|
|
74
|
+
reproduces it.
|
|
75
|
+
- A second process opening the database no longer marks a running stage as interrupted. Migration
|
|
76
|
+
`0005` records which process owns a stage run, and only a run whose owner is gone is marked.
|
|
77
|
+
- `/api/v1/docs` and `/api/v1/openapi.json` work: response annotations imported only under
|
|
78
|
+
`TYPE_CHECKING` left forward references FastAPI could not resolve, so building the schema raised.
|
|
79
|
+
- The CI workflow parses again: an edit had left a duplicate `env:` key on one step, which GitHub
|
|
80
|
+
refuses and PyYAML accepts, so the whole workflow was invalid and no job ran. A test now loads it
|
|
81
|
+
with a loader that refuses duplicate keys the way GitHub does.
|
|
82
|
+
- The PostgreSQL CI job now names the server `weightsdb.testing` looks for, passes
|
|
83
|
+
`WEIGHTSDB_POSTGRES_URL` rather than `DATABASE_URL`, and uses the `+psycopg` driver this project
|
|
84
|
+
installs; it previously could not connect at all.
|
|
85
|
+
- `pytest` now collects under the bare console script as well as `python -m pytest`
|
|
86
|
+
(`pythonpath = ["."]`), which is the invocation CI runs.
|
|
87
|
+
- Coverage measures the importable `ideapress` package rather than the `src/ideapress` path, so a
|
|
88
|
+
non-editable install reports real coverage instead of 0 %.
|
|
89
|
+
- The PostgreSQL CI job selects tests by path; it previously selected a marker this repository never
|
|
90
|
+
declares, collecting nothing.
|
|
91
|
+
- `ruff` no longer formats `docs/`, which is a byte-identical mirror of the suite documentation.
|
|
92
|
+
- Restored the six mirrored `docs/apps/ideapress/` documents; three were missing and three had been
|
|
93
|
+
edited downstream.
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
- `loadcoach` moved out of the `dev` extra into a `loadcoach-contract` extra, so the default
|
|
97
|
+
development and CI environment has no other application installed.
|
|
98
|
+
|
|
99
|
+
- Widened the `sweatmeter` pin to `>=0.4,<0.5`. SweatMeter's first published release is `0.4.0`
|
|
100
|
+
(`0.3.0` completed its development plan but never reached the index), and it adds the in-process
|
|
101
|
+
NVML GPU backend, selected automatically wherever the optional `pynvml` extra is installed.
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
- Repository scaffold generated from the suite's development plan (no functional code yet).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Contributing to IdeaPress
|
|
2
|
+
|
|
3
|
+
This repository is one component of the Local AI Suite. Before changing anything, read
|
|
4
|
+
`docs/apps/ideapress/spec.md` and the current
|
|
5
|
+
phase in `development-plan.md` — both are in this repository's `docs/` folder, copied from the suite's
|
|
6
|
+
central documentation set so this repository can be worked on independently.
|
|
7
|
+
|
|
8
|
+
## Development setup
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
python -m venv .venv
|
|
12
|
+
source .venv/bin/activate
|
|
13
|
+
pip install -e ".[dev]"
|
|
14
|
+
pre-commit install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Required reading, in order
|
|
18
|
+
|
|
19
|
+
1. This component's spec — purpose, scope, non-goals, contracts.
|
|
20
|
+
2. `development-plan.md` in the same folder — the phase you are implementing, its acceptance criteria and its tests.
|
|
21
|
+
|
|
22
|
+
## Rules that apply to every change here
|
|
23
|
+
|
|
24
|
+
* Follow the architecture's dependency direction.
|
|
25
|
+
This repository's `.importlinter` enforces it in CI; do not weaken that file to make an import work.
|
|
26
|
+
* No business logic in a route handler or CLI command body — both call one service method and render
|
|
27
|
+
.
|
|
28
|
+
* An unavailable measurement is `Unsupported`, never zero, never `None` used as a substitute
|
|
29
|
+
.
|
|
30
|
+
* Prompts are versioned JSON records, not Python string literals.
|
|
31
|
+
* Every phase's acceptance criteria in `development-plan.md` must be demonstrable, not merely
|
|
32
|
+
test-covered — the plan states what to run and what a person should see.
|
|
33
|
+
|
|
34
|
+
## Before opening a pull request
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ruff format --check .
|
|
38
|
+
ruff check .
|
|
39
|
+
mypy src tests
|
|
40
|
+
lint-imports
|
|
41
|
+
pytest -m "not live and not performance"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
All of the above run in CI (`.github/workflows/ci.yml`); a red CI run blocks merge.
|
|
45
|
+
|
|
46
|
+
## Commit style
|
|
47
|
+
|
|
48
|
+
Conventional Commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`, `perf:`, `build:`,
|
|
49
|
+
`ci:`), with `!` or a `BREAKING CHANGE:` footer for breaking changes. Update `CHANGELOG.md` under
|
|
50
|
+
`## [Unreleased]` for any user-visible change.
|