Publish curated ITWorx_MCP_Hub source from 5d65966d0393e868ed5df1d95a21412a4c587d78
This commit is contained in:
1 parent
378ae83d30
commit
570089b749
14 files changed
+3491
-78
No files matched your search
+22
-30
@@ -10,21 +10,19 @@ Every entry is hashed from `git archive` output at a chosen ref (default
|
||||
byte-for-byte (see the WP-220 evidence and ``.gitattributes`` for why
|
||||
that already caused a false-positive manifest failure once, in commit
|
||||
95329ca).
|
||||
2. Raw blob content is *also* not what a real archive extraction or checkout
|
||||
produces for every file: Git always stores blobs LF-normalized
|
||||
internally, but a file with an explicit `eol=crlf` `.gitattributes`
|
||||
override (e.g. scripts/bootstrap.ps1, intentionally always-CRLF for
|
||||
native Windows tooling) gets CRLF from `git archive`/`git checkout`
|
||||
regardless. Hashing raw blobs would make the manifest describe bytes
|
||||
nobody ever actually receives. Hashing `git archive` output instead makes
|
||||
manifest generation and "verify a real archive extraction"
|
||||
(`validate_pack.py --verify-tree`) definitionally the same operation.
|
||||
2. The bytes received from Git depend on the path's .gitattributes rules.
|
||||
Text files with an explicit eol rule are normalized in the object store
|
||||
and converted on archive/checkout; paths marked -text retain their exact
|
||||
source bytes in both places. Hashing raw blobs would miss the conversion
|
||||
for text files, while hashing git archive output makes manifest generation
|
||||
and "verify a real archive extraction" (validate_pack.py --verify-tree)
|
||||
definitionally the same operation.
|
||||
|
||||
Both properties hold together because ``.gitattributes`` pins an explicit
|
||||
`eol` for every tracked file type in this repository — no file is left to
|
||||
`core.autocrlf` auto-detection ambiguity, so `git archive` output is fully
|
||||
deterministic across platforms even though it is not identical to the raw
|
||||
blob for CRLF-pinned files.
|
||||
Both properties hold together because .gitattributes pins explicit behavior
|
||||
for every tracked path: ordinary text files have a pinned eol, and the WP-400
|
||||
retained-provenance bundle is a scoped -text exact-byte exception. This avoids
|
||||
core.autocrlf auto-detection ambiguity and keeps git archive output
|
||||
deterministic across platforms.
|
||||
|
||||
Only files tracked by Git at the chosen ref are ever considered — ignored,
|
||||
untracked, local-only, generated, cache, secret, editor, and agent-setting
|
||||
@@ -110,18 +108,13 @@ def batch_blob_contents(ref: str, paths: list[str], repo_root: Path = ROOT) -> d
|
||||
Deliberately sourced from `git archive`, not raw `git cat-file` blob
|
||||
content. Those two differ for any file with an explicit `eol=crlf` (or
|
||||
`eol=lf`) `.gitattributes` override — e.g. scripts/bootstrap.ps1, which
|
||||
is intentionally always-CRLF for native Windows tooling. Git stores every
|
||||
blob LF-normalized internally regardless of that attribute; the
|
||||
attribute only governs the conversion `git archive` and `git checkout`
|
||||
apply on the way *out*. Hashing raw blob bytes would make the manifest
|
||||
describe content nobody ever actually receives from a real archive
|
||||
extraction or checkout — hashing `git archive` output instead makes the
|
||||
manifest and "verify a real archive extraction" (scripts/validate_pack.py
|
||||
--verify-tree) definitionally the same operation, by construction. This
|
||||
is still fully platform-independent: .gitattributes pins an explicit
|
||||
`eol` for every tracked file type, so no file is left to `core.autocrlf`
|
||||
auto-detection ambiguity (verified: a Windows checkout with
|
||||
core.autocrlf=true and a Linux checkout produce byte-identical archives).
|
||||
is intentionally always-CRLF for native Windows tooling. Text paths are
|
||||
normalized in the object store and converted by archive/checkout; -text
|
||||
paths such as the retained WP-400 provenance bundle keep their raw bytes.
|
||||
Raw blobs omit archive-time conversion for text files, while hashing
|
||||
git archive output matches the bytes consumers extract and check out.
|
||||
This makes the manifest and "verify a real archive extraction"
|
||||
(scripts/validate_pack.py --verify-tree) definitionally the same operation.
|
||||
"""
|
||||
if not paths:
|
||||
return {}
|
||||
@@ -202,9 +195,8 @@ def build_manifest(ref: str, repo_root: Path = ROOT) -> dict[str, object]:
|
||||
"contentDigest": compute_content_digest(files),
|
||||
"description": (
|
||||
"Every entry below is hashed from `git archive` output at "
|
||||
"this commit, not from checked-out filesystem bytes and not "
|
||||
"from raw `git cat-file` blob content (those differ for "
|
||||
"files with an explicit eol= override, e.g. "
|
||||
"this commit, not from checked-out filesystem bytes or raw "
|
||||
"blob content for text paths with an eol conversion (e.g. "
|
||||
"scripts/bootstrap.ps1). Regenerating this manifest from the "
|
||||
"same commit on any platform (Windows checkout, Linux "
|
||||
"checkout, fresh clone, or `git archive` extraction) must "
|
||||
@@ -224,7 +216,7 @@ def build_manifest(ref: str, repo_root: Path = ROOT) -> dict[str, object]:
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=("Create a deterministic Git-blob-based checksum manifest for the design pack.")
|
||||
description="Create a deterministic Git-archive-based checksum manifest.",
|
||||
)
|
||||
parser.add_argument("--output", default="PACK_MANIFEST.json")
|
||||
parser.add_argument(
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+31
-30
@@ -11,6 +11,8 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
@@ -29,37 +31,36 @@ _PLACEHOLDER = re.compile(
|
||||
|
||||
def _tracked_text_files() -> list[Path]:
|
||||
files: list[Path] = []
|
||||
for path in ROOT.rglob("*"):
|
||||
if not path.is_file() or set(path.parts) & {
|
||||
".git",
|
||||
".venv",
|
||||
"node_modules",
|
||||
"dist",
|
||||
"coverage",
|
||||
}:
|
||||
git = shutil.which("git")
|
||||
if git is None:
|
||||
raise FileNotFoundError("git is required to enumerate tracked source files")
|
||||
result = subprocess.run( # noqa: S603
|
||||
[git, "ls-files", "-z"],
|
||||
cwd=ROOT,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
)
|
||||
for relative in result.stdout.decode("utf-8").split("\0"):
|
||||
if not relative:
|
||||
continue
|
||||
relative_parts = path.relative_to(ROOT).parts
|
||||
if relative_parts[:2] == (".claude", "worktrees"):
|
||||
# Git-ignored linked worktrees (.git/info/exclude) are full nested
|
||||
# checkouts of a branch's tracked content under a different path
|
||||
# prefix, so a fixture file like tests/fixtures/secret-like.md
|
||||
# reappears at .claude/worktrees/<name>/tests/fixtures/secret-like.md
|
||||
# and fails the tests/-prefix fixture-placeholder match below even
|
||||
# though it's the same already-tracked, already-scanned content.
|
||||
continue
|
||||
if path.suffix.lower() in {
|
||||
".py",
|
||||
".ts",
|
||||
".tsx",
|
||||
".js",
|
||||
".jsx",
|
||||
".json",
|
||||
".yaml",
|
||||
".yml",
|
||||
".md",
|
||||
".toml",
|
||||
".env",
|
||||
}:
|
||||
path = ROOT / relative
|
||||
if (
|
||||
path.suffix.lower()
|
||||
in {
|
||||
".py",
|
||||
".ts",
|
||||
".tsx",
|
||||
".js",
|
||||
".jsx",
|
||||
".json",
|
||||
".yaml",
|
||||
".yml",
|
||||
".md",
|
||||
".toml",
|
||||
".env",
|
||||
}
|
||||
and path.is_file()
|
||||
):
|
||||
files.append(path)
|
||||
return sorted(files)
|
||||
|
||||
|
||||
@@ -83,6 +83,9 @@ def main() -> int:
|
||||
"scripts/restore_state.py",
|
||||
"scripts/compose_release_check.py",
|
||||
"scripts/promotion_preflight.py",
|
||||
"scripts/publish_mcp_hub_ingestion.py",
|
||||
"scripts/build_mcp_hub_release_images.py",
|
||||
"scripts/package_mcp_hub_release_artifact.py",
|
||||
"scripts/export_release.py",
|
||||
"scripts/render_release_record.py",
|
||||
"scripts/verify_demo_token_flow.py",
|
||||
@@ -107,6 +110,11 @@ def main() -> int:
|
||||
"tests/test_contextforge_integration.py",
|
||||
"tests/test_bootstrap.py",
|
||||
"tests/test_compose.py",
|
||||
"tests/test_database_candidate_provenance.py",
|
||||
"tests/test_mcp_hub_ingestion_publisher.py",
|
||||
"tests/test_mcp_hub_release_images.py",
|
||||
"tests/test_mcp_hub_release_artifact.py",
|
||||
"tests/test_release_images_workflow.py",
|
||||
"tests/test_domain.py",
|
||||
"tests/test_migrations.py",
|
||||
"tests/test_persistence.py",
|
||||
@@ -294,6 +302,9 @@ def main() -> int:
|
||||
"scripts/restore_state.py",
|
||||
"scripts/compose_release_check.py",
|
||||
"scripts/promotion_preflight.py",
|
||||
"scripts/publish_mcp_hub_ingestion.py",
|
||||
"scripts/build_mcp_hub_release_images.py",
|
||||
"scripts/package_mcp_hub_release_artifact.py",
|
||||
"scripts/discover_unraid.py",
|
||||
"scripts/revoke_demo_token.py",
|
||||
"scripts/verify_demo_token_runtime.py",
|
||||
|
||||
Reference in new issue
Block a user