rootsign 0.1.1__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.
- rootsign-0.1.1/.env.example +38 -0
- rootsign-0.1.1/.github/CLA_SIGNED.md +7 -0
- rootsign-0.1.1/.github/CODEOWNERS +9 -0
- rootsign-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +33 -0
- rootsign-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +34 -0
- rootsign-0.1.1/.github/ISSUE_TEMPLATE/framework_integration.yml +26 -0
- rootsign-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +27 -0
- rootsign-0.1.1/.github/workflows/ci.yml +153 -0
- rootsign-0.1.1/.gitignore +65 -0
- rootsign-0.1.1/.vscode/settings.json +9 -0
- rootsign-0.1.1/CLA.md +15 -0
- rootsign-0.1.1/CLAUDE.md +90 -0
- rootsign-0.1.1/CONTRIBUTING.md +82 -0
- rootsign-0.1.1/CONTRIBUTORS.md +11 -0
- rootsign-0.1.1/LICENSE +201 -0
- rootsign-0.1.1/NOTICE +10 -0
- rootsign-0.1.1/PKG-INFO +313 -0
- rootsign-0.1.1/README.md +267 -0
- rootsign-0.1.1/SECURITY.md +65 -0
- rootsign-0.1.1/alembic.ini +39 -0
- rootsign-0.1.1/docker-compose.yml +22 -0
- rootsign-0.1.1/docs/adr/ADR-001-hash-canonical-spec.md +60 -0
- rootsign-0.1.1/docs/adr/ADR-002-transport-agnostic-client.md +47 -0
- rootsign-0.1.1/docs/adr/ADR-003-framework-contract-tests.md +39 -0
- rootsign-0.1.1/docs/adr/ADR-004-langgraph-interception-strategy.md +113 -0
- rootsign-0.1.1/docs/adr/ADR-005-crewai-interception-strategy.md +117 -0
- rootsign-0.1.1/docs/adr/ADR-006-redaction-contract.md +158 -0
- rootsign-0.1.1/docs/adr/ADR-007-hitl-checkpoint-design.md +214 -0
- rootsign-0.1.1/docs/adr/ADR-008-decision-capture.md +84 -0
- rootsign-0.1.1/docs/design-partner-feedback.md +180 -0
- rootsign-0.1.1/docs/framework-support.md +104 -0
- rootsign-0.1.1/docs/releases/v0.1.0.md +129 -0
- rootsign-0.1.1/docs/rootsign-logo.png +0 -0
- rootsign-0.1.1/docs/show-hn-draft.md +178 -0
- rootsign-0.1.1/pyproject.toml +102 -0
- rootsign-0.1.1/rootsign/__init__.py +106 -0
- rootsign-0.1.1/rootsign/_migrations/__init__.py +7 -0
- rootsign-0.1.1/rootsign/_migrations/env.py +65 -0
- rootsign-0.1.1/rootsign/_migrations/script.py.mako +25 -0
- rootsign-0.1.1/rootsign/_migrations/versions/0001_initial_schema.py +387 -0
- rootsign-0.1.1/rootsign/_migrations/versions/0002_approval_parent_id.py +56 -0
- rootsign-0.1.1/rootsign/_migrations/versions/0003_action_timed_out.py +50 -0
- rootsign-0.1.1/rootsign/_version.py +29 -0
- rootsign-0.1.1/rootsign/cli.py +230 -0
- rootsign-0.1.1/rootsign/config.py +32 -0
- rootsign-0.1.1/rootsign/crud/__init__.py +28 -0
- rootsign-0.1.1/rootsign/crud/action.py +201 -0
- rootsign-0.1.1/rootsign/crud/agent.py +10 -0
- rootsign-0.1.1/rootsign/crud/approval.py +298 -0
- rootsign-0.1.1/rootsign/crud/base.py +74 -0
- rootsign-0.1.1/rootsign/crud/decision.py +39 -0
- rootsign-0.1.1/rootsign/crud/incident.py +10 -0
- rootsign-0.1.1/rootsign/crud/policy.py +10 -0
- rootsign-0.1.1/rootsign/crud/session.py +10 -0
- rootsign-0.1.1/rootsign/database.py +32 -0
- rootsign-0.1.1/rootsign/errors.py +173 -0
- rootsign-0.1.1/rootsign/hashing.py +47 -0
- rootsign-0.1.1/rootsign/ingest/__init__.py +19 -0
- rootsign-0.1.1/rootsign/ingest/handler.py +351 -0
- rootsign-0.1.1/rootsign/ingest/idempotency.py +66 -0
- rootsign-0.1.1/rootsign/ingest/schemas.py +203 -0
- rootsign-0.1.1/rootsign/models/__init__.py +19 -0
- rootsign-0.1.1/rootsign/models/action.py +86 -0
- rootsign-0.1.1/rootsign/models/agent.py +66 -0
- rootsign-0.1.1/rootsign/models/approval.py +66 -0
- rootsign-0.1.1/rootsign/models/decision.py +61 -0
- rootsign-0.1.1/rootsign/models/incident.py +62 -0
- rootsign-0.1.1/rootsign/models/policy.py +50 -0
- rootsign-0.1.1/rootsign/models/session.py +63 -0
- rootsign-0.1.1/rootsign/schemas/__init__.py +83 -0
- rootsign-0.1.1/rootsign/schemas/action.py +57 -0
- rootsign-0.1.1/rootsign/schemas/agent.py +66 -0
- rootsign-0.1.1/rootsign/schemas/approval.py +42 -0
- rootsign-0.1.1/rootsign/schemas/decision.py +34 -0
- rootsign-0.1.1/rootsign/schemas/incident.py +62 -0
- rootsign-0.1.1/rootsign/schemas/policy.py +48 -0
- rootsign-0.1.1/rootsign/schemas/session.py +50 -0
- rootsign-0.1.1/rootsign/sdk/__init__.py +40 -0
- rootsign-0.1.1/rootsign/sdk/_async_bridge.py +50 -0
- rootsign-0.1.1/rootsign/sdk/chain.py +151 -0
- rootsign-0.1.1/rootsign/sdk/cli.py +300 -0
- rootsign-0.1.1/rootsign/sdk/client.py +107 -0
- rootsign-0.1.1/rootsign/sdk/config.py +78 -0
- rootsign-0.1.1/rootsign/sdk/context.py +127 -0
- rootsign-0.1.1/rootsign/sdk/decorator.py +612 -0
- rootsign-0.1.1/rootsign/sdk/frameworks/__init__.py +6 -0
- rootsign-0.1.1/rootsign/sdk/frameworks/crewai.py +154 -0
- rootsign-0.1.1/rootsign/sdk/frameworks/langgraph.py +125 -0
- rootsign-0.1.1/rootsign/sdk/hashing.py +42 -0
- rootsign-0.1.1/rootsign/sdk/hitl.py +231 -0
- rootsign-0.1.1/rootsign/sdk/redaction.py +228 -0
- rootsign-0.1.1/rootsign/sdk/registration.py +73 -0
- rootsign-0.1.1/rootsign/sdk/session.py +119 -0
- rootsign-0.1.1/scripts/demo_verify_chain.py +125 -0
- rootsign-0.1.1/scripts/generate_hash_vectors.py +114 -0
- rootsign-0.1.1/scripts/init_test_db.sql +5 -0
- rootsign-0.1.1/tests/__init__.py +0 -0
- rootsign-0.1.1/tests/conftest.py +304 -0
- rootsign-0.1.1/tests/contract/__init__.py +0 -0
- rootsign-0.1.1/tests/contract/crewai/__init__.py +0 -0
- rootsign-0.1.1/tests/contract/crewai/test_tool_interception.py +170 -0
- rootsign-0.1.1/tests/contract/langgraph/__init__.py +1 -0
- rootsign-0.1.1/tests/contract/langgraph/test_tool_interception.py +153 -0
- rootsign-0.1.1/tests/fixtures/hash_vectors.json +60 -0
- rootsign-0.1.1/tests/fixtures/redaction_vectors.json +47 -0
- rootsign-0.1.1/tests/integration/__init__.py +0 -0
- rootsign-0.1.1/tests/integration/test_approve_cli.py +229 -0
- rootsign-0.1.1/tests/integration/test_crewai_integration.py +129 -0
- rootsign-0.1.1/tests/integration/test_crud.py +306 -0
- rootsign-0.1.1/tests/integration/test_decision_capture.py +200 -0
- rootsign-0.1.1/tests/integration/test_decision_ingest.py +69 -0
- rootsign-0.1.1/tests/integration/test_ingest.py +737 -0
- rootsign-0.1.1/tests/integration/test_langgraph_integration.py +130 -0
- rootsign-0.1.1/tests/integration/test_register_agent.py +66 -0
- rootsign-0.1.1/tests/integration/test_relationships.py +130 -0
- rootsign-0.1.1/tests/integration/test_sdk_smoke.py +106 -0
- rootsign-0.1.1/tests/integration/test_session_context_manager.py +64 -0
- rootsign-0.1.1/tests/integration/test_show_hn_quickstart.py +186 -0
- rootsign-0.1.1/tests/integration/test_verify_cli.py +154 -0
- rootsign-0.1.1/tests/performance/__init__.py +0 -0
- rootsign-0.1.1/tests/performance/test_benchmarks.py +125 -0
- rootsign-0.1.1/tests/performance/test_langgraph_benchmarks.py +73 -0
- rootsign-0.1.1/tests/performance/test_verify_benchmarks.py +108 -0
- rootsign-0.1.1/tests/unit/__init__.py +0 -0
- rootsign-0.1.1/tests/unit/test_action_record_decision_id.py +118 -0
- rootsign-0.1.1/tests/unit/test_chain.py +166 -0
- rootsign-0.1.1/tests/unit/test_context.py +125 -0
- rootsign-0.1.1/tests/unit/test_crewai_tracer.py +184 -0
- rootsign-0.1.1/tests/unit/test_crud_approval.py +277 -0
- rootsign-0.1.1/tests/unit/test_emit_approval_record.py +206 -0
- rootsign-0.1.1/tests/unit/test_emit_decision_record.py +163 -0
- rootsign-0.1.1/tests/unit/test_errors.py +127 -0
- rootsign-0.1.1/tests/unit/test_hashing.py +189 -0
- rootsign-0.1.1/tests/unit/test_hitl.py +298 -0
- rootsign-0.1.1/tests/unit/test_ingest_client.py +85 -0
- rootsign-0.1.1/tests/unit/test_langgraph_tracer.py +144 -0
- rootsign-0.1.1/tests/unit/test_redaction.py +68 -0
- rootsign-0.1.1/tests/unit/test_redaction_pii.py +270 -0
- rootsign-0.1.1/tests/unit/test_schemas.py +294 -0
- rootsign-0.1.1/tests/unit/test_sdk_config.py +51 -0
- rootsign-0.1.1/tests/unit/test_sdk_hashing.py +52 -0
- rootsign-0.1.1/tests/unit/test_trace_hitl.py +372 -0
- rootsign-0.1.1/uv.lock +4496 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------
|
|
2
|
+
# Store-side infra config (read by rootsign.config.Settings — no prefix).
|
|
3
|
+
# These describe the PostgreSQL/TimescaleDB instance the storage layer
|
|
4
|
+
# connects to. Defaults assume the bundled docker-compose db service.
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
DATABASE_URL=postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
7
|
+
DATABASE_URL_SYNC=postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
8
|
+
TEST_DATABASE_URL=postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_test
|
|
9
|
+
TEST_DATABASE_URL_SYNC=postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_test
|
|
10
|
+
DB_POOL_SIZE=10
|
|
11
|
+
DB_MAX_OVERFLOW=20
|
|
12
|
+
DB_POOL_TIMEOUT=30
|
|
13
|
+
|
|
14
|
+
# ---------------------------------------------------------------------------
|
|
15
|
+
# RootSign SDK config (read by rootsign.sdk.config.SDKSettings, prefix
|
|
16
|
+
# ROOTSIGN_). User-facing — the developer using @rootsign.trace sets these.
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
# Transport: 'local' calls IngestHandler in-process (Phase 1 default).
|
|
20
|
+
# 'cloud' would POST to the hosted backend, but Phase 1 stubs that path —
|
|
21
|
+
# HttpIngestClient raises NotImplementedError until Phase 2.
|
|
22
|
+
ROOTSIGN_BACKEND=local
|
|
23
|
+
# ROOTSIGN_CLOUD_URL=https://ingest.getprovidex.com/v1
|
|
24
|
+
# ROOTSIGN_API_KEY=your-api-key-here
|
|
25
|
+
|
|
26
|
+
# Capture per-step Decision records (the agent's reasoning). Off by default
|
|
27
|
+
# because Decision payloads are the largest and most PII-sensitive surface.
|
|
28
|
+
# Enabling in production requires explicit user-consent acknowledgement.
|
|
29
|
+
ROOTSIGN_CAPTURE_DECISIONS=false
|
|
30
|
+
|
|
31
|
+
# Write-ahead log for events that failed ingest (network blip, DB down).
|
|
32
|
+
# The decorator drains this on the next successful call. Default: ~/.rootsign/wal
|
|
33
|
+
ROOTSIGN_WAL_PATH=~/.rootsign/wal
|
|
34
|
+
|
|
35
|
+
# Retry policy for HttpIngestClient (Phase 2 — unused in Phase 1).
|
|
36
|
+
ROOTSIGN_MAX_RETRIES=3
|
|
37
|
+
ROOTSIGN_RETRY_BASE_DELAY=0.1
|
|
38
|
+
ROOTSIGN_RETRY_MAX_DELAY=5.0
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# CLA Signatures
|
|
2
|
+
|
|
3
|
+
This file records contributors who have signed the [Contributor License Agreement](../CLA.md). New contributors are added automatically by the CLA Assistant bot the first time they comment the sign-off line on a PR.
|
|
4
|
+
|
|
5
|
+
| GitHub handle | Date | Commit |
|
|
6
|
+
|---------------|------------|---------|
|
|
7
|
+
| @oabolade | 2026-05-01 | initial |
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something is not working as described in the spec
|
|
3
|
+
labels: [bug, needs-triage]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: description
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened?
|
|
9
|
+
description: Describe the bug. Include the exact error message.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: repro
|
|
14
|
+
attributes:
|
|
15
|
+
label: Minimal reproduction
|
|
16
|
+
description: Shortest code that reproduces the issue.
|
|
17
|
+
render: python
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: dropdown
|
|
21
|
+
id: framework
|
|
22
|
+
attributes:
|
|
23
|
+
label: Agent framework
|
|
24
|
+
options: [LangGraph, CrewAI, AutoGen, Custom, Not applicable]
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: input
|
|
28
|
+
id: versions
|
|
29
|
+
attributes:
|
|
30
|
+
label: Versions
|
|
31
|
+
placeholder: rootsign==0.1.0, langgraph==0.2.1, python==3.11
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new capability or improvement
|
|
3
|
+
labels: [enhancement, needs-triage]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What problem does this solve?
|
|
9
|
+
description: Describe the limitation or gap you are experiencing.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: solution
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: How would you like this to work?
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: dropdown
|
|
20
|
+
id: phase
|
|
21
|
+
attributes:
|
|
22
|
+
label: Which product phase does this relate to?
|
|
23
|
+
options:
|
|
24
|
+
- Phase 1 (SDK capture)
|
|
25
|
+
- Phase 2 (Compliance dashboard)
|
|
26
|
+
- Phase 3 (Enterprise enforcement)
|
|
27
|
+
- Phase 4 (Cross-platform governance)
|
|
28
|
+
- Not sure
|
|
29
|
+
- type: checkboxes
|
|
30
|
+
id: contribute
|
|
31
|
+
attributes:
|
|
32
|
+
label: Contribution
|
|
33
|
+
options:
|
|
34
|
+
- label: I am willing to implement this
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Framework integration request
|
|
2
|
+
description: Request support for a new agent framework
|
|
3
|
+
labels: [framework-integration, enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: input
|
|
6
|
+
id: framework
|
|
7
|
+
attributes:
|
|
8
|
+
label: Framework name and link
|
|
9
|
+
placeholder: 'LlamaIndex — https://github.com/run-llama/llama_index'
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: tool_call
|
|
14
|
+
attributes:
|
|
15
|
+
label: How does this framework call tools?
|
|
16
|
+
description: Paste a minimal example of a tool call in this framework.
|
|
17
|
+
render: python
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: checkboxes
|
|
21
|
+
id: willing
|
|
22
|
+
attributes:
|
|
23
|
+
label: Contribution
|
|
24
|
+
options:
|
|
25
|
+
- label: I am willing to implement this integration
|
|
26
|
+
- label: I can provide a real pipeline for contract testing
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
<!-- One sentence: what does this PR do? -->
|
|
3
|
+
|
|
4
|
+
## Related issue
|
|
5
|
+
Closes #
|
|
6
|
+
|
|
7
|
+
## Type of change
|
|
8
|
+
- [ ] Bug fix
|
|
9
|
+
- [ ] New feature
|
|
10
|
+
- [ ] Framework integration
|
|
11
|
+
- [ ] Documentation
|
|
12
|
+
- [ ] Test coverage
|
|
13
|
+
|
|
14
|
+
## Checklist
|
|
15
|
+
- [ ] All existing tests pass (`pytest tests/ -v`)
|
|
16
|
+
- [ ] New code has test coverage >= 90%
|
|
17
|
+
- [ ] Overall coverage stays >= 85% (enforced by `pyproject.toml`)
|
|
18
|
+
- [ ] No changes to canonical hash spec (or new ADR filed if yes — see [ADR-001](../docs/adr/ADR-001-hash-canonical-spec.md))
|
|
19
|
+
- [ ] `ruff check .` and `ruff format .` pass
|
|
20
|
+
- [ ] CONTRIBUTING.md commit message format followed
|
|
21
|
+
- [ ] CLA signed (bot will check automatically)
|
|
22
|
+
|
|
23
|
+
## Testing done
|
|
24
|
+
<!-- List specific test cases you ran manually -->
|
|
25
|
+
|
|
26
|
+
## Notes for reviewer
|
|
27
|
+
<!-- Anything the reviewer should pay special attention to -->
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, 'feat/**', 'fix/**', 'test/**', 'docs/**']
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
unit-tests:
|
|
11
|
+
name: Unit tests (Python ${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ['3.11', '3.12']
|
|
17
|
+
services:
|
|
18
|
+
# The session-scoped _bootstrap_test_db fixture needs a real Postgres
|
|
19
|
+
# even for unit tests (it runs alembic against rootsign_test before
|
|
20
|
+
# collection). See feedback_phase0_discrepancies — we keep the
|
|
21
|
+
# alembic-based test DB rather than Base.metadata.create_all so the
|
|
22
|
+
# actions table stays a real TimescaleDB hypertable.
|
|
23
|
+
timescaledb:
|
|
24
|
+
image: timescale/timescaledb:latest-pg16
|
|
25
|
+
env:
|
|
26
|
+
POSTGRES_DB: rootsign_dev
|
|
27
|
+
POSTGRES_USER: rootsign
|
|
28
|
+
POSTGRES_PASSWORD: rootsign
|
|
29
|
+
ports: ['5432:5432']
|
|
30
|
+
options: >-
|
|
31
|
+
--health-cmd pg_isready
|
|
32
|
+
--health-interval 5s
|
|
33
|
+
--health-timeout 5s
|
|
34
|
+
--health-retries 10
|
|
35
|
+
env:
|
|
36
|
+
DATABASE_URL: postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
37
|
+
DATABASE_URL_SYNC: postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
38
|
+
TEST_DATABASE_URL: postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_test
|
|
39
|
+
TEST_DATABASE_URL_SYNC: postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_test
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v5
|
|
42
|
+
- uses: actions/setup-python@v6
|
|
43
|
+
with:
|
|
44
|
+
python-version: ${{ matrix.python-version }}
|
|
45
|
+
- name: Install
|
|
46
|
+
run: pip install -e '.[dev]'
|
|
47
|
+
- name: Wait for Postgres
|
|
48
|
+
run: |
|
|
49
|
+
for _ in $(seq 1 30); do
|
|
50
|
+
pg_isready -h localhost -U rootsign -d rootsign_dev && break
|
|
51
|
+
sleep 1
|
|
52
|
+
done
|
|
53
|
+
- name: Bootstrap rootsign_test
|
|
54
|
+
run: |
|
|
55
|
+
PGPASSWORD=rootsign psql -h localhost -U rootsign -d rootsign_dev \
|
|
56
|
+
-c "CREATE DATABASE rootsign_test OWNER rootsign;" || true
|
|
57
|
+
PGPASSWORD=rootsign psql -h localhost -U rootsign -d rootsign_test \
|
|
58
|
+
-c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
|
|
59
|
+
- name: Unit tests
|
|
60
|
+
run: pytest tests/unit/ -v
|
|
61
|
+
|
|
62
|
+
integration-tests:
|
|
63
|
+
name: Integration tests (Python 3.12)
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
services:
|
|
66
|
+
timescaledb:
|
|
67
|
+
image: timescale/timescaledb:latest-pg16
|
|
68
|
+
env:
|
|
69
|
+
POSTGRES_DB: rootsign_dev
|
|
70
|
+
POSTGRES_USER: rootsign
|
|
71
|
+
POSTGRES_PASSWORD: rootsign
|
|
72
|
+
ports: ['5432:5432']
|
|
73
|
+
options: >-
|
|
74
|
+
--health-cmd pg_isready
|
|
75
|
+
--health-interval 5s
|
|
76
|
+
--health-timeout 5s
|
|
77
|
+
--health-retries 10
|
|
78
|
+
env:
|
|
79
|
+
DATABASE_URL: postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
80
|
+
DATABASE_URL_SYNC: postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_dev
|
|
81
|
+
TEST_DATABASE_URL: postgresql+asyncpg://rootsign:rootsign@localhost:5432/rootsign_test
|
|
82
|
+
TEST_DATABASE_URL_SYNC: postgresql+psycopg2://rootsign:rootsign@localhost:5432/rootsign_test
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@v5
|
|
85
|
+
- uses: actions/setup-python@v6
|
|
86
|
+
with:
|
|
87
|
+
python-version: '3.12'
|
|
88
|
+
- run: pip install -e '.[dev]'
|
|
89
|
+
- name: Bootstrap rootsign_test
|
|
90
|
+
run: |
|
|
91
|
+
PGPASSWORD=rootsign psql -h localhost -U rootsign -d rootsign_dev \
|
|
92
|
+
-c "CREATE DATABASE rootsign_test OWNER rootsign;" || true
|
|
93
|
+
PGPASSWORD=rootsign psql -h localhost -U rootsign -d rootsign_test \
|
|
94
|
+
-c "CREATE EXTENSION IF NOT EXISTS timescaledb;"
|
|
95
|
+
- name: alembic upgrade head
|
|
96
|
+
run: alembic upgrade head
|
|
97
|
+
- name: Integration tests
|
|
98
|
+
run: pytest tests/integration/ -v
|
|
99
|
+
|
|
100
|
+
framework-contract-langgraph:
|
|
101
|
+
# ADR-003 / Sprint 2: framework contract tests are MANDATORY — this job
|
|
102
|
+
# must pass on every PR before merge. Sprint 2 filled the contract suite
|
|
103
|
+
# in tests/contract/langgraph/ (see ADR-004 for the interception design).
|
|
104
|
+
#
|
|
105
|
+
# Contract tests use a mock IngestClient and never touch the DB, so this
|
|
106
|
+
# job intentionally runs WITHOUT a Postgres service. The
|
|
107
|
+
# ROOTSIGN_SKIP_DB_BOOTSTRAP env var tells the session-autouse fixture
|
|
108
|
+
# in tests/conftest.py to skip alembic / DB connect at session start.
|
|
109
|
+
name: LangGraph contract (langgraph ~=${{ matrix.langgraph-version }})
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
strategy:
|
|
112
|
+
fail-fast: false
|
|
113
|
+
matrix:
|
|
114
|
+
langgraph-version: ['0.1', '0.2']
|
|
115
|
+
env:
|
|
116
|
+
ROOTSIGN_SKIP_DB_BOOTSTRAP: '1'
|
|
117
|
+
steps:
|
|
118
|
+
- uses: actions/checkout@v5
|
|
119
|
+
- uses: actions/setup-python@v6
|
|
120
|
+
with:
|
|
121
|
+
python-version: '3.12'
|
|
122
|
+
- name: Install with langgraph extra
|
|
123
|
+
run: pip install -e '.[dev,langgraph]' "langgraph~=${{ matrix.langgraph-version }}"
|
|
124
|
+
- name: Contract tests
|
|
125
|
+
run: pytest tests/contract/langgraph/ -v
|
|
126
|
+
|
|
127
|
+
framework-contract-crewai:
|
|
128
|
+
# ADR-005 / Sprint 3: framework contract tests for CrewAI are MANDATORY —
|
|
129
|
+
# this job must pass on every PR before merge. Same pattern as the
|
|
130
|
+
# langgraph job above: mock IngestClient, no DB, ROOTSIGN_SKIP_DB_BOOTSTRAP.
|
|
131
|
+
#
|
|
132
|
+
# Sprint 4 (S4-TASK 10): added '1.0' to lock the duck-typing strategy
|
|
133
|
+
# against the 1.x line ahead of the Show HN post. Local run against
|
|
134
|
+
# crewai 1.6.1 had all 13 contract tests green — the ADR-005
|
|
135
|
+
# heuristic (name + _run callable) survives 1.x's BaseTool refactor
|
|
136
|
+
# because we never imported the class, only the shape.
|
|
137
|
+
name: CrewAI contract (crewai ~=${{ matrix.crewai-version }})
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
strategy:
|
|
140
|
+
fail-fast: false
|
|
141
|
+
matrix:
|
|
142
|
+
crewai-version: ['0.28', '0.40', '1.0']
|
|
143
|
+
env:
|
|
144
|
+
ROOTSIGN_SKIP_DB_BOOTSTRAP: '1'
|
|
145
|
+
steps:
|
|
146
|
+
- uses: actions/checkout@v5
|
|
147
|
+
- uses: actions/setup-python@v6
|
|
148
|
+
with:
|
|
149
|
+
python-version: '3.12'
|
|
150
|
+
- name: Install with crewai extra
|
|
151
|
+
run: pip install -e '.[dev,crewai]' "crewai~=${{ matrix.crewai-version }}"
|
|
152
|
+
- name: Contract tests
|
|
153
|
+
run: pytest tests/contract/crewai/ -v
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
env/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
dist/
|
|
12
|
+
build/
|
|
13
|
+
.eggs/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
.coverage.*
|
|
17
|
+
htmlcov/
|
|
18
|
+
coverage.xml
|
|
19
|
+
.tox/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.ruff_cache/
|
|
22
|
+
.dmypy.json
|
|
23
|
+
.env
|
|
24
|
+
.env.local
|
|
25
|
+
.idea/
|
|
26
|
+
# .vscode: gitignore everything except shared workspace files
|
|
27
|
+
.vscode/*
|
|
28
|
+
!.vscode/settings.json
|
|
29
|
+
!.vscode/extensions.json
|
|
30
|
+
!.vscode/tasks.json
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
.DS_Store
|
|
34
|
+
*.log
|
|
35
|
+
pip-log.txt
|
|
36
|
+
pip-delete-this-directory.txt
|
|
37
|
+
.python-version
|
|
38
|
+
|
|
39
|
+
# Confidential coding-agent sprint briefings (per CLAUDE.md / memory
|
|
40
|
+
# feedback_never_commit_internal_specs). These are dropped into the
|
|
41
|
+
# repo root for the coding agent to READ but must NEVER be committed.
|
|
42
|
+
# Memory reference: feedback_never_commit_internal_specs.md.
|
|
43
|
+
AGENTS_Phase*.md
|
|
44
|
+
AGENTS_PRD*.md
|
|
45
|
+
RootSign_Phase*.docx
|
|
46
|
+
RootSign_Phase*.md
|
|
47
|
+
RootSign_PRD*.docx
|
|
48
|
+
RootSign_PRD*.md
|
|
49
|
+
ProvidexAI_Phase*.docx
|
|
50
|
+
ProvidexAI_Phase*.md
|
|
51
|
+
ProvidexAI_PRD*.docx
|
|
52
|
+
ProvidexAI_PRD*.md
|
|
53
|
+
|
|
54
|
+
# Code-quality / security review artifacts the founder runs locally.
|
|
55
|
+
# Track them in a private notes location, not in-tree.
|
|
56
|
+
rootsign_review.md
|
|
57
|
+
|
|
58
|
+
# Local-only memory backups and ephemeral sample files dropped into the
|
|
59
|
+
# repo root for the coding agent to read during a session. See CLAUDE.md
|
|
60
|
+
# top section. MEMORY.md is the working memory index — never committed.
|
|
61
|
+
MEMORY.md
|
|
62
|
+
MEMORY_*.md
|
|
63
|
+
Sample_*.md
|
|
64
|
+
Sample_*.py
|
|
65
|
+
Sample_*.docx
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
|
|
3
|
+
"python.testing.pytestEnabled": true,
|
|
4
|
+
"python.testing.unittestEnabled": false,
|
|
5
|
+
"python.testing.pytestArgs": ["tests"],
|
|
6
|
+
"[python]": {
|
|
7
|
+
"editor.defaultFormatter": "charliermarsh.ruff"
|
|
8
|
+
}
|
|
9
|
+
}
|
rootsign-0.1.1/CLA.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# RootSign Contributor License Agreement
|
|
2
|
+
|
|
3
|
+
By signing this agreement, you (the Contributor) grant Providex AI Inc. (the Project) a perpetual, worldwide, non-exclusive, royalty-free license to use, reproduce, modify, distribute, and sublicense your Contributions as part of the Project.
|
|
4
|
+
|
|
5
|
+
You confirm that:
|
|
6
|
+
|
|
7
|
+
1. You have the legal right to grant this license.
|
|
8
|
+
2. Your Contribution is your original work, or you have sufficient rights to submit it.
|
|
9
|
+
3. You understand the Project may relicense your Contribution under other terms in the future, including commercial licenses.
|
|
10
|
+
|
|
11
|
+
You retain copyright ownership of your Contributions.
|
|
12
|
+
|
|
13
|
+
This agreement does not affect your ability to use your own Contributions for any purpose.
|
|
14
|
+
|
|
15
|
+
**To sign:** comment `I have read the CLA Document and I hereby sign the CLA` on any pull request. The CLA Assistant bot will record your signature.
|
rootsign-0.1.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## NEVER commit or push project/sprint artifacts
|
|
6
|
+
|
|
7
|
+
Sprint plans, agent guides, internal audits, memory snapshots, and similar working documents **must stay local**. They are gitignored as a backstop, but the rule is the rule regardless of whether `.gitignore` catches a given filename:
|
|
8
|
+
|
|
9
|
+
- `AGENTS*.md`, `AGENTS_Phase*.md`, `RootSign_Phase*.{md,docx}`, `ProvidexAI_Phase*.{md,docx}`
|
|
10
|
+
- `MEMORY.md` and anything under a `memory/` directory
|
|
11
|
+
- `rootsign_review.md` and other founder-run audit artifacts
|
|
12
|
+
|
|
13
|
+
If a new artifact like this gets created during a session, treat it as local-only by default. Do not `git add`, do not stage, do not include in commits. If a `git add -A` / `git add .` would sweep one in, switch to per-file staging. If a similar file pattern appears that isn't already gitignored, add the pattern to `.gitignore` in the same change.
|
|
14
|
+
|
|
15
|
+
**Why:** these documents contain unreleased product strategy, audit findings, and pre-decision context. A Sprint 4 history-rewrite was needed once to scrub an accidentally-tracked sprint plan — the gitignore patterns added in commit 128cec5 exist as a mechanical backstop. The rule is to never need that backstop.
|
|
16
|
+
|
|
17
|
+
## Where the code actually lives
|
|
18
|
+
|
|
19
|
+
The Python project is `phase0/` (this directory). The parent `turbo/` is just a workspace wrapper. All paths below are relative to `phase0/`.
|
|
20
|
+
|
|
21
|
+
## Dev environment
|
|
22
|
+
|
|
23
|
+
CONTRIBUTING.md has the full setup. The non-obvious bits:
|
|
24
|
+
|
|
25
|
+
- **Always run `python -m pytest`, never bare `pytest`.** A brew-installed `pytest` shadows the venv binary and silently runs under the system interpreter — produces `ModuleNotFoundError: sqlalchemy` and similar.
|
|
26
|
+
- **Even unit tests need a running database.** `tests/conftest.py` has a session-scoped `_bootstrap_test_db` fixture that runs alembic before any test collection. Start the DB first: `rootsign-admin start-db` (or `docker-compose up -d db` in-repo).
|
|
27
|
+
- **Schema bootstrap:** `rootsign-admin init` applies migrations. Idempotent. `--reset` drops and recreates the public schema (no confirmation prompt — be careful).
|
|
28
|
+
- **Single test:** `python -m pytest tests/integration/test_show_hn_quickstart.py::TestShowHNQuickstart::test_readme_quickstart_end_to_end -v`
|
|
29
|
+
- **Test markers:** `integration` and `benchmark` are declared in `pyproject.toml`. Performance suite at `tests/performance/` is opt-in via `-m benchmark`.
|
|
30
|
+
- **Coverage gate:** `fail_under = 85` in `pyproject.toml`. CI enforces it. New code expected at ≥90% per CONTRIBUTING.
|
|
31
|
+
- **Lint:** `ruff check .` and `ruff format .` before pushing.
|
|
32
|
+
|
|
33
|
+
## Two CLIs — do not flip them
|
|
34
|
+
|
|
35
|
+
Naming is locked (sprint plan Flag, do not re-derive):
|
|
36
|
+
|
|
37
|
+
| Surface | Entry point | Commands |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **User CLI** `rootsign` | `rootsign.sdk.cli:app` | `verify`, `approve`, `approve --list` |
|
|
40
|
+
| **Operator CLI** `rootsign-admin` | `rootsign.cli:app` | `start-db`, `stop-db`, `init`, `status` |
|
|
41
|
+
|
|
42
|
+
`rootsign approve <id>` is a developer workflow on the user CLI. `rootsign-admin replay-pending` (when it lands) is a privileged schema-level operation on the operator CLI. Decorator is `@rootsign.trace`, never `@providex.trace`. Package is `rootsign`, never `providex`.
|
|
43
|
+
|
|
44
|
+
## Big-picture architecture
|
|
45
|
+
|
|
46
|
+
**Hash chain (per-session, tamper-evident).** Each `Action` row carries `prev_action_hash` linking to the previous action in its session. `compute_action_self_hash` in `rootsign/hashing.py` is the **frozen canonical spec** — ADR-001 governs it, and CONTRIBUTING refuses to merge changes without a new ADR. Never re-implement it (the local-verify path got this wrong once and silently broke; see commit 128cec5). `self_hash` deliberately excludes `input_redacted`/`output_redacted` — the chain proves hash integrity, not payload-to-hash binding (an open pre-Phase-2 audit item).
|
|
47
|
+
|
|
48
|
+
**Ingest path.** SDK constructs an envelope → `IngestClient.handle(envelope)` → `IngestHandler` validates and routes by `event_type` → CRUD writes. `LocalIngestClient` is the in-process v0.1.0 path. `HttpIngestClient` is the Phase 2 hosted-backend path. Failure isolation rule (ADR-002): ingest **never raises into the decorated tool**; failures log at WARNING and the tool returns normally.
|
|
49
|
+
|
|
50
|
+
**HiTL checkpoint (ADR-007 — locked design).** `require_approval=True` on `@rootsign.trace` inserts an `ACTION_RECORD` with `authorization_status='pending'` and a reserved sequence number at submission time, then waits on `HiTLCheckpoint` (async poll loop). On approval: tool runs. Timeout: status becomes `'timed_out'` (terminal, distinct from `'human_rejected'`) and an Approval row is written with `approver_type='timeout_auto_rejected'`. **APPROVAL_RECORD rows are NOT in the hash chain** — they're a separate entity queried independently. The poll loop opens its own `AsyncSession` per cycle (`session_factory=AsyncSessionLocal`), never the caller's.
|
|
51
|
+
|
|
52
|
+
**Storage.** PostgreSQL 16 + TimescaleDB 2.x. The `actions` table is a **hypertable partitioned by `timestamp`**, which has hard consequences for any code joining against it (see below).
|
|
53
|
+
|
|
54
|
+
**Migrations.** Live in `rootsign/_migrations/` so they ship inside the wheel. `rootsign-admin init` resolves the directory via `importlib.resources.files("rootsign") / "_migrations"` and builds `alembic.config.Config` programmatically — no `alembic.ini` lookup, no cwd assumption. Developers running `alembic` directly from repo root work via the root-level `alembic.ini` whose `script_location` points at the same directory.
|
|
55
|
+
|
|
56
|
+
## Test invariants (binding rules)
|
|
57
|
+
|
|
58
|
+
These were locked in the Sprint 3/4 plans because each one traces to a specific incident. Audit any new SDK or test code against them.
|
|
59
|
+
|
|
60
|
+
1. **`_emit_action_record` and `_emit_approval_record` are keyword-only.** No positional args.
|
|
61
|
+
2. **AsyncSession loop binding:**
|
|
62
|
+
- Tool calls in async tests use `await tool.ainvoke({...})` — never `tool._run(...)` or sync `tool.invoke(...)`.
|
|
63
|
+
- CLI tests in async use `await asyncio.to_thread(runner.invoke, app, [...])` — never bare `runner.invoke(...)`. Typer's runner does `asyncio.run()` internally and crashes inside an already-running loop.
|
|
64
|
+
3. **`seeded_agent` (commits) for HiTL / CLI / `asyncio.to_thread` tests.** `registered_agent` uses SAVEPOINT rollback — its data is invisible to the poll loop's per-cycle session, the `to_thread` CLI runner, and the timeout recorder.
|
|
65
|
+
4. **HiTL design is locked (ADR-007).** Don't re-derive it in code.
|
|
66
|
+
5. **Hypertable-safe Action lookups.** Single-column `action_id` lookups are forbidden. Two valid two-column forms:
|
|
67
|
+
- `(action_id, action_timestamp)` — canonical chain-link form (`CRUDApproval.create_with_chain_link`, HiTL CLI / poll-loop paths). Prunes chunks on the partition column.
|
|
68
|
+
- `(session_id, action_id)` — `CRUDApproval.create_with_action_status_update` (ingest path). `ApprovalRecordPayload` doesn't carry `action_timestamp`; switching would require an envelope-schema bump.
|
|
69
|
+
6. **`tests/integration/test_show_hn_quickstart.py` is the launch gate.** It mirrors the README's LangGraph quickstart end-to-end (register → instrument → verify) and must stay green.
|
|
70
|
+
|
|
71
|
+
## What's deliberately orphaned
|
|
72
|
+
|
|
73
|
+
- **`_emit_approval_record`** in `rootsign/sdk/decorator.py` has zero call sites in `rootsign/`. It's a Phase 2 hook for when `HttpIngestClient` lands — the v0.1.0 HiTL CLI writes APPROVAL_RECORD rows directly via `CRUDApproval.create_with_chain_link` (single source of truth). Re-emitting via the IngestClient path would hit the terminal-state guard and warn for no semantic gain. The marker comment above the def points at this; don't delete the helper or its tests.
|
|
74
|
+
|
|
75
|
+
## Authoritative context
|
|
76
|
+
|
|
77
|
+
When changing anything in the SDK, HiTL, or hashing paths:
|
|
78
|
+
|
|
79
|
+
- `docs/adr/ADR-001` — canonical hash spec (frozen)
|
|
80
|
+
- `docs/adr/ADR-002` — ingest failure isolation
|
|
81
|
+
- `docs/adr/ADR-006` — redaction contract
|
|
82
|
+
- `docs/adr/ADR-007` — HiTL checkpoint design
|
|
83
|
+
- `AGENTS_Phase1_Sprint4.md` — sprint plan with naming contract, six binding flags, ADR-007 summary, the launch review checklist. **Gitignored**, so absent from fresh clones; it's a working doc for whoever's driving the sprint.
|
|
84
|
+
- `rootsign_review.md` — pre-launch audit findings. Also gitignored. High-severity items were fixed in commit 128cec5; the remainder is the Pre-Phase-2 backlog (concurrency on approvals, payload→hash binding at verify, HiTL classification edge cases, CLI polish).
|
|
85
|
+
|
|
86
|
+
## Conventions
|
|
87
|
+
|
|
88
|
+
- **Commits:** `type(scope): short description` (see CONTRIBUTING). Recent history matches: `fix(packaging):`, `fix(security):`, `feat(sdk):`, `docs:`. Body explains *why*, references file:line, and includes a `Co-Authored-By` trailer when relevant.
|
|
89
|
+
- **Branches:** `feat/`, `fix/`, `test/`, `docs/` prefixes.
|
|
90
|
+
- **Hard "no":** mock-based integration tests (real PG+TimescaleDB only), sync SQLAlchemy outside Alembic, changing `compute_action_self_hash` without a new ADR, silently swallowing ingest failures (must log at WARNING), committing/pushing project or sprint artifacts (see top section).
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Contributing to RootSign
|
|
2
|
+
|
|
3
|
+
## Welcome
|
|
4
|
+
|
|
5
|
+
RootSign is the open-source agent capture layer of the Providex AI Agent Accountability Platform. We welcome contributions of all kinds: bug fixes, documentation improvements, new framework integrations, and test coverage.
|
|
6
|
+
|
|
7
|
+
## Before you contribute
|
|
8
|
+
|
|
9
|
+
- **Code of Conduct.** RootSign adopts the [Contributor Covenant v2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) as its code of conduct. By participating in this project (issues, PRs, discussions, Discord), you agree to uphold its standards. Report unacceptable behavior to `info@getprovidex.com`.
|
|
10
|
+
- Sign the [CLA](CLA.md) (automated — you'll be prompted on your first PR)
|
|
11
|
+
- Check the issue tracker for existing discussion before opening a new issue
|
|
12
|
+
|
|
13
|
+
## Development setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/Providex-AI/rootsign
|
|
17
|
+
cd rootsign
|
|
18
|
+
pip install -e '.[dev]' # installs dev + test deps
|
|
19
|
+
docker-compose up -d db # PostgreSQL + TimescaleDB
|
|
20
|
+
rootsign-admin init # alembic upgrade head
|
|
21
|
+
python -m pytest tests/unit/ -v # unit tests (no DB needed at runtime — see note)
|
|
22
|
+
python -m pytest tests/integration/ -v # integration tests (needs DB)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> **Python:** RootSign requires Python 3.11 or 3.12. We do not support 3.10 or below.
|
|
26
|
+
>
|
|
27
|
+
> The package's `requires-python` is `>=3.11,<3.15`, but the `[crewai]` extra currently lacks wheels for 3.13/3.14 so installs of `'.[crewai]'` on those versions fail with `No matching distribution found`. Bump the recommendation only after upstream ships matching wheels.
|
|
28
|
+
>
|
|
29
|
+
> **Always invoke pytest as `python -m pytest`.** If you `brew install`-ed pytest, the system binary will resolve ahead of the venv's pytest on PATH and run under the system Python — which does not see your venv's site-packages and will fail with confusing `ModuleNotFoundError` (typically on `sqlalchemy` first). `python -m pytest` always uses the venv's interpreter.
|
|
30
|
+
>
|
|
31
|
+
> **Note on unit tests:** The session-scoped `_bootstrap_test_db` fixture in `tests/conftest.py` runs alembic against the test DB before any test (including unit tests). Bring `docker-compose up -d db` up first.
|
|
32
|
+
|
|
33
|
+
## Branch naming
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
feat/[short-description] # new feature
|
|
37
|
+
fix/[short-description] # bug fix
|
|
38
|
+
test/[short-description] # test additions
|
|
39
|
+
docs/[short-description] # documentation only
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Commit message format
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
type(scope): short description
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
```
|
|
50
|
+
feat(sdk): add CrewAI tool wrapper
|
|
51
|
+
fix(hashing): correct canonical field order
|
|
52
|
+
test(crud): add verify_chain corruption test
|
|
53
|
+
docs(adr): add ADR-004 for retry strategy
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Pull request requirements
|
|
57
|
+
|
|
58
|
+
- All existing tests must pass: `pytest tests/ -v`
|
|
59
|
+
- New code must have test coverage >= 90%
|
|
60
|
+
- Overall coverage must not drop below 85% (enforced by `fail_under = 85` in `pyproject.toml`)
|
|
61
|
+
- No breaking changes to the canonical hash spec without a new ADR (see [ADR-001](docs/adr/ADR-001-hash-canonical-spec.md))
|
|
62
|
+
- Framework integrations must pass contract tests on all supported framework versions (see CI matrix)
|
|
63
|
+
- Run `ruff check .` and `ruff format .` before pushing
|
|
64
|
+
|
|
65
|
+
## What we will NOT merge
|
|
66
|
+
|
|
67
|
+
- Changes to `compute_action_self_hash` canonical spec (see [ADR-001](docs/adr/ADR-001-hash-canonical-spec.md)) without a new ADR approved by the maintainer
|
|
68
|
+
- Synchronous SQLAlchemy in any non-Alembic code
|
|
69
|
+
- Mock-based integration tests (real PostgreSQL + TimescaleDB only — see [the data model rationale](AGENTS.md))
|
|
70
|
+
- Any PR that reduces test coverage below 85% overall
|
|
71
|
+
- Code that swallows ingest failures silently (RootSign's promise is that ingest never raises into the agent, but failures *must* be logged at WARNING level — see [ADR-002](docs/adr/ADR-002-transport-agnostic-client.md))
|
|
72
|
+
|
|
73
|
+
## Adding a new framework integration
|
|
74
|
+
|
|
75
|
+
1. Open a `framework_integration` issue first so we can discuss API surface and version targets
|
|
76
|
+
2. Copy the LangGraph integration as a reference (lands in Sprint 2)
|
|
77
|
+
3. Implement contract tests against a minimum of two framework versions (latest stable + previous minor) — see [ADR-003](docs/adr/ADR-003-framework-contract-tests.md)
|
|
78
|
+
4. Update `docs/framework-support.md` (created in Sprint 2)
|
|
79
|
+
|
|
80
|
+
## Questions?
|
|
81
|
+
|
|
82
|
+
Open a [GitHub Discussion](https://github.com/Providex-AI/rootsign/discussions). A `#rootsign` channel on the LangChain Discord is coming alongside Sprint 2.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Contributors
|
|
2
|
+
|
|
3
|
+
Thank you to everyone who has contributed to RootSign.
|
|
4
|
+
|
|
5
|
+
## Maintainers
|
|
6
|
+
|
|
7
|
+
- Olasile Abolade ([@oabolade](https://github.com/oabolade)) — Founder, Providex AI
|
|
8
|
+
|
|
9
|
+
## Contributors
|
|
10
|
+
|
|
11
|
+
*Your name here (@your-github-handle) — one line description of what you worked on*
|