Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .governance/error/GOV-WORKTREE-OVERLAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ równoległe worktree są dozwolone, nachodzące zmiany nie.
## Meaning

`001` — rzeczywisty konkurencyjny wkład: brudne zmiany wobec brudnych zmian
lub nowych commitów drugiej strony od wspólnego przodka; dla rozbieżnych
commitów sprawdzany jest merge. Wspólna historia nie jest drugim wkładem.
Brak możliwości ustalenia przodka zachowuje konserwatywne sprawdzanie.
lub nowych commitów drugiej strony. Gdy oba checkouty widzą ten sam SHA
`origin/<default>`, wkład każdego jest liczony od jego wspólnego przodka z
tym SHA. Zmiany odziedziczone z main nie należą do nowego writera.
Dla rozbieżnych commitów sprawdzany jest merge; konflikt przypisuje się parze
tylko na ścieżce, na której obie strony wnoszą wkład. Konflikt starej gałęzi
z main pozostaje widoczny w jej stanie, ale nie blokuje niezależnego writera.
Brak zgodnych refów albo odczytu obiektów zachowuje konserwatywne sprawdzanie
od wspólnego przodka pary. Tak samo traktowane są historie ze zmianą nazwy:
Git może zgłosić konflikt pod inną ścieżką niż pierwotna edycja. Checker nie
pobiera refów i nie zatwierdza merge'a.
`002` — dwa `IN_PROGRESS` intent.json w różnych worktree deklarują nachodzące
`allowedPaths` i żadne nie wymienia drugiego w `conflictsWith`.
`003` — audyt nie dał się bezpiecznie dokończyć.
Expand Down
25 changes: 25 additions & 0 deletions .governance/governance_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -2601,6 +2601,26 @@ def check_delivery_timebox(
)


def is_published_integration(root: Path, target: str, supplied_base: str | None) -> bool:
"""Recognize one clean integration already observed on the target branch.

The supplied first parent is the target before this integration. Comparing
the accepted base with the published HEAD would include the ticket's own
changes as intervening drift. Ambiguous ranges and dirty trees retain the
conservative target comparison; this observation never grants approval.
"""
if not supplied_base:
return False
try:
return (
git_output(root, ["rev-parse", "HEAD"]).decode().strip() == target
and git_output(root, ["rev-parse", f"{target}^1"]).decode().strip() == supplied_base
and not git_output(root, ["status", "--porcelain"])
)
except (subprocess.CalledProcessError, FileNotFoundError):
return False


