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
2 changes: 1 addition & 1 deletion cmd/harness/cli/commands/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ func NewInstallCommand() *cobra.Command {
},
}

cmd.Flags().String("bindings", "", "Path to an explicit bindings YAML file")
cmd.Flags().String("bindings", "", "Path to a Runtime Bindings YAML file")
cmd.Flags().String("ref", "", "Select one template branch explicitly when installing from an external Git source")
cmd.Flags().Bool("overwrite-existing", false, "Allow overwriting an existing install-backed orbit and removing stale install-owned files")
cmd.Flags().StringSlice("override", nil, "Explicitly transfer ownership of one or more existing orbit members from another install unit")
Expand Down
2 changes: 2 additions & 0 deletions cmd/hyard/cli/cli_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ func TestHyardHelpShowsUserLayerHeadlineAndPlumbingEntry(t *testing.T) {
require.Contains(t, stdout, "status")
require.Contains(t, stdout, "agent")
require.Contains(t, stdout, "guide")
require.Contains(t, stdout, "vars")
require.Contains(t, stdout, "hyard vars init docs --out .harness/vars.yaml")
require.Contains(t, stdout, "plumbing")
require.NotContains(t, stdout, "framework")
}
Expand Down
4 changes: 4 additions & 0 deletions cmd/hyard/cli/install_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ func TestHyardInstallHelpShowsYankedOverride(t *testing.T) {
require.Empty(t, stderr)
require.Contains(t, stdout, "--allow-yanked")
require.Contains(t, stdout, "yanked")
require.Contains(t, stdout, "--bindings string")
require.Contains(t, stdout, "Runtime Bindings YAML file")
require.NotContains(t, stdout, "--strict-bindings")
require.NotContains(t, stdout, "--allow-unresolved-bindings")
}

