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
Original file line number Diff line number Diff line change
Expand Up @@ -959,3 +959,10 @@ The full planning contracts remain in repository Markdown:

- `docs/product_workspace_graph_versioning_roadmap.md`
- `docs/product_workspace_stable_mode_guide.md`
## Durable workspace binding evidence

Proposal `0211` adds a public-safe `workspace_binding_evidence` descriptor to
the SpecGraph product workspace initialization receipt. The descriptor pins
workspace identity, relative layout roots, project-config digest, and
repository-role hints without exposing absolute local paths or granting
Platform, Git, spec, or Ontology mutation authority.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 0211 Durable Product Workspace Binding Evidence

## Status

Draft / bounded product workspace initialization evidence slice.

## Summary

Platform already records routing and execution fields for an initialized product
workspace, but downstream operations can still derive run directories, state
namespaces, or artifact routes from a workspace slug or shared local defaults.
SpecGraph's initialization receipt proves that a workspace layout is valid, but
it does not yet expose a compact digest-bound descriptor that Platform can pin
when it creates the durable cross-repository binding.

This slice adds that SpecGraph-owned evidence without making SpecGraph the owner
of Platform paths, SpecSpace state, deployment URLs, or Git execution.

## Decision

`runs/product_workspace_initialization.json` carries
`workspace_binding_evidence` with:

- stable workspace identity and product-workspace governance;
- workspace-relative layout refs for config, specs, proposals, runs, and
supervisor state;
- the `specgraph.project.yaml` digest;
- repository/worktree identity hints that do not create a worktree;
- a stable evidence digest over the public-safe descriptor;
- closed privacy and authority boundaries.

Platform may validate and pin the whole initialization report plus this evidence
when it creates its durable workspace binding. SpecSpace may render a sanitized
projection but must not infer local paths from the route.

## Authority Boundary

This slice does not:

- select Platform artifact base URLs or local execution roots;
- allocate SpecSpace mutable-state storage;
- execute Platform, SpecGraph managed flows, or Git Service;
- create a repository, worktree, branch, commit, or pull request;
- mutate canonical specs;
- write Ontology packages or accept Ontology terms;
- publish raw root intent or local absolute paths.

## Acceptance Criteria

- Ready initialization reports include versioned workspace binding evidence.
- Evidence uses workspace-relative refs and a stable content digest.
- The project config digest is available on first initialization and idempotent
reruns.
- Blocked initialization reports mark binding evidence blocked.
- No absolute input path or raw root intent appears in the evidence.
- Platform can pin the initialization report and evidence without re-deriving
SpecGraph layout semantics.

8 changes: 8 additions & 0 deletions docs/product_workspace_graph_versioning_roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,14 @@ That directory has its own `artifact_manifest.json` and `checksums.sha256`.
SpecSpace production routes should read `/team-decision-log` from this
workspace-specific artifact base instead of the bootstrap root bundle.

## Durable Product Workspace Binding Evidence

Implemented producer-side in proposal `0211`. Product workspace initialization
now emits digest-bound, workspace-relative binding evidence. Platform owns the
external binding across artifact routing, SpecSpace state namespace, execution
run directory, and repository resolution; SpecGraph owns only initialized
workspace identity, layout semantics, and project-config evidence.

## Related Documents