def check_delivery_base(
root: Path,
policy: dict[str, Any],
Expand Down Expand Up @@ -2649,6 +2669,11 @@ def check_delivery_base(
current_target = git_output(root, ["rev-parse", "--verify", f"{target_ref}^{{commit}}"]).decode().strip()
except (subprocess.CalledProcessError, FileNotFoundError):
continue
supplied_base = next((sha for source, sha in observed if source == "suppliedBase"), None)
if is_published_integration(root, current_target, supplied_base):
# The accepted-to-supplied-base check below still detects changes
# that landed on the target before this ticket was integrated.
break
observed.append((target_ref, current_target))
break

Expand Down
2 changes: 1 addition & 1 deletion .governance/manifest.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"stacks": [],
"standard": {
"id": "wellmanifest/new-project",
"version": "0.20.13"
"version": "0.20.16"
},
"ticket": {
"activeStatuses": [
Expand Down
2 changes: 1 addition & 1 deletion .governance/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
],
"standard": {
"id": "wellmanifest/new-project",
"version": "0.20.13"
"version": "0.20.16"
},
"ticket": {
"activeStatuses": [
Expand Down
18 changes: 9 additions & 9 deletions .governance/manifest.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@
".governance/error/GOV-TICKET-ALLOCATION.md": "09f92cac24bbbbe5c2967221497fb6b68b02bcd3bf4f56afe36d36ac7d7b0a58",
".governance/error/GOV-WORK-CONTINUITY.md": "de46a4adc51e8dd5880a83a6d9585ecdbbea4ae30a44ee6506c207ea2e8bc8eb",
".governance/error/GOV-WORKSPACE-LIFECYCLE.md": "72436684572d784327a340d90ca96d9fd2927519e02334036fab402e9c1d8262",
".governance/error/GOV-WORKTREE-OVERLAP.md": "3f0170924de9c316cfc7313b3f0d37635e47181714ce5542fdeac054fd08124e",
".governance/error/GOV-WORKTREE-OVERLAP.md": "65a2533f13e63d6ebeeb63c07adc0794ea9e04075a91e873eff2d79910239b0e",
".governance/error/README.md": "e8486dd29f52ca3fee96ed6881a62c38141864cde5aa1adea2b16d22b2feefaa",
".governance/generate_required_checks.py": "aa44610d8ec26aaf4993cec194ce16338d458b567f7d06a2c34b470b9b76f6cc",
".governance/governance_check.py": "305fc2fbf1c01a8a05e514346aa244977efabedd348379ebffd7e6562949fa17",
".governance/governance_check.py": "290f8dee1c2e6b24c3a195ae548bedf796f5ea3447b2518cc2a737e8437f71d6",
".governance/intent.schema.json": "9755f20cd189efe2205629781a6cf6b613bd93e9368416793c4de53256b0a9c0",
".governance/lock.schema.json": "ad80c98f800a4a3310870336dcdaf0aa689cc4988f71084d25d76bea2df1242f",
".governance/manifest.base.json": "763a046bb830631e3a6fb94f6a35403620918a02d4956d7573a8dcd03e4ba1ab",
".governance/manifest.base.json": "87fb6c9a351c4893cfa7ba15d39f00079dafe366ef26dd9bf435000719bfc665",
".governance/manifest.schema.json": "5aa2ccd3f6898834d4e39a78342448145490be56aa132e16ac7c9d64acef8f73",
".governance/package-manifest.json": "a2ea77aca16d59282e1b60105521270ae112ebc52ddb3e08af3eeec26942dc3f",
".governance/precommit_standard_update.py": "c91e2bf9ae9d6ccc77bce0e61450c818a5961edee5bfde3b60426da88e296b0f",
Expand All @@ -69,10 +69,10 @@
".governance/work_continuity.py": "2efb720b530cc295b45413a2bc7384a426bd29b5d9b20452035e5943294c18e4",
".governance/workspace_lifecycle_check.py": "f196f33c4884120ca216e65473f32b163f6c6d262624309cf0cbdc37063d181f",
".governance/worktree_guard.py": "b154f6e67626770ec11c9544d31a27b32d9c215ef73ffc9eb8f52e9c3a9b051b",
".governance/worktree_overlap_check.py": "dfb6463889617352578576ad699f8baa4246c013cf943e1b427a76176d7e19a5",
".governance/worktree_path_check.py": "d3309b76e2c91dd7f046b00322ec8cb48ef744b8b7908d70e475fedf95e5e196",
".governance/worktrees.lock.json": "9ed607dd339fd4ed30263d7de62231249447568e8e35c8b19fdc0231fca39fde",
".governance/worktrees.schema.json": "9cc10d126e06cafc87cc117f11b8b095676f461de4d168d2a1c2bb959f0fccd5",
".governance/worktree_overlap_check.py": "582fb82588aa1cf40af5213e9e931f06ae90824e59b5ec5deb16ae7d6beb09b8",
".governance/worktree_path_check.py": "4d3e8457023eccd417a472be9c46a975dbc46c04d38c204eecd92a8583bb996e",
".governance/worktrees.lock.json": "319349217c525d28def89d155dade1cfcee637f536dd852dc87287612c47731f",
".governance/worktrees.schema.json": "bb5989c19ee33d9beafa34576ef568ef70384a664ccf763ac2e29dde3a464756",
".subactor/.gitignore": "dd223aed5e053f94c6808ac434368c16eeca7e77218f8426e8cf5e46ae441d03",
".subactor/manifest.json": "ab8b1cbe4052a6f0005a3c33a43fa2a70e8837cd32c18b4183d0d448c3a8cee2",
"AGENTS.md": "12641a33dcfc24c353834e95d09d4784c42ec035dcf350dd153b55eb02182364",
Expand All @@ -92,7 +92,7 @@
"id": "wellmanifest/new-project",
"publicationStatus": "published",
"sourceRepository": "wellmanifest/new-project",
"sourceRevision": "824625238d697511f58be2b73c0aa6e15c228a9a",
"version": "0.20.13"
"sourceRevision": "6d2da011088b69ebe1636f3bf681e5ec21a062ab",
"version": "0.20.16"
}
}
40 changes: 35 additions & 5 deletions .governance/worktree_overlap_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,15 @@ def contested_paths(
) -> tuple[str, ...]:
"""Paths these two checkouts genuinely contend for.

Compare each dirty delta with the peer's contribution since their shared
history, not with everything inherited from the default branch. An inert
snapshot at the same HEAD contributes no competing committed change.
Unknown ancestry retains the conservative path-intersection fallback.
Prefer each writer's contribution relative to the same observed origin
default-branch revision. A pair's older common ancestor includes main's
history in a fresh writer, even when that writer edits unrelated files.
Missing or divergent observations retain the common-ancestor fallback.
"""
first_dirty = set(first.dirty_paths) - pending_main_imports(first.path)
second_dirty = set(second.dirty_paths) - pending_main_imports(second.path)
first_changes, second_changes = set(first.changed_paths), set(second.changed_paths)
shared_default = False
if first.head and second.head:
base = first.head if first.head == second.head else merge_base(first.path, first.head, second.head)
if base:
Expand All @@ -502,6 +503,30 @@ def contested_paths(
second_changes = second_committed | second_dirty
except AuditError:
pass
try:
first_default = run_git(first.path, "rev-parse", "--verify",
f"refs/remotes/origin/{default_branch(first.path)}^{{commit}}")
second_default = run_git(second.path, "rev-parse", "--verify",
f"refs/remotes/origin/{default_branch(second.path)}^{{commit}}")
if first_default == second_default:
first_base = run_git(first.path, "merge-base", first.head, first_default)
second_base = run_git(second.path, "merge-base", second.head, second_default)
first_committed = set(run_git(first.path, "diff", "--name-only", "--no-renames", first_base, first.head).splitlines())
second_committed = set(run_git(second.path, "diff", "--name-only", "--no-renames", second_base, second.head).splitlines())
first_renames = run_git(first.path, "diff", "--name-only", "--find-renames",
"--diff-filter=R", first_base, first.head)
second_renames = run_git(second.path, "diff", "--name-only", "--find-renames",
"--diff-filter=R", second_base, second.head)
# Replace both sides only after every strict Git read succeeds.
# Rename/directory-rename conflicts can be reported at a path
# edited under another name. Preserve the conservative path
# model until attribution can follow those identities too.
if not first_renames and not second_renames:
first_changes = first_committed | first_dirty
second_changes = second_committed | second_dirty
shared_default = True
except AuditError:
pass
dirty_overlap = (first_dirty & second_changes) | (second_dirty & first_changes)
conflicts: set[str] = set()
if first.head and second.head and first.head != second.head:
Expand All @@ -511,9 +536,14 @@ def contested_paths(
reported = merge_tree_conflicts(first.path, first.head, second.head)
if reported is None:
# No usable merge-tree: fall back to the path-intersection proxy.
conflicts = set(first.changed_paths) & set(second.changed_paths)
conflicts = first_changes & second_changes
else:
conflicts = set(reported)
if shared_default:
# A branch can conflict with main without contending with
# this particular peer. Keep the conflict in its inventory,
# but require contributions from both writers for pairing.
conflicts &= first_changes & second_changes
return tuple(
sorted(
name
Expand Down
20 changes: 12 additions & 8 deletions .governance/worktree_path_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ def _validate_segment(label: str, value: str) -> None:
raise ValueError(f"{label} must contain lowercase ASCII words separated by hyphens")


def _validate_repository_name(repository_name: str) -> None:
if (
not isinstance(repository_name, str)
or not repository_name
or repository_name in {".", ".."}
or any(character in repository_name for character in ("/", "\\", "\0"))
):
raise ValueError("repositoryName must be an observed repository basename")


def plan(
*,
repository: str,
Expand All @@ -44,7 +54,7 @@ def plan(
path_style: str = "posix",
) -> dict[str, str]:
"""Return the canonical v5 layout record for one delivery unit."""
_validate_segment("repositoryName", repository_name)
_validate_repository_name(repository_name)
_validate_segment("slug", slug)
ticket_match = TICKET_RE.fullmatch(ticket)
if not ticket_match:
Expand Down Expand Up @@ -303,13 +313,7 @@ def inventory(
path_style: str = "posix",
) -> dict[str, Any]:
"""Build a deterministic, observation-only inventory record."""
if (
not isinstance(repository_name, str)
or not repository_name
or repository_name in {".", ".."}
or any(character in repository_name for character in ("/", "\\", "\0"))
):
raise ValueError("repositoryName must be an observed repository basename")
_validate_repository_name(repository_name)
path_type = _path_type(path_style)
primary = path_type(primary_checkout)
if not primary.is_absolute():
Expand Down
8 changes: 4 additions & 4 deletions .governance/worktrees.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
"schema": "new-project.worktrees-lock/v1",
"dependency": {
"id": "wellmanifest/worktrees",
"version": "0.5.1",
"version": "0.5.2",
"sourceRepository": "wellmanifest/worktrees",
"sourceRevision": "81e0d750f18ecace4436706250bf5deb190a000a"
"sourceRevision": "44f1686dd041554649720e171d690944afa49586"
},
"artifacts": [
{
"sourcePath": "models/worktrees.schema.json",
"packageSourcePath": "subprojects/worktrees/worktrees.schema.json",
"managedTargetPath": ".governance/worktrees.schema.json",
"sourceSha256": "9cc10d126e06cafc87cc117f11b8b095676f461de4d168d2a1c2bb959f0fccd5"
"sourceSha256": "bb5989c19ee33d9beafa34576ef568ef70384a664ccf763ac2e29dde3a464756"
},
{
"sourcePath": "operations/conformance.py",
"packageSourcePath": "subprojects/worktrees/conformance.py",
"managedTargetPath": ".governance/worktree_path_check.py",
"sourceSha256": "d3309b76e2c91dd7f046b00322ec8cb48ef744b8b7908d70e475fedf95e5e196"
"sourceSha256": "4d3e8457023eccd417a472be9c46a975dbc46c04d38c204eecd92a8583bb996e"
}
],
"installation": {
Expand Down
3 changes: 1 addition & 2 deletions .governance/worktrees.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
],
"$defs": {
"repositoryName": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
"$ref": "#/$defs/observedRepositoryName"
},
"observedRepositoryName": {
"type": "string",
Expand Down
18 changes: 18 additions & 0 deletions project/ticket-094/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ticket 094: Adopt published integration-base validation

- **Owner**: codex
- **Status**: IN_PROGRESS
- **Workflow state**: PUBLICATION

SESSION_EXECUTION_AUTHORIZATION: the user requests continuation, fixes, tests and GitHub publication. Wait for the independently approved immutable standard release 0.20.16, then adopt it through Goal and verify the post-merge CI result. This does not wait for another chat approval.

## Acceptance criteria

- [x] AC-01: Adopt published standard 0.20.16 while preserving target extensions and immutable provenance.
- [ ] AC-02: Full tests and required checks pass, protected publication succeeds, and the main-branch CI verifies the integrated result without GOV-BASE-002.

Existing primary metadata and other agents' workspaces remain preserved.

Published dependency: wellmanifest/new-project v0.20.16, immutable source `6d2da011088b69ebe1636f3bf681e5ec21a062ab`, approved and merged in PR #309.

Validation before publication: 735 tests passed, 2 pre-existing skips; all 10 published integration-base regression cases passed against digest-verified adopted code. Governance passed with 0 errors and 0 warnings; immutable adoption, active host hooks, local pin and Compose validation passed. Package standard/revision declarations were regenerated from the lock; product package version and dependencies remain unchanged. AC-02 remains pending protected merge and the main-branch CI run.
90 changes: 90 additions & 0 deletions project/ticket-094/intent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
"schema": "new-project.intent/v3",
"ticket": "ticket-094",
"summary": "Adopt the immutable published fix for integration-base validation",
"workstream": "governance",
"classification": {
"kind": "BUG",
"priority": "P1",
"origin": "regression"
},
"allowedPaths": [
".governance/**",
"pyproject.toml",
"project/ticket-094/**"
],
"forbiddenPaths": [
"project/ticket-*/user-*.md"
],
"stacks": [
"python",
"docker"
],
"dependsOn": [],
"conflictsWith": [],
"integrationTicket": null,
"delivery": {
"acceptedBaseSha": "c684b082618c8b7ba0cd54ca03d04aeff1f771b3",
"targetBranch": "main",
"outcome": "Adopt approved standard 0.20.16, restore green post-merge main CI, and verify the actual local Goal installation.",
"nonGoals": [
"Change product CLI behavior beyond the published governance update.",
"Publish a new Goal package version."
],
"complexity": "L",
"estimatedMinutes": 30,
"budgets": {
"maxImplementationFiles": 15,
"maxAffectedComponents": 1,
"maxPublicInterfaceChanges": 0,
"maxRuntimeDependencies": 0
},
"architecture": {
"status": "accepted",
"decision": "Use the immutable published standard through Goal and preserve all existing target-owned extensions. Update only the standard/revision package declaration from the adoption lock, through the standard atomic-adoption binding.",
"components": [
{
"name": "governance-adoption",
"paths": [
".governance/**",
"pyproject.toml"
]
}
],
"responsibilityChanges": false,
"interfaceChanges": [],
"dataChanges": [],
"ui": {
"impact": "none",
"states": [],
"evidence": []
},
"rollback": "Re-adopt the previous published source through protected delivery."
},
"runtimeDependencies": [],
"validation": [
{
"criterion": "AC-01",
"commands": [
"goal governance adopt --check",
"./scripts/install-agent-hosts.sh --check"
],
"evidence": "Published immutable source revision and managed payload digests."
},
{
"criterion": "AC-02",
"commands": [
"./project/governance-check.sh",
"python3 -m pytest tests/ -q",
"docker compose config --quiet"
],
"evidence": "Required Python CI on the PR and after integration; fresh trusted merge and deployment readback."
}
],
"standardAdoption": {
"sourceRepository": "wellmanifest/new-project",
"fromRevision": "824625238d697511f58be2b73c0aa6e15c228a9a",
"toRevision": "6d2da011088b69ebe1636f3bf681e5ec21a062ab"
}
}
}
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ python_files = ["test_*.py"]
addopts = "-p wellmanifest_governance"

[tool.wellmanifest]
standard = "0.20.13"
revision = "824625238d697511f58be2b73c0aa6e15c228a9a"
standard = "0.20.16"
revision = "6d2da011088b69ebe1636f3bf681e5ec21a062ab"
gate = "project/governance-check.sh"

[tool.pfix]
Expand Down