type packageHandleInstallFixture struct {
Expand Down
1 change: 1 addition & 0 deletions cmd/hyard/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func NewRootCommand() *cobra.Command {
" hyard create runtime demo-repo\n" +
" hyard create source ./research-source --orbit research\n" +
" hyard clone ../starter-template --ref harness-template/workspace\n" +
" hyard vars init docs --out .harness/vars.yaml\n" +
" hyard install docs --bindings .harness/vars.yaml\n" +
" hyard current\n" +
" hyard enter docs\n" +
Expand Down
11 changes: 10 additions & 1 deletion cmd/hyard/cli/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,16 @@ func newVarsCommand() *cobra.Command {
Use: "vars",
Short: "Manage Runtime Bindings",
Long: "Manage Runtime Bindings for Package Variables.\n" +
"The canonical Runtime Bindings file is .harness/vars.yaml.",
"The canonical Runtime Bindings file is .harness/vars.yaml.\n" +
"Runtime Bindings use schema_version: 2 and satisfy Package Variables\n" +
"referenced by strict {{ vars.<name> }} Package Template References.",
Example: "" +
" hyard vars path\n" +
" hyard vars init <package-source> --out .harness/vars.yaml\n" +
" hyard vars init <package-source> --defaults\n" +
" hyard vars validate\n" +
" hyard vars doctor\n" +
" hyard vars explain project_name\n",
Args: cobra.NoArgs,
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/hyard/cli/vars_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ func TestHyardVarsPathReportsCanonicalRuntimeBindingsPath(t *testing.T) {
require.Equal(t, ".harness/vars.yaml\n", stdout)
}

func TestHyardVarsHelpTeachesPublicRuntimeBindingsSurface(t *testing.T) {
t.Parallel()

stdout, stderr, err := executeHyardCLI(t, t.TempDir(), "vars", "--help")
require.NoError(t, err)
require.Empty(t, stderr)
require.Contains(t, stdout, "Runtime Bindings")
require.Contains(t, stdout, ".harness/vars.yaml")
require.Contains(t, stdout, "schema_version: 2")
require.Contains(t, stdout, "hyard vars init <package-source>")
require.Contains(t, stdout, "{{ vars.<name> }}")
require.NotContains(t, stdout, ".orbit/vars.yaml")
require.NotContains(t, stdout, "$name")
require.NotContains(t, stdout, "--strict-bindings")
require.NotContains(t, stdout, "--allow-unresolved-bindings")
}

func TestHyardVarsValidateAcceptsSchema2RuntimeBindings(t *testing.T) {
t.Parallel()

Expand Down
19 changes: 19 additions & 0 deletions docs/guides/harness-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,28 @@ owned bindings usually belong in:
Install packages with explicit bindings when variables are required:

```bash
hyard vars init acme/docs --out .harness/vars.yaml
hyard install <package-source> --bindings .harness/vars.yaml
```

Runtime Bindings use schema `2`:

```yaml
schema_version: 2
variables:
project_name:
value: Harness Yard Docs
github_token:
value_from:
env: GITHUB_TOKEN
```

Package Variables are referenced from package-owned runtime files with strict
`{{ vars.project_name }}` Package Template References. Declaration defaults
satisfy required Package Variables without writing a Runtime Binding unless the
user explicitly asks `hyard vars init --defaults` to materialize defaults.
Sensitive Package Variables should use `value_from.env`.

Zero variables is a complete contract. Do not add placeholder bindings just to
make a file look complete.

Expand Down
30 changes: 30 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,36 @@ verified bare or `latest` resolution with a stale cached resolution warning.
Set `HYARD_CACHE_DIR` only when you need to relocate or inspect the user-level
registry cache while troubleshooting.

### Runtime Bindings

Packages may declare Package Variables that must be supplied by the runtime.
Runtime Bindings live in `.harness/vars.yaml` and use schema `2`.

Create a skeleton from a package before installing when required values are
missing:

```bash
hyard vars init acme/docs --out .harness/vars.yaml
hyard vars validate
hyard install acme/docs --bindings .harness/vars.yaml
```

The skeleton uses the public Runtime Bindings shape:

```yaml
schema_version: 2
variables:
project_name:
value: Harness Yard Docs
github_token:
value_from:
env: GITHUB_TOKEN
```

Package-owned runtime files reference Package Variables with strict Package
Template References such as `{{ vars.project_name }}`. Missing required Runtime
Bindings block installation before package-owned runtime files are written.

Maintainer-level registry behavior is documented in
`docs/maintainers/package-registry-source-contract.md`.

Expand Down
14 changes: 7 additions & 7 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,22 +136,22 @@ bindings YAML schema.
The public Runtime Bindings document starts at `schema_version: 2`. It supports
inline `value` bindings and explicit `value_from.env` or `value_from.file`
sources. Scoped Bindings use `scoped_variables.<namespace>.variables`, where the
namespace is the installed package or orbit namespace. Pre-release schema `1`
documents and scalar shorthand are not part of the public configuration
namespace is the installed package or orbit namespace. Earlier pre-release
Runtime Bindings document shapes are not part of the public configuration
contract. Package-owned runtime files reference Package Variables with
`{{ vars.<name> }}`; `vars` is the only initial template namespace, and
unsupported namespaces fail rendering. Pre-release `$name` shorthand is not part
of the public template contract. Rendering is strict: unsupported namespaces,
unknown `vars.*` references, unresolved declared variables, and malformed
Harness Yard template syntax block package-owned runtime writes. GitHub Actions
unsupported namespaces fail rendering. Earlier shorthand template references are
not part of the public template contract. Rendering is strict: unsupported
namespaces, unknown `vars.*` references, unresolved declared variables, and
malformed Harness Yard template syntax block package-owned runtime writes. GitHub Actions
`${{ ... }}` expressions are not Harness Yard template references. Sensitive
Package Variables may only use `value_from.env` in the initial public contract;
inline `value` and `value_from.file` are rejected for sensitive declarations,
and sensitive declarations may not define defaults.
Declaration defaults are fallbacks, not Runtime Bindings; they satisfy required
variables only when no scoped or global binding is present. Required Package
Variables are strict by default: missing Runtime Bindings block package
installation instead of writing unresolved placeholders. Interactive installs
installation before package-owned runtime files are written. Interactive installs
may prompt for missing required Runtime Bindings and persist them to
`.harness/vars.yaml`; non-interactive installs fail with `hyard vars init`
recovery guidance.
Expand Down
39 changes: 38 additions & 1 deletion scripts/test_release_surface_hyard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ install_script="$repo_root/install.sh"
goreleaser_config="$repo_root/.goreleaser.yaml"
hyard_install_cmd="$repo_root/cmd/hyard/cli/install.go"
hyard_registry_cmd="$repo_root/cmd/hyard/cli/registry.go"
hyard_vars_cmd="$repo_root/cmd/hyard/cli/vars.go"
harness_install_cmd="$repo_root/cmd/harness/cli/commands/install.go"

for doc in \
"$quickstart_doc" \
Expand All @@ -107,7 +109,9 @@ for doc in \
"$install_script" \
"$goreleaser_config" \
"$hyard_install_cmd" \
"$hyard_registry_cmd"
"$hyard_registry_cmd" \
"$hyard_vars_cmd" \
"$harness_install_cmd"
do
assert_file_exists "$doc"
done
Expand Down Expand Up @@ -140,6 +144,12 @@ assert_contains "$quickstart_doc" "hyard install acme/frontend-lab"
assert_contains "$quickstart_doc" "hyard install acme/docs"
assert_contains "$quickstart_doc" "hyard install acme/docs@0.1.0"
assert_contains "$quickstart_doc" "hyard install docs"
assert_contains "$quickstart_doc" "### Runtime Bindings"
assert_contains "$quickstart_doc" "hyard vars init acme/docs --out .harness/vars.yaml"
assert_contains "$quickstart_doc" "schema_version: 2"
assert_contains "$quickstart_doc" "{{ vars.project_name }}"
assert_contains "$quickstart_doc" "Runtime Bindings"
assert_contains "$quickstart_doc" "Package Variables"
assert_contains "$quickstart_doc" 'Package Handle Coordinates are case-insensitive'
assert_contains "$quickstart_doc" 'Use `namespace/name[@version-or-tag]`, not npm-style `@namespace/name`.'
assert_contains "$quickstart_doc" 'Bare handles such as `docs` are curated aliases'
Expand Down Expand Up @@ -198,6 +208,10 @@ assert_not_contains "$quickstart_doc" 'export ORBIT_BIN="$ORBIT_BIN_DIR/orbit"'
assert_not_contains "$quickstart_doc" 'export HARNESS_BIN="$ORBIT_BIN_DIR/harness"'
assert_not_contains "$quickstart_doc" '"$ORBIT_BIN" branch list --json'
assert_not_contains "$quickstart_doc" '"$HARNESS_BIN" install "$TEMPLATE_REPO"'
assert_not_contains "$quickstart_doc" ".orbit/vars.yaml"
assert_not_contains "$quickstart_doc" '$project_name'
assert_not_contains "$quickstart_doc" "--strict-bindings"
assert_not_contains "$quickstart_doc" "--allow-unresolved-bindings"

assert_contains "$concepts_doc" "# Harness Yard Concepts"
assert_contains "$concepts_doc" "A Harness Yard revision is a Git worktree revision with exactly one revision"
Expand All @@ -214,6 +228,11 @@ assert_contains "$configuration_doc" ".harness/orbits/*.yaml"
assert_contains "$configuration_doc" "Deleted records and retained Git history are not active install state."
assert_contains "$configuration_doc" 'Supported fields are `name`, `description`, `role`, and `lane`'
assert_contains "$configuration_doc" "hyard orbit content apply <package> --check --json"
assert_contains "$configuration_doc" "hyard vars init"
assert_contains "$configuration_doc" "schema_version: 2"
assert_contains "$configuration_doc" "{{ vars.<name> }}"
assert_contains "$configuration_doc" "Rendering is strict"
assert_not_contains "$configuration_doc" ".orbit/vars.yaml"
assert_contains "$configuration_doc" "## Audit, Check, And Prepare"
assert_contains "$configuration_doc" 'Audit statuses are `pass`,'
assert_contains "$configuration_doc" 'A dirty but otherwise valid worktree is an'
Expand All @@ -229,6 +248,11 @@ assert_contains "$harness_authoring_doc" "# Harness Authoring"
assert_contains "$harness_authoring_doc" "hyard publish harness workspace"
assert_contains "$harness_authoring_doc" "hyard install acme/frontend-lab"
assert_contains "$harness_authoring_doc" "hyard install acme/docs --bindings .harness/vars.yaml"
assert_contains "$harness_authoring_doc" "hyard vars init acme/docs --out .harness/vars.yaml"
assert_contains "$harness_authoring_doc" "schema_version: 2"
assert_contains "$harness_authoring_doc" "{{ vars.project_name }}"
assert_contains "$harness_authoring_doc" "Runtime Bindings"
assert_contains "$harness_authoring_doc" "Package Variables"
assert_contains "$harness_authoring_doc" "Explicit Git locators are"
assert_contains "$harness_authoring_doc" "hyard registry entry harness acme/workspace@0.1.0 --source origin --ref harness-template/workspace --package workspace"
assert_contains "$harness_authoring_doc" "hyard assign orbit <orbit-package>"
Expand Down Expand Up @@ -272,6 +296,12 @@ assert_contains "$release_surface_doc" "hyard install <curated-name>"
assert_contains "$release_surface_doc" "hyard install acme/docs"
assert_contains "$release_surface_doc" "hyard install acme/docs@0.1.0"
assert_contains "$release_surface_doc" "hyard install docs"
assert_contains "$release_surface_doc" "## Runtime Bindings Surface"
assert_contains "$release_surface_doc" "hyard vars init <package-source>"
assert_contains "$release_surface_doc" "schema_version: 2"
assert_contains "$release_surface_doc" "{{ vars.project_name }}"
assert_contains "$release_surface_doc" "Package Template Reference rendering is strict"
assert_contains "$release_surface_doc" "hyard vars init --defaults"
assert_contains "$release_surface_doc" 'Package Handle Coordinates are case-insensitive'
assert_contains "$release_surface_doc" 'not npm-style `@namespace/name`'
assert_contains "$release_surface_doc" 'Explicit Git locators are the advanced escape hatch'
Expand Down Expand Up @@ -374,13 +404,20 @@ assert_contains "$hyard_install_cmd" "hyard install acme/docs@0.1.0"
assert_contains "$hyard_install_cmd" "registry-source"
assert_contains "$hyard_install_cmd" "allow-yanked"

assert_contains "$harness_install_cmd" "Runtime Bindings YAML file"
assert_contains "$harness_install_cmd" "hideInstallBindingCompatibilityFlags(cmd)"

assert_contains "$hyard_registry_cmd" "Generate an Orbit Package Registry Entry Candidate"
assert_contains "$hyard_registry_cmd" "Generate a Harness Package Registry Entry Candidate"
assert_contains "$hyard_registry_cmd" "hyard registry entry orbit acme/docs@0.1.0"
assert_contains "$hyard_registry_cmd" "hyard registry entry harness acme/workspace@0.1.0"
assert_contains "$hyard_registry_cmd" "--out"
assert_contains "$hyard_registry_cmd" "--registry"

assert_contains "$hyard_vars_cmd" "Manage Runtime Bindings"
assert_contains "$hyard_vars_cmd" "schema_version: 2"
assert_contains "$hyard_vars_cmd" "{{ vars.<name> }}"

if command -v goreleaser >/dev/null 2>&1; then
(
cd "$repo_root"
Expand Down
Loading