- `docs/product_workspace_stable_mode_guide.md`
Expand Down
7 changes: 7 additions & 0 deletions docs/product_workspace_initialization_viewer_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ python3 tools/supervisor.py \
}
```

Proposal `0211` adds `workspace_binding_evidence` to the same receipt. The
evidence carries workspace identity, workspace-relative layout refs, the
`specgraph.project.yaml` digest, repository/worktree identity hints, and a
stable evidence digest. Platform may pin it into a durable workspace binding;
SpecSpace should consume only a public-safe projection and must not infer local
paths from the route.

## UI Guidance

- Show `summary.status` as the primary status.
Expand Down
58 changes: 58 additions & 0 deletions docs/proposals/0211_durable_product_workspace_binding_evidence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 0211 Durable Product Workspace Binding Evidence

## Status

Draft / bounded product workspace initialization evidence slice.

## Summary

Platform already records routing and execution fields for an initialized product
workspace, but downstream operations can still derive run directories, state
namespaces, or artifact routes from a workspace slug or shared local defaults.
SpecGraph's initialization receipt proves that a workspace layout is valid, but
it does not yet expose a compact digest-bound descriptor that Platform can pin
when it creates the durable cross-repository binding.

This slice adds that SpecGraph-owned evidence without making SpecGraph the owner
of Platform paths, SpecSpace state, deployment URLs, or Git execution.

## Decision

`runs/product_workspace_initialization.json` carries
`workspace_binding_evidence` with:

- stable workspace identity and product-workspace governance;
- workspace-relative layout refs for config, specs, proposals, runs, and
supervisor state;
- the `specgraph.project.yaml` digest;
- repository/worktree identity hints that do not create a worktree;
- a stable evidence digest over the public-safe descriptor;
- closed privacy and authority boundaries.

Platform may validate and pin the whole initialization report plus this evidence
when it creates its durable workspace binding. SpecSpace may render a sanitized
projection but must not infer local paths from the route.

## Authority Boundary

This slice does not:

- select Platform artifact base URLs or local execution roots;
- allocate SpecSpace mutable-state storage;
- execute Platform, SpecGraph managed flows, or Git Service;
- create a repository, worktree, branch, commit, or pull request;
- mutate canonical specs;
- write Ontology packages or accept Ontology terms;
- publish raw root intent or local absolute paths.

## Acceptance Criteria

- Ready initialization reports include versioned workspace binding evidence.
- Evidence uses workspace-relative refs and a stable content digest.
- The project config digest is available on first initialization and idempotent
reruns.
- Blocked initialization reports mark binding evidence blocked.
- No absolute input path or raw root intent appears in the evidence.
- Platform can pin the initialization report and evidence without re-deriving
SpecGraph layout semantics.

36 changes: 36 additions & 0 deletions tests/test_supervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25015,6 +25015,33 @@ def test_initialize_product_workspace_creates_minimal_layout(
)
assert artifact["workspace"]["root"] == "."
assert artifact["workspace"]["local_input_path_persisted"] is False
binding = artifact["workspace_binding_evidence"]
assert binding["contract_ref"] == ("specgraph.product-workspace.binding-evidence.v0.1")
assert binding["proposal_id"] == "0211"
assert binding["status"] == "ready"
assert binding["identity"] == {
"workspace_id": "swiftui-calculator",
"display_name": "SwiftUI Calculator",
"governance_profile": "product_workspace",
"repository_role": "product_spec_workspace",
}
assert binding["layout"]["runs_root_ref"] == "runs"
assert binding["project_config"]["source_ref"] == "specgraph.project.yaml"
assert len(binding["project_config"]["source_sha256"]) == 64
binding_without_digest = copy.deepcopy(binding)
evidence_sha256 = binding_without_digest.pop("evidence_sha256")
assert (
evidence_sha256
== supervisor_module.hashlib.sha256(
json.dumps(
binding_without_digest,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
).hexdigest()
)
assert binding["privacy_boundary"]["workspace_relative_refs_only"] is True
assert binding["authority_boundary"]["may_create_git_commit"] is False
assert artifact["root_intent"]["status"] == "captured"
assert "Build a SwiftUI calculator" not in json.dumps(artifact)

Expand Down Expand Up @@ -25044,6 +25071,14 @@ def test_initialize_product_workspace_is_idempotent(
assert second["workspace"]["created_paths"] == []
assert "specgraph.project.yaml" in second["workspace"]["existing_paths"]
assert ".specgraph/root_intent.md" in second["workspace"]["existing_paths"]
assert (
first["workspace_binding_evidence"]["project_config"]["source_sha256"]
== second["workspace_binding_evidence"]["project_config"]["source_sha256"]
)
assert (
first["workspace_binding_evidence"]["evidence_sha256"]
== second["workspace_binding_evidence"]["evidence_sha256"]
)


def test_initialize_product_workspace_hashes_existing_root_intent(
Expand Down Expand Up @@ -25216,6 +25251,7 @@ def test_initialize_product_workspace_blocks_conflicting_config_without_overwrit
)
assert artifact["summary"]["status"] == "blocked"
assert artifact["next_gap"] == "repair_product_workspace_initialization"
assert artifact["workspace_binding_evidence"]["status"] == "blocked"


def test_initialize_product_workspace_refuses_core_repo_paths(
Expand Down
6 changes: 6 additions & 0 deletions tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2030,3 +2030,9 @@ python3 tools/search_pageindex.py "agent orchestration" --top-k 10 --context

The script expects the PageIndex API to be running on `http://localhost:8765` and uses the
`~/Development/GitHub/PageIndexInstance/results/chatgpt_dialogs/catalog.json` catalog by default.
## Durable product workspace binding evidence

