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
102 changes: 102 additions & 0 deletions dag/extdeps/git/publication_transport.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
module extdeps.git.publication_transport

import std.types { Bool, CommitSha, GitRef, Int, List, NonEmptyStr, String }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef }
import extdeps.uri { Uri, Https }

data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "git-scm.com/docs/git-push"
}
}

data git_commit_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "git-scm.com/docs/git-commit"
}
}

data extdeps_model_scope: ExternalModelScope = ExternalModelScope {
subject: ExternalSubjectRef {
declaration: DeclarationRef {
module_path: "extdeps.git.publication_transport",
decl_name: "PublicationTransport",
field: WholeDeclaration
}
},
first_citation: extdeps_external_authority_anchor,
further_citations: [git_commit_external_authority_anchor]
}

data git_publication_transport_note: String = "Modeled upstream publication write operations de-fused from git.Core. GitPushRequest and GitCommitRequest are the interface shapes; shell argv lives only in git.PublicationTransport service transport rows — no parallel free-fn argv surface. Slice 1 is model + shadow only — consumers route through tools.publication_publisher before binding a transport handler in the live slice."

type GitRefUpdateSpec {
local_ref: GitRef
remote_ref: GitRef
}

type GitPushRequest {
remote: NonEmptyStr
ref_updates: List<GitRefUpdateSpec>
}

type GitCommitRequest {
message: NonEmptyStr
allow_empty: Bool
}

data git_commit_allow_empty_dispatch_note: String = "GitCommitRequest.allow_empty selects RecordEmptyCommit vs RecordCommit at transport bind — two operations, because shell argv templates cannot branch on Bool."

service git.PublicationTransport {
operation PushRefUpdate {
input {
remote: NonEmptyStr
refspec: NonEmptyStr
}
output {
exit_code: Int from "exit_code"
stderr: String from "stderr"
success: Bool from "exit_success"
}
transport shell { argv: ["git", "push", "{remote}", "{refspec}"] }
exit {
0 => Unit
nonzero => String "Push failed"
}
}

operation RecordCommit {
input {
message: NonEmptyStr
}
output {
sha: CommitSha from "stdout"
success: Bool from "exit_success"
stderr: String from "stderr"
}
transport shell { argv: ["git", "commit", "-m", "{message}"] }
exit {
0 => Unit
nonzero => String "Commit failed"
}
}

operation RecordEmptyCommit {
input {
message: NonEmptyStr
}
output {
sha: CommitSha from "stdout"
success: Bool from "exit_success"
stderr: String from "stderr"
}
transport shell { argv: ["git", "commit", "--allow-empty", "-m", "{message}"] }
exit {
0 => Unit
nonzero => String "Commit failed"
}
}
}
7 changes: 7 additions & 0 deletions dag/gunbc/doc_graph_roots.dag
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@ data hand_authored_doc_binds: List<HandAuthoredDocBind> = [
additional_works: [DeclarationRef { module_path: "v2.workflow.floor_diff_observe", decl_name: "floor_observe_ci_diff_event", field: WholeDeclaration }, DeclarationRef { module_path: "gunbc.diff_baseline", decl_name: "diff_baseline_fail_closed_law", field: WholeDeclaration }],
dissolution: HasTrigger { text: "the last-green baseline lands — the push baseline becomes the last main commit whose floor RAN AND WHOSE SELECTION COVERED IT (not floor job conclusion, which stops meaning coverage the moment push selection becomes real), observed fail-closed so an undeterminable answer refuses instead of falling back to the before-SHA — and the stage-1 counted receipt for unverifiable predecessor coverage reaches zero. Then the sequencing argument is spent and the surviving facts live on their carriers, so this note deletes with this row. The evidence-status table is the part that must migrate rather than evaporate: which arms are observed, which are spec-grounded, and the window each measurement came from." },
},
HandAuthoredDocBind {
home: PlanDoc,
slug: "sole-modeled-publisher-design",
primary_work: DeclarationRef { module_path: "tools.publication_publisher", decl_name: "PublicationAuthority", field: WholeDeclaration },
additional_works: [DeclarationRef { module_path: "tools.publication_push_shadow", decl_name: "shadow_replay_public_pushes", field: WholeDeclaration }],
dissolution: HasTrigger { text: "live slice lands: ordinary sessions lose public-write credentials, git.PublicationTransport dispatch binds to PublicationAuthority, and shadow witness becomes regression control — then register as gunbc.plan.Plan row or delete with carriers" },
},
]

