gabion 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.
- gabion-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- gabion-0.1.0/.github/ISSUE_TEMPLATE/sppf-node.yml +76 -0
- gabion-0.1.0/.github/actions/gabion/README.md +30 -0
- gabion-0.1.0/.github/actions/gabion/action.yml +40 -0
- gabion-0.1.0/.github/actions/gabion/run.sh +27 -0
- gabion-0.1.0/.github/workflows/ci.yml +63 -0
- gabion-0.1.0/.github/workflows/pr-dataflow-grammar.yml +113 -0
- gabion-0.1.0/.github/workflows/release-test.yml +34 -0
- gabion-0.1.0/.github/workflows/release.yml +32 -0
- gabion-0.1.0/.gitignore +11 -0
- gabion-0.1.0/AGENTS.md +66 -0
- gabion-0.1.0/CONTRIBUTING.md +289 -0
- gabion-0.1.0/LICENSE +190 -0
- gabion-0.1.0/Makefile +34 -0
- gabion-0.1.0/PKG-INFO +250 -0
- gabion-0.1.0/POLICY_SEED.md +452 -0
- gabion-0.1.0/README.md +223 -0
- gabion-0.1.0/artifacts/.gitkeep +0 -0
- gabion-0.1.0/docs/allowed_actions.txt +7 -0
- gabion-0.1.0/docs/doer_judge_witness.md +49 -0
- gabion-0.1.0/docs/pinning_actions.md +52 -0
- gabion-0.1.0/docs/publishing_practices.md +83 -0
- gabion-0.1.0/docs/sppf_checklist.md +138 -0
- gabion-0.1.0/docs/synthesis_payload.md +71 -0
- gabion-0.1.0/docs/workflows/gabion_action_example.yml +19 -0
- gabion-0.1.0/extensions/vscode/README.md +24 -0
- gabion-0.1.0/extensions/vscode/extension.js +83 -0
- gabion-0.1.0/extensions/vscode/package.json +54 -0
- gabion-0.1.0/gabion.toml +4 -0
- gabion-0.1.0/glossary.md +221 -0
- gabion-0.1.0/in/AGENTS.md +21 -0
- gabion-0.1.0/in/CONTRIBUTING.md +86 -0
- gabion-0.1.0/in/README.md +206 -0
- gabion-0.1.0/in/ci-milestones.yml +542 -0
- gabion-0.1.0/in/dataflow_grammar_audit.py +1083 -0
- gabion-0.1.0/in/in-1.md +74 -0
- gabion-0.1.0/in/in-10.md +266 -0
- gabion-0.1.0/in/in-11.md +266 -0
- gabion-0.1.0/in/in-12.md +236 -0
- gabion-0.1.0/in/in-13.md +161 -0
- gabion-0.1.0/in/in-14.md +83 -0
- gabion-0.1.0/in/in-2.md +57 -0
- gabion-0.1.0/in/in-3.md +37 -0
- gabion-0.1.0/in/in-4.md +272 -0
- gabion-0.1.0/in/in-5.md +78 -0
- gabion-0.1.0/in/in-6.md +172 -0
- gabion-0.1.0/in/in-7.md +725 -0
- gabion-0.1.0/in/in-8.md +203 -0
- gabion-0.1.0/in/in-9.md +474 -0
- gabion-0.1.0/in/inspiration.md +1475 -0
- gabion-0.1.0/in/policy_check.py +344 -0
- gabion-0.1.0/in/pr-dataflow-grammar.yml +78 -0
- gabion-0.1.0/mise.toml +2 -0
- gabion-0.1.0/pyproject.toml +41 -0
- gabion-0.1.0/pytest.ini +2 -0
- gabion-0.1.0/scripts/audit_snapshot.sh +45 -0
- gabion-0.1.0/scripts/bootstrap.sh +15 -0
- gabion-0.1.0/scripts/checks.sh +50 -0
- gabion-0.1.0/scripts/clean_artifacts.sh +12 -0
- gabion-0.1.0/scripts/dataflow_grammar_audit.py +21 -0
- gabion-0.1.0/scripts/docflow_audit.py +222 -0
- gabion-0.1.0/scripts/install_hooks.sh +47 -0
- gabion-0.1.0/scripts/latest_snapshot.sh +52 -0
- gabion-0.1.0/scripts/lsp_smoke_test.py +50 -0
- gabion-0.1.0/scripts/pin_actions.py +128 -0
- gabion-0.1.0/scripts/policy_check.py +428 -0
- gabion-0.1.0/scripts/run_tests.sh +16 -0
- gabion-0.1.0/scripts/sppf_sync.py +142 -0
- gabion-0.1.0/src/gabion/__init__.py +5 -0
- gabion-0.1.0/src/gabion/__main__.py +11 -0
- gabion-0.1.0/src/gabion/analysis/__init__.py +37 -0
- gabion-0.1.0/src/gabion/analysis/dataflow_audit.py +3173 -0
- gabion-0.1.0/src/gabion/analysis/engine.py +8 -0
- gabion-0.1.0/src/gabion/analysis/model.py +45 -0
- gabion-0.1.0/src/gabion/analysis/visitors.py +402 -0
- gabion-0.1.0/src/gabion/cli.py +503 -0
- gabion-0.1.0/src/gabion/config.py +45 -0
- gabion-0.1.0/src/gabion/lsp_client.py +111 -0
- gabion-0.1.0/src/gabion/refactor/__init__.py +4 -0
- gabion-0.1.0/src/gabion/refactor/engine.py +726 -0
- gabion-0.1.0/src/gabion/refactor/model.py +37 -0
- gabion-0.1.0/src/gabion/schema.py +84 -0
- gabion-0.1.0/src/gabion/server.py +447 -0
- gabion-0.1.0/src/gabion/synthesis/__init__.py +26 -0
- gabion-0.1.0/src/gabion/synthesis/merge.py +41 -0
- gabion-0.1.0/src/gabion/synthesis/model.py +41 -0
- gabion-0.1.0/src/gabion/synthesis/naming.py +45 -0
- gabion-0.1.0/src/gabion/synthesis/protocols.py +74 -0
- gabion-0.1.0/src/gabion/synthesis/schedule.py +87 -0
- gabion-0.1.0/tests/test_alias_attribute.py +77 -0
- gabion-0.1.0/tests/test_alias_rename_invariance.py +76 -0
- gabion-0.1.0/tests/test_alias_unpacking.py +46 -0
- gabion-0.1.0/tests/test_baseline_ratchet.py +27 -0
- gabion-0.1.0/tests/test_class_method_propagation.py +86 -0
- gabion-0.1.0/tests/test_code_action_stub.py +31 -0
- gabion-0.1.0/tests/test_config_declarations_anywhere.py +70 -0
- gabion-0.1.0/tests/test_config_defaults.py +60 -0
- gabion-0.1.0/tests/test_config_fields.py +36 -0
- gabion-0.1.0/tests/test_dataclass_call_bundles.py +73 -0
- gabion-0.1.0/tests/test_decorator_transparency.py +81 -0
- gabion-0.1.0/tests/test_import_shadowing.py +65 -0
- gabion-0.1.0/tests/test_lsp_smoke.py +42 -0
- gabion-0.1.0/tests/test_nested_resolution.py +47 -0
- gabion-0.1.0/tests/test_param_spans.py +50 -0
- gabion-0.1.0/tests/test_refactor_engine.py +181 -0
- gabion-0.1.0/tests/test_refactor_plan.py +49 -0
- gabion-0.1.0/tests/test_star_import_resolution.py +100 -0
- gabion-0.1.0/tests/test_synthesis_merge.py +26 -0
- gabion-0.1.0/tests/test_synthesis_merge_integration.py +30 -0
- gabion-0.1.0/tests/test_synthesis_naming.py +27 -0
- gabion-0.1.0/tests/test_synthesis_protocols.py +40 -0
- gabion-0.1.0/tests/test_synthesis_schedule.py +28 -0
- gabion-0.1.0/tests/test_synthesis_stubs.py +54 -0
- gabion-0.1.0/tests/test_synthesis_tiers.py +55 -0
- gabion-0.1.0/tests/test_synthesis_types.py +142 -0
- gabion-0.1.0/tests/test_unused_arg_audit.py +92 -0
- gabion-0.1.0/tests/test_wildcard_forwarding.py +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: "SPPF node"
|
|
2
|
+
description: "Track a node from docs/sppf_checklist.md"
|
|
3
|
+
title: "[SPPF] <node>"
|
|
4
|
+
labels:
|
|
5
|
+
- "sppf-node"
|
|
6
|
+
- "planning"
|
|
7
|
+
body:
|
|
8
|
+
- type: markdown
|
|
9
|
+
attributes:
|
|
10
|
+
value: |
|
|
11
|
+
Use this form to track an item from `docs/sppf_checklist.md`.
|
|
12
|
+
Paste the exact checklist line so the linkage is unambiguous.
|
|
13
|
+
- type: input
|
|
14
|
+
id: checklist_entry
|
|
15
|
+
attributes:
|
|
16
|
+
label: Checklist entry
|
|
17
|
+
description: Paste the exact checklist line (including [ ] or [~]).
|
|
18
|
+
placeholder: "- [ ] Refactor engine: Signature rewriting (def foo(a, b) -> def foo(bundle))."
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: input
|
|
22
|
+
id: checklist_section
|
|
23
|
+
attributes:
|
|
24
|
+
label: Checklist section
|
|
25
|
+
description: Section header containing the entry (e.g., "Phase 3: Refactoring & UX").
|
|
26
|
+
placeholder: "Phase 3: Refactoring & UX"
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: dropdown
|
|
30
|
+
id: status
|
|
31
|
+
attributes:
|
|
32
|
+
label: Status
|
|
33
|
+
options:
|
|
34
|
+
- planned
|
|
35
|
+
- partial/heuristic
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
- type: input
|
|
39
|
+
id: dependencies
|
|
40
|
+
attributes:
|
|
41
|
+
label: Dependencies
|
|
42
|
+
description: Related issues or prerequisites (optional).
|
|
43
|
+
placeholder: "#123, #456"
|
|
44
|
+
validations:
|
|
45
|
+
required: false
|
|
46
|
+
- type: textarea
|
|
47
|
+
id: acceptance_criteria
|
|
48
|
+
attributes:
|
|
49
|
+
label: Acceptance criteria
|
|
50
|
+
description: What must be true for this node to be marked [x]?
|
|
51
|
+
placeholder: "List objective criteria and expected test evidence."
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
- type: textarea
|
|
55
|
+
id: test_plan
|
|
56
|
+
attributes:
|
|
57
|
+
label: Test plan
|
|
58
|
+
description: Tests or checks to validate completion (optional).
|
|
59
|
+
placeholder: "pytest tests/test_..."
|
|
60
|
+
validations:
|
|
61
|
+
required: false
|
|
62
|
+
- type: input
|
|
63
|
+
id: target_release
|
|
64
|
+
attributes:
|
|
65
|
+
label: Target release
|
|
66
|
+
description: Optional release tag or milestone.
|
|
67
|
+
placeholder: "v0.1.0-alpha"
|
|
68
|
+
validations:
|
|
69
|
+
required: false
|
|
70
|
+
- type: checkboxes
|
|
71
|
+
id: checklist_linkback
|
|
72
|
+
attributes:
|
|
73
|
+
label: Checklist linkage
|
|
74
|
+
options:
|
|
75
|
+
- label: "I will add the GH issue ID to the checklist entry after creation."
|
|
76
|
+
required: true
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Gabion Composite Action
|
|
2
|
+
|
|
3
|
+
This composite action installs and runs Gabion using the system Python.
|
|
4
|
+
|
|
5
|
+
### Inputs
|
|
6
|
+
- `version`: pip specifier (default: `gabion`)
|
|
7
|
+
- `command`: subcommand to run (default: `check`)
|
|
8
|
+
- `root`: project root (default: `.`)
|
|
9
|
+
- `config`: path to gabion config (optional)
|
|
10
|
+
- `report`: path to write a Markdown report (optional)
|
|
11
|
+
- `args`: extra CLI args (optional)
|
|
12
|
+
|
|
13
|
+
### Example
|
|
14
|
+
```yaml
|
|
15
|
+
name: gabion
|
|
16
|
+
on:
|
|
17
|
+
pull_request:
|
|
18
|
+
jobs:
|
|
19
|
+
gabion:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@<PINNED_SHA>
|
|
23
|
+
- uses: actions/setup-python@<PINNED_SHA>
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.11"
|
|
26
|
+
- uses: mikemol/gabion/.github/actions/gabion@<TAG_OR_SHA>
|
|
27
|
+
with:
|
|
28
|
+
command: "check"
|
|
29
|
+
args: "--fail-on-violations"
|
|
30
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: "Gabion"
|
|
2
|
+
description: "Run gabion check against a repository"
|
|
3
|
+
inputs:
|
|
4
|
+
version:
|
|
5
|
+
description: "Gabion version specifier for pip (default: gabion)"
|
|
6
|
+
required: false
|
|
7
|
+
default: "gabion"
|
|
8
|
+
command:
|
|
9
|
+
description: "Gabion subcommand to run (default: check)"
|
|
10
|
+
required: false
|
|
11
|
+
default: "check"
|
|
12
|
+
root:
|
|
13
|
+
description: "Project root for gabion (default: .)"
|
|
14
|
+
required: false
|
|
15
|
+
default: "."
|
|
16
|
+
config:
|
|
17
|
+
description: "Path to gabion.toml or config file"
|
|
18
|
+
required: false
|
|
19
|
+
default: ""
|
|
20
|
+
report:
|
|
21
|
+
description: "Path for Markdown report (optional)"
|
|
22
|
+
required: false
|
|
23
|
+
default: ""
|
|
24
|
+
args:
|
|
25
|
+
description: "Additional CLI args"
|
|
26
|
+
required: false
|
|
27
|
+
default: ""
|
|
28
|
+
runs:
|
|
29
|
+
using: "composite"
|
|
30
|
+
steps:
|
|
31
|
+
- name: Run Gabion
|
|
32
|
+
shell: bash
|
|
33
|
+
run: "${{ github.action_path }}/run.sh"
|
|
34
|
+
env:
|
|
35
|
+
GABION_VERSION: "${{ inputs.version }}"
|
|
36
|
+
GABION_COMMAND: "${{ inputs.command }}"
|
|
37
|
+
GABION_ROOT: "${{ inputs.root }}"
|
|
38
|
+
GABION_CONFIG: "${{ inputs.config }}"
|
|
39
|
+
GABION_REPORT: "${{ inputs.report }}"
|
|
40
|
+
GABION_ARGS: "${{ inputs.args }}"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if ! command -v python >/dev/null 2>&1; then
|
|
5
|
+
echo "python is required to run gabion" >&2
|
|
6
|
+
exit 2
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
python -m pip install --upgrade pip >/dev/null
|
|
10
|
+
python -m pip install "${GABION_VERSION}"
|
|
11
|
+
|
|
12
|
+
cmd=("${GABION_COMMAND}")
|
|
13
|
+
if [[ -n "${GABION_ROOT}" ]]; then
|
|
14
|
+
cmd+=("--root" "${GABION_ROOT}")
|
|
15
|
+
fi
|
|
16
|
+
if [[ -n "${GABION_CONFIG}" ]]; then
|
|
17
|
+
cmd+=("--config" "${GABION_CONFIG}")
|
|
18
|
+
fi
|
|
19
|
+
if [[ -n "${GABION_REPORT}" ]]; then
|
|
20
|
+
cmd+=("--report" "${GABION_REPORT}")
|
|
21
|
+
fi
|
|
22
|
+
if [[ -n "${GABION_ARGS}" ]]; then
|
|
23
|
+
# shellcheck disable=SC2206
|
|
24
|
+
cmd+=(${GABION_ARGS})
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
python -m gabion "${cmd[@]}"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- stage
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
audit:
|
|
17
|
+
if: github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/stage'
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
env:
|
|
20
|
+
MISE_TRUSTED_CONFIG_PATHS: ${{ github.workspace }}
|
|
21
|
+
steps:
|
|
22
|
+
# Allow-listed actions: actions/checkout, jdx/mise-action
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
25
|
+
- name: Install mise
|
|
26
|
+
uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8
|
|
27
|
+
- name: Install toolchain
|
|
28
|
+
run: mise install
|
|
29
|
+
- name: Install package
|
|
30
|
+
run: mise exec -- python -m pip install -e .
|
|
31
|
+
- name: Install test deps
|
|
32
|
+
run: mise exec -- python -m pip install pytest
|
|
33
|
+
- name: Policy check (workflows)
|
|
34
|
+
run: |
|
|
35
|
+
mise exec -- python -m pip install pyyaml
|
|
36
|
+
mise exec -- python scripts/policy_check.py --workflows
|
|
37
|
+
- name: Policy check (posture)
|
|
38
|
+
if: github.event_name == 'push'
|
|
39
|
+
env:
|
|
40
|
+
POLICY_GITHUB_TOKEN: ${{ secrets.POLICY_GITHUB_TOKEN }}
|
|
41
|
+
run: |
|
|
42
|
+
if [ -z "${POLICY_GITHUB_TOKEN:-}" ]; then
|
|
43
|
+
echo "POLICY_GITHUB_TOKEN not set; skipping posture check."
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
mise exec -- python scripts/policy_check.py --posture
|
|
47
|
+
- name: Dataflow audit
|
|
48
|
+
run: mise exec -- python -m gabion check
|
|
49
|
+
- name: Docflow audit
|
|
50
|
+
run: mise exec -- python scripts/docflow_audit.py --root . --fail-on-violations
|
|
51
|
+
- name: Tests
|
|
52
|
+
run: |
|
|
53
|
+
mkdir -p artifacts/test_runs
|
|
54
|
+
mise exec -- python -m pytest \
|
|
55
|
+
--junitxml artifacts/test_runs/junit.xml \
|
|
56
|
+
--log-file artifacts/test_runs/pytest.log \
|
|
57
|
+
--log-file-level=INFO
|
|
58
|
+
- name: Upload test artifacts
|
|
59
|
+
if: always()
|
|
60
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
|
61
|
+
with:
|
|
62
|
+
name: test-runs
|
|
63
|
+
path: artifacts/test_runs
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
name: pr-dataflow-grammar
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- "scripts/**"
|
|
7
|
+
- "src/**"
|
|
8
|
+
- "gabion.toml"
|
|
9
|
+
- ".github/workflows/pr-dataflow-grammar.yml"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
dataflow-grammar:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
pull-requests: write
|
|
20
|
+
env:
|
|
21
|
+
MISE_TRUSTED_CONFIG_PATHS: ${{ github.workspace }}
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
25
|
+
- name: Install mise
|
|
26
|
+
uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8
|
|
27
|
+
- name: Install toolchain
|
|
28
|
+
run: mise install
|
|
29
|
+
- name: Install package
|
|
30
|
+
run: mise exec -- python -m pip install -e .
|
|
31
|
+
- name: Render dataflow grammar report
|
|
32
|
+
run: |
|
|
33
|
+
mkdir -p artifacts/dataflow_grammar
|
|
34
|
+
mise exec -- python -m gabion dataflow-audit . \
|
|
35
|
+
--root . \
|
|
36
|
+
--report artifacts/dataflow_grammar/report.md \
|
|
37
|
+
--dot artifacts/dataflow_grammar/dataflow_graph.dot \
|
|
38
|
+
--type-audit-report
|
|
39
|
+
- name: Upload dataflow artifact
|
|
40
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
|
41
|
+
with:
|
|
42
|
+
name: dataflow-grammar
|
|
43
|
+
path: artifacts/dataflow_grammar
|
|
44
|
+
- name: Comment on PR with report
|
|
45
|
+
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
46
|
+
env:
|
|
47
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
48
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
49
|
+
REPO: ${{ github.repository }}
|
|
50
|
+
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
python - <<'PY'
|
|
54
|
+
import json
|
|
55
|
+
import os
|
|
56
|
+
import pathlib
|
|
57
|
+
import urllib.request
|
|
58
|
+
|
|
59
|
+
token = os.environ["GITHUB_TOKEN"]
|
|
60
|
+
repo = os.environ["REPO"]
|
|
61
|
+
issue = os.environ["PR_NUMBER"]
|
|
62
|
+
run_url = os.environ["RUN_URL"]
|
|
63
|
+
marker = "<!-- dataflow-grammar -->"
|
|
64
|
+
report_path = pathlib.Path("artifacts/dataflow_grammar/report.md")
|
|
65
|
+
if report_path.exists():
|
|
66
|
+
report = report_path.read_text()
|
|
67
|
+
else:
|
|
68
|
+
report = f"{marker}\nDataflow grammar report generated.\n"
|
|
69
|
+
if marker not in report:
|
|
70
|
+
report = f"{marker}\n{report}"
|
|
71
|
+
footer = f"\n\n- Artifact: dataflow-grammar\n- Download: {run_url}\n"
|
|
72
|
+
body = report + footer
|
|
73
|
+
if len(body) > 60000:
|
|
74
|
+
body = body[:60000] + "\n\n(truncated)\n" + footer
|
|
75
|
+
|
|
76
|
+
def request(url, method="GET", payload=None):
|
|
77
|
+
data = None if payload is None else json.dumps(payload).encode("utf-8")
|
|
78
|
+
req = urllib.request.Request(
|
|
79
|
+
url,
|
|
80
|
+
data=data,
|
|
81
|
+
headers={
|
|
82
|
+
"Authorization": f"Bearer {token}",
|
|
83
|
+
"Accept": "application/vnd.github+json",
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
},
|
|
86
|
+
method=method,
|
|
87
|
+
)
|
|
88
|
+
with urllib.request.urlopen(req) as resp:
|
|
89
|
+
return json.loads(resp.read().decode("utf-8"))
|
|
90
|
+
|
|
91
|
+
comments = []
|
|
92
|
+
page = 1
|
|
93
|
+
while True:
|
|
94
|
+
url = (
|
|
95
|
+
f"https://api.github.com/repos/{repo}/issues/{issue}/comments"
|
|
96
|
+
f"?per_page=100&page={page}"
|
|
97
|
+
)
|
|
98
|
+
batch = request(url)
|
|
99
|
+
if not batch:
|
|
100
|
+
break
|
|
101
|
+
comments.extend(batch)
|
|
102
|
+
page += 1
|
|
103
|
+
|
|
104
|
+
existing = next(
|
|
105
|
+
(c for c in comments if marker in (c.get("body") or "")),
|
|
106
|
+
None,
|
|
107
|
+
)
|
|
108
|
+
if existing:
|
|
109
|
+
request(existing["url"], method="PATCH", payload={"body": body})
|
|
110
|
+
else:
|
|
111
|
+
url = f"https://api.github.com/repos/{repo}/issues/{issue}/comments"
|
|
112
|
+
request(url, method="POST", payload={"body": body})
|
|
113
|
+
PY
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: release-test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "test-v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: testpypi
|
|
17
|
+
url: https://test.pypi.org/project/gabion/
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11"
|
|
25
|
+
- name: Build artifacts
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
python -m pip install build twine
|
|
29
|
+
python -m build
|
|
30
|
+
python -m twine check dist/*
|
|
31
|
+
- name: Publish to TestPyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
|
|
33
|
+
with:
|
|
34
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/project/gabion/
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.11"
|
|
25
|
+
- name: Build artifacts
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
python -m pip install build twine
|
|
29
|
+
python -m build
|
|
30
|
+
python -m twine check dist/*
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e
|
gabion-0.1.0/.gitignore
ADDED
gabion-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc_revision: 9
|
|
3
|
+
reader_reintern: "Reader-only: re-intern if doc_revision changed since you last read this doc."
|
|
4
|
+
doc_id: agents
|
|
5
|
+
doc_role: agent
|
|
6
|
+
doc_scope:
|
|
7
|
+
- repo
|
|
8
|
+
- agents
|
|
9
|
+
- tooling
|
|
10
|
+
doc_authority: normative
|
|
11
|
+
doc_requires:
|
|
12
|
+
- README.md
|
|
13
|
+
- CONTRIBUTING.md
|
|
14
|
+
- POLICY_SEED.md
|
|
15
|
+
- glossary.md
|
|
16
|
+
doc_change_protocol: "POLICY_SEED.md §6"
|
|
17
|
+
doc_invariants:
|
|
18
|
+
- read_policy_glossary_first
|
|
19
|
+
- refuse_on_conflict
|
|
20
|
+
- tier2_reification
|
|
21
|
+
- tier3_documentation
|
|
22
|
+
- lsp_first_invariant
|
|
23
|
+
doc_erasure:
|
|
24
|
+
- formatting
|
|
25
|
+
- typos
|
|
26
|
+
doc_owner: maintainer
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# AGENTS.md
|
|
30
|
+
|
|
31
|
+
This repository is governed by `POLICY_SEED.md`. Treat it as authoritative.
|
|
32
|
+
Semantic correctness is governed by `glossary.md` (co-equal contract).
|
|
33
|
+
|
|
34
|
+
## Cross-references (normative pointers)
|
|
35
|
+
- `README.md` defines project scope, status, and entry points.
|
|
36
|
+
- `CONTRIBUTING.md` defines human+machine workflow guardrails.
|
|
37
|
+
- `POLICY_SEED.md` defines execution and CI safety constraints.
|
|
38
|
+
- `glossary.md` defines semantic meanings, axes, and commutation obligations.
|
|
39
|
+
|
|
40
|
+
## Required behavior
|
|
41
|
+
- Read `POLICY_SEED.md` and `glossary.md` before proposing or applying changes.
|
|
42
|
+
- If a request conflicts with `POLICY_SEED.md`, stop and ask for guidance.
|
|
43
|
+
- Do not weaken or bypass self-hosted runner protections.
|
|
44
|
+
- Keep workflow actions pinned to full commit SHAs and allow-listed.
|
|
45
|
+
- When changing workflows, run the policy checks (once the scripts exist) and
|
|
46
|
+
surface any violations explicitly.
|
|
47
|
+
- Preserve the LSP-first invariant: the server is the semantic core and the
|
|
48
|
+
CLI remains a thin LSP client.
|
|
49
|
+
- Use `mise exec -- python` for repo-local tooling to ensure the pinned
|
|
50
|
+
interpreter and dependencies are used.
|
|
51
|
+
- Treat docflow as repo-local convenience only; do not project it as a
|
|
52
|
+
general Gabion feature without explicit policy change.
|
|
53
|
+
|
|
54
|
+
## Dataflow grammar invariant
|
|
55
|
+
- Recurring parameter bundles are type-level obligations.
|
|
56
|
+
- Any bundle that crosses function boundaries must be promoted to a Protocol
|
|
57
|
+
(dataclass config/local bundle) or explicitly documented with a
|
|
58
|
+
`# dataflow-bundle:` marker.
|
|
59
|
+
- Tier-2 bundles must be reified before merge (see `glossary.md`).
|
|
60
|
+
- Tier-3 bundles must be documented or reified (see `glossary.md`).
|
|
61
|
+
|
|
62
|
+
## Doc hygiene
|
|
63
|
+
- Markdown docs include a YAML front-matter block with `doc_revision`.
|
|
64
|
+
- Bump `doc_revision` for conceptual changes.
|
|
65
|
+
|
|
66
|
+
If unsure, prefer refusal over unsafe compliance.
|