Proposal 0211 adds digest-bound `workspace_binding_evidence` to
`runs/product_workspace_initialization.json`. Platform can use it as
producer-owned initialization evidence while retaining ownership of artifact
routing, state namespaces, execution roots, and repository operations.
13 changes: 13 additions & 0 deletions tools/proposal_promotion_registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -2715,5 +2715,18 @@
"required_provenance_links": [
"source_draft_ref"
]
},
{
"proposal_id": "0211",
"source_artifact_class": "working_draft",
"source_refs": [
"docs/archive/proposal_sources/0211_durable_product_workspace_binding_evidence.md"
],
"motivating_concern": "Platform and SpecSpace need durable product workspace routing and execution bindings, but SpecGraph initialization currently lacks a compact digest-bound descriptor of the workspace identity and relative layout it owns.",
"normalized_title": "Durable Product Workspace Binding Evidence",
"bounded_scope": "Emit digest-bound workspace-relative initialization evidence for Platform and SpecSpace consumers without selecting deployment URLs or state storage, executing managed operations, mutating canonical specs, writing Ontology packages, accepting terms, creating Git artifacts, or publishing raw intent and local paths.",
"required_provenance_links": [
"source_draft_ref"
]
}
]
49 changes: 49 additions & 0 deletions tools/proposal_runtime_registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -12041,5 +12041,54 @@
}
],
"notes": "SpecGraph now emits workspace-bound fallback-free real-intake clarification outcomes and browser-answerable templates, including mandatory policy context, without publishing raw ideas or expanding execution authority."
},
{
"proposal_id": "0211",
"posture": "bounded_runtime_followup",
"runtime_surfaces": [
"docs/proposals/0211_durable_product_workspace_binding_evidence.md",
"docs/archive/proposal_sources/0211_durable_product_workspace_binding_evidence.md",
"tools/supervisor.py",
"tests/test_supervisor.py",
"docs/product_workspace_initialization_viewer_contract.md",
"docs/product_workspace_graph_versioning_roadmap.md",
"Sources/SpecGraph/Documentation.docc/ProductWorkspacePilots.md",
"tools/README.md"
],
"runtime_markers": [
{
"path": "tools/supervisor.py",
"pattern": "PRODUCT_WORKSPACE_BINDING_EVIDENCE_PROPOSAL_ID = \"0211\""
},
{
"path": "tools/supervisor.py",
"pattern": "\"workspace_binding_evidence\": binding_evidence"
}
],
"validation_markers": [
{
"path": "tests/test_supervisor.py",
"pattern": "specgraph.product-workspace.binding-evidence.v0.1"
},
{
"path": "tests/test_supervisor.py",
"pattern": "workspace_binding_evidence\"][\"status\"] == \"blocked\""
}
],
"observation_markers": [
{
"path": "docs/product_workspace_graph_versioning_roadmap.md",
"pattern": "Implemented producer-side in proposal `0211`"
},
{
"path": "Sources/SpecGraph/Documentation.docc/ProductWorkspacePilots.md",
"pattern": "Proposal `0211` adds a public-safe"
},
{
"path": "tools/README.md",
"pattern": "Proposal 0211 adds digest-bound"
}
],
"notes": "SpecGraph product workspace initialization now emits digest-bound workspace-relative binding evidence for Platform without taking ownership of external routing, state namespaces, execution roots, or Git operations."
}
]
55 changes: 55 additions & 0 deletions tools/supervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10924,6 +10924,10 @@ def write_project_environment(environment: dict[str, Any]) -> Path:


PRODUCT_WORKSPACE_INITIALIZATION_ARTIFACT_KIND = "product_workspace_initialization"
PRODUCT_WORKSPACE_BINDING_EVIDENCE_PROPOSAL_ID = "0211"
PRODUCT_WORKSPACE_BINDING_EVIDENCE_CONTRACT_REF = (
"specgraph.product-workspace.binding-evidence.v0.1"
)
PRODUCT_WORKSPACE_INITIALIZATION_SCHEMA_VERSION = 1
PRODUCT_WORKSPACE_INITIALIZATION_PROPOSAL_ID = "0054"
PRODUCT_WORKSPACE_REQUIRED_DIRECTORIES = (
Expand Down Expand Up @@ -11330,6 +11334,56 @@ def initialize_product_workspace(
root_intent_content_sha256 = ""

workspace_status = "blocked" if has_errors else ("initialized" if created_paths else "ready")
binding_evidence: dict[str, Any] = {
"contract_ref": PRODUCT_WORKSPACE_BINDING_EVIDENCE_CONTRACT_REF,
"proposal_id": PRODUCT_WORKSPACE_BINDING_EVIDENCE_PROPOSAL_ID,
"status": "blocked" if has_errors else "ready",
"identity": {
"workspace_id": normalized_project_id,
"display_name": normalized_display_name,
"governance_profile": "product_workspace",
"repository_role": "product_spec_workspace",
},
"layout": {
"root_reference": "workspace_relative",
"project_config_ref": PROJECT_CONFIG_RELATIVE_PATH,
"specs_root_ref": "specs",
"proposals_root_ref": "docs/proposals",
"runs_root_ref": "runs",
"supervisor_state_root_ref": ".specgraph",
},
"project_config": {
"source_ref": PROJECT_CONFIG_RELATIVE_PATH,
"source_sha256": hashlib.sha256(config_text.encode("utf-8")).hexdigest(),
},
"repository": {
"repository_role": "product_spec_workspace",
"workspace_identity": normalized_project_id,
"worktree_identity": f"product-workspace/{normalized_project_id}",
"creates_worktree": False,
},
"privacy_boundary": {
"workspace_relative_refs_only": True,
"local_input_path_persisted": False,
"raw_root_intent_published": False,
},
"authority_boundary": {
"report_only": True,
"may_execute_platform": False,
"may_mutate_canonical_specs": False,
"may_write_ontology_packages": False,
"may_accept_ontology_terms": False,
"may_create_git_commit": False,
"may_open_pull_request": False,
},
}
binding_evidence["evidence_sha256"] = hashlib.sha256(
json.dumps(
binding_evidence,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
).hexdigest()
report: dict[str, Any] = {
"artifact_kind": PRODUCT_WORKSPACE_INITIALIZATION_ARTIFACT_KIND,
"schema_version": PRODUCT_WORKSPACE_INITIALIZATION_SCHEMA_VERSION,
Expand All @@ -11342,6 +11396,7 @@ def initialize_product_workspace(
"display_name": normalized_display_name,
"governance_profile": "product_workspace",
},
"workspace_binding_evidence": binding_evidence,
"workspace": {
"root": ".",
"root_reference": "workspace_relative",
Expand Down