fn hand_authored_doc_graph_roots() -> List<String> {
Expand Down
1 change: 1 addition & 0 deletions dag/gunbc/extdeps_scope_frontier.dag
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ data scope_carrier_paths: List<String> = [
"dag/extdeps/automation/playwright.dag",
"dag/extdeps/browser/chromium.dag",
"dag/extdeps/container/oci/digest.dag",
"dag/extdeps/git/publication_transport.dag",
"dag/extdeps/github/actions_environment.dag",
"dag/extdeps/os/debian.dag",
"dag/extdeps/tools/wc.dag",
Expand Down
128 changes: 128 additions & 0 deletions dag/gunbc/public_projection.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
module gunbc.public_projection

import std.types { CommitSha, FilePath, List, NonEmptyStr }
import std.content_hash {
ContentHash,
content_hash_atom,
content_hash_combine_structural,
content_hash_tagged,
serialize_content_hash,
as_content_hash_structural,
}
import gunbc.publication_policy {
AdmittedPublicationPolicy,
PublicationDisposition,
PublishPublic,
WithholdPrivate,
resolve_disposition_for_path,
}

data public_projection_note: String = "Derived public projection plan over authored subjects. Requires AdmittedPublicationPolicy from admit_publication_policy — illegal policies are unrepresentable on this path. Never the unrestricted authored tree and never a pathname census: policy resolves each subject's disposition, included_subjects carries only PublishPublic rows, omitted_subjects carries WithholdPrivate rows, and projection_digest fingerprints the admitted set."

type PublicationSubject {
subject_identity: ContentHash
content_identity: ContentHash
path: FilePath
}

type PublicProjectionPlan {
source_revision: CommitSha
policy_version: NonEmptyStr
included_subjects: List<PublicationSubject>
omitted_subjects: List<PublicationSubject>
projection_digest: ContentHash
}

fn publication_subject_digest(subject: PublicationSubject) -> ContentHash {
content_hash_tagged(
tag: "publication-subject",
payload: content_hash_combine_structural(
left: content_hash_atom(value: serialize_content_hash(hash: subject.subject_identity)),
right: content_hash_atom(value: serialize_content_hash(hash: subject.content_identity)),
),
)
}

fn projection_digest_from_subjects(subjects: List<PublicationSubject>) -> ContentHash {
let digests = map(subjects, subject => publication_subject_digest(subject: subject))
as_content_hash_structural(
structural: fold(
sort_by(digests, digest => serialize_content_hash(hash: digest) as String),
init: content_hash_atom(value: "public-projection" as NonEmptyStr),
f: fn(acc, digest) {
content_hash_combine_structural(
left: acc,
right: content_hash_atom(value: serialize_content_hash(hash: digest)),
)
},
)
)
}

type AuthoredSubjectPartition {
included: List<PublicationSubject>
omitted: List<PublicationSubject>
}

fn partition_authored_subjects(
admitted: AdmittedPublicationPolicy,
authored_subjects: List<PublicationSubject>,
) -> AuthoredSubjectPartition {
fold(
authored_subjects,
init: AuthoredSubjectPartition { included: [], omitted: [] },
f: fn(parts, subject) {
match resolve_disposition_for_path(
policy: admitted.policy,
path: subject.path,
) {
PublishPublic =>
AuthoredSubjectPartition {
included: append(parts.included, items: [subject]),
omitted: parts.omitted,
}
WithholdPrivate =>
AuthoredSubjectPartition {
included: parts.included,
omitted: append(parts.omitted, items: [subject]),
}
}
},
)
}

fn derive_public_projection_plan(
admitted: AdmittedPublicationPolicy,
source_revision: CommitSha,
authored_subjects: List<PublicationSubject>,
) -> PublicProjectionPlan {
let parts = partition_authored_subjects(
admitted: admitted,
authored_subjects: authored_subjects,
)
PublicProjectionPlan {
source_revision: source_revision,
policy_version: admitted.policy.version,
included_subjects: parts.included,
omitted_subjects: parts.omitted,
projection_digest: projection_digest_from_subjects(subjects: parts.included),
}
}

fn public_projection_includes_subject(
plan: PublicProjectionPlan,
subject_identity: ContentHash,
) -> Bool {
fold(plan.included_subjects, init: false, f: fn(found, subject) {
found || subject.subject_identity == subject_identity
})
}

fn public_projection_omits_subject(
plan: PublicProjectionPlan,
subject_identity: ContentHash,
) -> Bool {
fold(plan.omitted_subjects, init: false, f: fn(found, subject) {
found || subject.subject_identity == subject_identity
})
}
Loading
Loading