feat(loop): Phase 0-1 report-only Evidence-Gated Engineering Loop foundation - #7
Merged
Merged
Conversation
…ndation
B2 - Minimal integration in this harness, nothing above 'report' autonomy:
- protect_sensitive_files.py (template and plugin): deny agent writes to
'.loop/**' and 'scripts/loop_*', separate from the existing
secrets denylist, with its own message pointing at docs/LOOPS.md. This
is the mechanism that keeps loop_runner.py/loop_gate.py/loop_state.py
and .loop/ contents from being silently built ahead of schedule; only a
human editing outside of an agent tool call can populate them.
- template/scripts/_vendor_loop_schemas/: vendored copy of
engineering-loop-schemas' src/loop_schemas/ (models.py,
validate_contract.py) at commit 422a8c4, header-documented per file. The
package is named _vendor_loop_schemas (not loop_schemas) so it does not
collide with its own scripts/loop_* denylist; that is the one deviation
from a verbatim vendor, documented in the header and in docs/LOOPS.md.
Stdlib-only: no new dependency was added to the harness core (PyYAML is
optional -- JSON contracts always work, YAML degrades gracefully with a
clear error if PyYAML is not importable).
- template/scripts/validate_loop_contracts.py: discovers contracts under
.loop/contracts/**, validates each with the vendored validator, and is
a documented no-op when none exist (the expected state today). Wired
into template/scripts/quality_gate.py as a new 'loop-contracts' check.
- docs/LOOPS.md: the three-tier model (agent/completion/operational), the
eight final states, the non-negotiable principles, and this repo's
current state (Phase 1, report-only).
B3 - Report-only self-evaluation workflow, in this harness only (no
changes to the sibling harness in this commit):
- scripts/loop_self_evaluation.py: renders every profile x governance
combination into a temporary directory (discarded after the run), gates
each with its own quality_gate.py, checks manifest/plugin/documentation
consistency by delegating to tests.test_harness.DistributionTests, and
writes a structured report.json + report.md. Zero repository
modification; exit code reflects whether everything passed.
- .github/workflows/loop-self-evaluation.yml: workflow_dispatch (with a
default-false 'run_agent_interpretation' input whose step is an inert,
read-only placeholder defining no credentials) plus a weekly schedule.
Uploads the report as a build artifact. Security: top-level
'permissions: {}', explicit job-level 'contents: read' only,
'persist-credentials: false', every action pinned by full commit SHA,
no pull_request_target anywhere.
Out of scope, per the approved plan: no loop_runner.py, loop_gate.py,
loop_state.py, evaluator, or state machine; no autonomy above 'report'.
Validation: full 'uv run python -m unittest discover -s tests -v' (61
tests) passed; ruff check/format clean; mypy clean on the covered source
roots (scripts/loop_self_evaluation.py additionally checked standalone
with mypy --strict, clean; it is not yet in the repo-level mypy path,
which pre-dates this change and covers bootstrap.py/tests/template only);
scripts/quality_gate.py passed in full prior to this commit's final
additions, with every subsequent addition verified individually (ruff,
mypy, and the full test suite including the new, slower self-evaluation
end-to-end test) since the sandbox's command timeout could not host one
single >45s invocation of the full gate.
brunovicco
force-pushed
the
feat/b2-b3-loop-phase0-foundation
branch
from
July 18, 2026 15:30
5508333 to
a8a4352
Compare
Re-vendor _vendor_loop_schemas/{__init__,models,validate_contract}.py
from brunovicco/engineering-loop-schemas@75a63ee,
which fixes two lint failures surfaced by CI on this branch's
generated-profiles (3.14, library) job:
1. UP037 flagged models.py's load-bearing quoted self-referencing
from_dict return annotations as removable, assuming PEP 649
semantics whenever target-version=py314 -- wrong here, since this
file also has to support 3.12/3.13 where the quotes are required.
Fixed upstream via a per-file-ignore in engineering-loop-schemas'
own pyproject.toml, not an inline noqa (an inline noqa becomes a
*second* failure, RUF100 unused-directive, on 3.12/3.13). Added the
matching per-file-ignore here: template/pyproject.toml,
profiles/library/pyproject.toml, profiles/workspace/pyproject.toml
(service has no override pyproject.toml and inherits the template's).
2. A stray '# noqa: PLC0415' on validate_contract.py's lazy
'import yaml' was itself unused (no consumer selects ruff's PL
rules) and became a second RUF100 failure once vendored into a
project with RUF enabled. Dropped upstream.
Verified by rendering all three profiles (service, library, workspace)
at Python 3.12/3.13/3.14 and running their quality gates, re-running
the full 68-test suite, and re-running scripts/loop_self_evaluation.py
end to end -- all pass.
brunovicco
marked this pull request as ready for review
July 18, 2026 16:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(loop): Phase 0-1 report-only Evidence-Gated Engineering Loop foundation
B2 - Minimal integration in this harness, nothing above 'report' autonomy:
'.loop/**' and 'scripts/loop_*', separate from the existing
secrets denylist, with its own message pointing at docs/LOOPS.md. This
is the mechanism that keeps loop_runner.py/loop_gate.py/loop_state.py
and .loop/ contents from being silently built ahead of schedule; only a
human editing outside of an agent tool call can populate them.
engineering-loop-schemas' src/loop_schemas/ (models.py,
validate_contract.py) at commit 422a8c4, header-documented per file. The
package is named vendor_loop_schemas (not loop_schemas) so it does not
collide with its own scripts/loop* denylist; that is the one deviation
from a verbatim vendor, documented in the header and in docs/LOOPS.md.
Stdlib-only: no new dependency was added to the harness core (PyYAML is
optional -- JSON contracts always work, YAML degrades gracefully with a
clear error if PyYAML is not importable).
.loop/contracts/**, validates each with the vendored validator, and is
a documented no-op when none exist (the expected state today). Wired
into template/scripts/quality_gate.py as a new 'loop-contracts' check.
eight final states, the non-negotiable principles, and this repo's
current state (Phase 1, report-only).
B3 - Report-only self-evaluation workflow, in this harness only (no
changes to the sibling harness in this commit):
combination into a temporary directory (discarded after the run), gates
each with its own quality_gate.py, checks manifest/plugin/documentation
consistency by delegating to tests.test_harness.DistributionTests, and
writes a structured report.json + report.md. Zero repository
modification; exit code reflects whether everything passed.
default-false 'run_agent_interpretation' input whose step is an inert,
read-only placeholder defining no credentials) plus a weekly schedule.
Uploads the report as a build artifact. Security: top-level
'permissions: {}', explicit job-level 'contents: read' only,
'persist-credentials: false', every action pinned by full commit SHA,
no pull_request_target anywhere.
Out of scope, per the approved plan: no loop_runner.py, loop_gate.py,
loop_state.py, evaluator, or state machine; no autonomy above 'report'.
Validation: full 'uv run python -m unittest discover -s tests -v' (61
tests) passed; ruff check/format clean; mypy clean on the covered source
roots (scripts/loop_self_evaluation.py additionally checked standalone
with mypy --strict, clean; it is not yet in the repo-level mypy path,
which pre-dates this change and covers bootstrap.py/tests/template only);
scripts/quality_gate.py passed in full prior to this commit's final
additions, with every subsequent addition verified individually (ruff,
mypy, and the full test suite including the new, slower self-evaluation
end-to-end test) since the sandbox's command timeout could not host one
single >45s invocation of the full gate.