diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..173da3a1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @deepfates diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 00000000..f407ec31 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Something in Imp behaves differently than documented +labels: bug +--- + +## What you ran + +The smallest program, `mix` command or IEx session that shows it. Include the +signature or module if the behavior depends on it. + +## What you expected + +## What happened + +Paste the error, stacktrace or wrong output verbatim. + +## Versions + +- Imp (tag, branch or commit): +- Elixir (`elixir --version`): +- OTP: +- Provider, if the failure involves a model call: diff --git a/.github/actions/elixir-setup/action.yml b/.github/actions/elixir-setup/action.yml index f59dda93..2af715cf 100644 --- a/.github/actions/elixir-setup/action.yml +++ b/.github/actions/elixir-setup/action.yml @@ -78,14 +78,14 @@ outputs: runs: using: composite steps: - - uses: erlef/setup-beam@v1 + - uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 # v1.24.1 id: beam with: otp-version: "28" elixir-version: "1.19" - name: Cache Elixir deps and build (single writer) if: inputs.save-cache == 'true' - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | deps @@ -94,7 +94,7 @@ runs: key: mix-v4-${{ runner.os }}-otp${{ steps.beam.outputs.otp-version }}-elixir${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('mix.lock') }} - name: Restore Elixir deps and build (read-only) if: inputs.save-cache != 'true' - uses: actions/cache/restore@v4 + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | deps diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 883c8d7e..9a0d2fc5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,21 +1,19 @@ -## User Story +## What changed -What becomes possible or more reliable for an Imp user? +What becomes possible or more reliable for an Imp user, and what public +behavior changed. Name the upstream source or paper if one is involved. -## Semantic Contract +## How it was verified -Describe upstream fidelity, intentional Elixir-native behavior, and important -invariants. +Run `mix check` — it is the ordinary merge signal and it needs no credentials. +Paste the summary line. Run any further gate your change touches +(`mix protocol.check`, `mix package.check`, `mix quality.check`, +`mix dialyzer.check`); `CONTRIBUTING.md` lists them all. -## Evidence +Say what you could not run and why. Provider-backed, research-scale and +benchmark checks need credentials, datasets or spend: they are the +maintainer's to run, and an outside contributor is not expected to. -- [ ] Deterministic tests -- [ ] Integration or protocol tests where applicable -- [ ] Live/provider evidence where applicable -- [ ] ExDoc, guide, or Livebook updates -- [ ] `mix quality.check` +## Documentation -## External Evidence - -List any paper-scale, paid-provider, or external-service evidence and its -reproducible artifact. State clearly when it was not run. +Update ExDoc, guides or Livebooks alongside a public API change. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35310307..277212fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,6 +21,11 @@ concurrency: # documentation, static analysis, and the pinned upstream differential stay # separate because they exercise genuinely different environments. Research # campaigns and evidence receipts are not release gates. +# +# Every third-party action is pinned to a full commit SHA with its version tag +# in a trailing comment: a public repository runs workflows for outside +# contributors, and a moving tag is a moving dependency. Bump the SHA and the +# comment together. jobs: changes: @@ -30,8 +35,8 @@ jobs: code: ${{ steps.filter.outputs.code }} docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@v7 - - uses: dorny/paths-filter@v3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 id: filter with: filters: | @@ -56,7 +61,7 @@ jobs: name: check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -71,10 +76,10 @@ jobs: name: stranger.check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - - uses: erlef/setup-beam@v1 + - uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 # v1.24.1 with: otp-version: "28" elixir-version: "1.19" @@ -88,7 +93,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # Single writer of the mix deps/_build/~/.hex cache: this is the job @@ -108,7 +113,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -120,7 +125,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -132,7 +137,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -144,7 +149,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -159,7 +164,7 @@ jobs: # define the result. The updated PLT is then saved under the new exact # key. This job is the only writer of this cache. - name: Cache dialyzer PLTs - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: priv/plts key: plt-v1-${{ runner.os }}-otp${{ steps.setup.outputs.otp-version }}-elixir${{ steps.setup.outputs.elixir-version }}-${{ hashFiles('mix.lock') }} @@ -175,11 +180,11 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup - - uses: actions/setup-python@v5 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.12" # The :dspy_parity suite validates Imp against real pinned DSPy 3.2.1: @@ -222,7 +227,7 @@ jobs: # Code edits can break doc rendering and livebook validation too. if: needs.changes.outputs.docs == 'true' || needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup diff --git a/.github/workflows/evidence.yml b/.github/workflows/evidence.yml index 7ba176bc..5b6b40c1 100644 --- a/.github/workflows/evidence.yml +++ b/.github/workflows/evidence.yml @@ -22,7 +22,7 @@ jobs: name: evidence.venv-free runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup @@ -49,13 +49,13 @@ jobs: if: inputs.full runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/elixir-setup with: save-cache: "false" - - uses: actions/setup-python@v6 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.12" cache: "pip" @@ -63,7 +63,7 @@ jobs: scripts/setup_dspy_parity_env.sh scripts/setup_dspy_current_target.sh scripts/setup_reference_test_env.sh - - uses: denoland/setup-deno@v2 + - uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5 with: deno-version: v2.8.3 - name: Check out the pinned DSPy 3.2.1 source tree diff --git a/AGENTS.md b/AGENTS.md index 7443ef34..a8c3e575 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,9 @@ # Working on Imp -Read this before changing anything here. The workshop's `AGENTS.md` has the -idioms these repositories share; this file is what is specific to Imp. +Orientation for anyone — person or agent — changing this repository. +`CONTRIBUTING.md` has the gates and the development setup; `decisions.md` has +the rulings that are in force and the condition under which each retires. This +file is the design context those two assume. ## What Imp owns @@ -12,10 +14,10 @@ application rather than owning one. ## What Imp does not own -Product-specific characters, residents, accounts, inboxes, or chat threads. -Imp now includes the optional `Imp.ACP` program adapter and the generic -`Imp.MCP` tool integration. ExMCP owns both wire protocols. Imp owns typed -program/tool conversion and execution; Dwell and hosts own product lifetimes. +Product-specific characters, accounts, inboxes, or chat threads. Imp includes +the optional `Imp.ACP` program adapter and the generic `Imp.MCP` tool +integration; ExMCP owns both wire protocols. Imp owns typed program/tool +conversion and execution, and the host application owns product lifetimes. Ordinary Imp startup opens no protocol listeners or remote connections. ## The centre of the model @@ -26,13 +28,10 @@ around it, and persistence stores it as plain data. Thirty-three modules read it When something needs to know a program's shape, it should ask the signature rather than re-describe it. -This is the strongest instance of "declare once, derive everything" in the -constellation, and it is the pattern the other repositories are measured against. - ## Where the boundaries are half-declared -Imp has more `@callback` boundaries than any other repository here — and nearly -all of them return `{:error, term()}`. Some paths return bare strings +Imp has many `@callback` boundaries, and nearly all of them return +`{:error, term()}`. Some paths return bare strings (`{:error, "expected an LM module exporting generate/2"}`), which a caller cannot act on except by matching text. @@ -49,10 +48,9 @@ process-group lifecycle on raw ports: TERM, grace, KILL, and a check that the group is gone. The grace period is the requirement worth preserving — a trainer SIGKILLed mid-checkpoint loses work — and it is the reason Imp cannot simply adopt `ExMCP.Internal.OwnedProcess`, which stops the root process before -signalling and so can never deliver a handleable TERM. - -If that consolidation happens, graceful shutdown is a precondition, not a -follow-up. Until then this is a documented divergence rather than an accident. +signalling and so can never deliver a handleable TERM. If that consolidation +happens, graceful shutdown is a precondition, not a follow-up. Until then this is +a documented divergence rather than an accident. ## Protocol integration @@ -63,12 +61,13 @@ adds ACP presentation hints to that import; it is not another client. The shared ExMCP pin and its fork reasons live in `mix.exs`. `Imp.ACP` owns the default session/program adapter formerly shipped separately -as imp_acp. Its namespace stays stable, but consumers depend on Imp directly. -`docs/PRODUCTION_OPERATIONS.md` describes the MCP lifecycle/API migration. +as the `imp_acp` package. Its namespace stays stable, but consumers depend on +Imp directly. `docs/PRODUCTION_OPERATIONS.md` describes the MCP lifecycle and +API migration. ## Checks -`CONTRIBUTING.md` lists the gates. `mix check` is the default; provider-backed, -research-scale and evidence-infrastructure runs are deliberately separate -because they need credentials, datasets or spend. Keep that separation — a green -default run is not evidence about a fidelity claim. +`mix check` is the default merge signal and needs no credentials. Provider-backed +and research-scale runs are deliberately separate because they need credentials, +datasets or spend. Keep that separation — a green default run is not evidence +about a fidelity claim. diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..5a7a93c6 --- /dev/null +++ b/NOTICE @@ -0,0 +1,19 @@ +# NOTICE + +Imp is licensed under the MIT License; see `LICENSE`. + +Imp contains code ported from DSPy (https://github.com/stanfordnlp/dspy), +which is licensed under the MIT License: + + Copyright (c) 2023 Stanford Future Data Systems + +The following files are ports of DSPy source and carry that copyright +alongside Imp's own: + +- `lib/imp/optimizer/utils.ex` — ported from `dspy/teleprompt/utils.py` and + `dspy/teleprompt/bootstrap_trace.py`. +- `lib/imp/adapter/chat.ex` — its field-marker section parsing is ported line + for line from DSPy's chat adapter. + +Other modules name DSPy concepts or reproduce its semantics without copying +its source; those are independent implementations. diff --git a/README.md b/README.md index ff8c3588..0af252f8 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ rather than hand-editing prompts—to the BEAM. integrated protocol adapters — `Imp.ACP` and `Imp.MCP.connect/2`, absorbed from the retired `imp_acp` package — exist only on `main` until the next tag. Installing `v0.3.2` gives you the library described below without them; using -the adapters today means a local checkout of `main`. +the adapters today means depending on `main` (see [Install](#install)). Here, “typed” means required inputs are checked and model outputs are parsed and validated against the signature before application code receives them. @@ -131,13 +131,24 @@ decision. ## Install -Imp is not published to Hex. Install the private source release from its -immutable tag (GitHub credentials with access to the repository are required): +Imp is not published to Hex. It is installed from this public repository, at +an immutable tag, with no credentials: ```elixir {:imp, github: "deepfates/imp", tag: "v0.3.2"} ``` +That tag does not contain `Imp.ACP` or `Imp.MCP.connect/2`; a tag that does +will be cut. Until then, depend on `{:imp, github: "deepfates/imp", branch: +"main"}` if you need the adapters. + +ExMCP is declared `runtime: false`, so an OTP release that uses `Imp.ACP` or +`Imp.MCP` must list `applications: [ex_mcp: :load]` in its release definition; +see [protocol runtime in releases](docs/PRODUCTION_OPERATIONS.md#protocol-runtime-in-releases). + +Imp is MIT licensed (`LICENSE`); `NOTICE` records the upstream DSPy code two +modules are ported from. + Use `{:imp, path: "path/to/imp"}` only while developing against a local checkout. Imp requires Elixir `~> 1.19`. Commit your application's `mix.lock`; the Git tag fixes Imp's source, while normal Mix constraints may otherwise diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 63913202..fc3be01f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,8 +7,8 @@ selected program under OTP. ## Install -`v0.3.2` is a private Git source release. GitHub credentials with access to the -repository are required. +`v0.3.2` is a Git source release from a public repository; no credentials are +required. ```elixir {:imp, github: "deepfates/imp", tag: "v0.3.2"} diff --git a/decisions.md b/decisions.md index 6326b34f..7fc4d3f2 100644 --- a/decisions.md +++ b/decisions.md @@ -4,14 +4,13 @@ One line per ruling. Each names its source, its status, and the condition under which it stops applying. A reason marked *unverified* is stated in the source but has no retained failure or measurement behind it; treat it as a claim, not a fact. Dates are when the ruling entered this repository (from `git log`), -not necessarily when it was made. Workshop-wide rulings live in the workshop's -`AGENTS.md` and are repeated here only where Imp is affected. +not necessarily when it was made. | Date | Decision | Source and reason | Status | Retires when | | --- | --- | --- | --- | --- | | 2026-09-16 | `Imp.MCP.connect/2` drops a server it cannot connect only when the caller asks for it (`on_failure: :drop`), and even then only for a failed dial and a failed `tools/list`: an unauthorized descriptor, a declared `auth` that cannot produce a header, a malformed descriptor and anything the caller's `:tool_filter` raises still refuse the whole import. An absence carries the `index` of its descriptor, because a name is not an identity. | `lib/imp/mcp/connections.ex` moduledoc, `test/mcp_connection_test.exs`. A caller that needs every tool must not silently get a smaller catalog; the refusals are answers the caller gave before anything was dialed, or the caller's own code failing; and a caller told only a name cannot tell which of two descriptors under it was left out. | In force. | Does not retire. | | 2026-09-16 | Each MCP dial is bounded by `:timeout` on its own, and a dial abandoned at that deadline is killed together with the half-open client it is linked to. | `lib/imp/mcp/connections.ex` `dial/2` and `abandon/1`, `test/mcp_connection_test.exs`. A host that accepts the connection and answers nothing returns within neither `:handshake_timeout` nor `:era_probe_timeout`, so one budget for the whole list refused imports that `:drop` exists to let through; and `ExMCP.Client` traps exits and ignores the `EXIT` from the process that started it, so a killed dial left a live client holding a socket. | In force. | ExMCP bounds its own handshake and closes a client whose starter dies. | -| 2026-08-23 | Imp is not published to Hex; each release is a private immutable Git tag (`v0.3.x`) installed with `{:imp, github: "deepfates/imp", tag: ...}`. | `README.md` Install, `docs/maintainers/RELEASE.md`. `mix hex.build` refuses the Git ExMCP dependency, so `mix package.check` cannot establish Hex publishability; publication is an owner action. | In force. | ExMCP is consumable as a released Hex package and the owner chooses to publish. | +| 2026-08-23 | Imp is not published to Hex; each release is a private immutable Git tag (`v0.3.x`) installed with `{:imp, github: "deepfates/imp", tag: ...}`. | `README.md` Install, `docs/maintainers/RELEASE.md`. `mix hex.build` refuses the Git ExMCP dependency, so `mix package.check` cannot establish Hex publishability; publication is an owner action. | Amended 2026-09-17: the repository is public, so the tags are public and need no credentials; whether to publish to Hex is still open. | ExMCP is consumable as a released Hex package and the owner chooses to publish. | | 2026-09-13 | An ACP tool kind is derived from the MCP `ToolAnnotations` the server declares, not from a host table keyed by tool name; a tool that declares no hint gets `nil` rather than a guess, and an explicit `:tool_kinds` entry still wins. | `lib/imp/acp/tool_kind.ex` moduledoc, `test/acp_options_tool_kinds_test.exs`. A name table goes stale the moment a server publishes a tool it does not name, and that is exactly when a permission mode that would have asked does not ask. | In force. | Does not retire. | | 2026-09-13 | On `session/load` and `session/resume` the session is installed with the `_meta` it was created with, not the `_meta` the request carried; both are passed to the program factory as `:meta` and `:requested_meta`. | `lib/imp/acp.ex` moduledoc, `test/acp_imp_acp_test.exs`. A session's history and transcript belong to the configuration that produced them, so a resume that silently adopts a different one replays one configuration's transcript as another's; only the factory knows which of its own `_meta` keys are identity-bearing, so it is given both and decides whether to refuse. | In force. | Does not retire. | | 2026-09-13 | `Imp.ACP` (the ACP session/program adapter) is part of Imp; the separate `imp_acp` package is retired with no compatibility shim and no second implementation. | Retired `imp_acp` README, `AGENTS.md`. One protocol stack, one owner of the ExMCP dependency. | In force on `main`; **not in `v0.3.2`** (the released tag predates absorption). | The "unreleased" caveat retires at the next tag. The absorption itself does not retire. | diff --git a/examples/deployment/README.md b/examples/deployment/README.md index 0ad32109..2e46fc5e 100644 --- a/examples/deployment/README.md +++ b/examples/deployment/README.md @@ -24,8 +24,8 @@ IMP_PATH=../.. mix deps.get IMP_PATH=../.. mix run --no-start run_workflow.exs ``` -A copied application with access to the private repository can omit `IMP_PATH` -and resolve the immutable `v0.3.2` Git dependency declared in `mix.exs`. +A copied application can omit `IMP_PATH` and resolve the immutable `v0.3.2` +Git dependency declared in `mix.exs`. The workflow: @@ -149,6 +149,5 @@ Use a whole-program artifact for a supported portable Imp shape. Use `Imp.Optimizer.Artifact` when the application owns a custom program and only its selected predictor parameters should cross the persistence boundary. -During source development set `IMP_PATH` to the Imp checkout. Applications -with access to the private repository use the tagged Git dependency in -`mix.exs`. +During source development set `IMP_PATH` to the Imp checkout. Other +applications use the tagged Git dependency in `mix.exs`. diff --git a/livebooks/01_real_lm_front_door.livemd b/livebooks/01_real_lm_front_door.livemd index 7eb0fd55..67104c05 100644 --- a/livebooks/01_real_lm_front_door.livemd +++ b/livebooks/01_real_lm_front_door.livemd @@ -29,7 +29,7 @@ if repo do Mix.install([{:imp, path: repo}], install_opts) else - # Standalone notebook: install the private source release. + # Standalone notebook: install the tagged Git source release. Mix.install([{:imp, github: "deepfates/imp", tag: "v0.3.2"}]) end diff --git a/livebooks/02_programming_not_prompting.livemd b/livebooks/02_programming_not_prompting.livemd index 9790f4a2..e3ce8960 100644 --- a/livebooks/02_programming_not_prompting.livemd +++ b/livebooks/02_programming_not_prompting.livemd @@ -29,7 +29,7 @@ if repo do Mix.install([{:imp, path: repo}], install_opts) else - # Standalone notebook: install the private source release. + # Standalone notebook: install the tagged Git source release. Mix.install([{:imp, github: "deepfates/imp", tag: "v0.3.2"}]) end live_provider_enabled? = System.get_env("LIVE_PROVIDER") == "1" diff --git a/livebooks/03_evaluate_and_optimize.livemd b/livebooks/03_evaluate_and_optimize.livemd index 9fb7b294..c6b015b9 100644 --- a/livebooks/03_evaluate_and_optimize.livemd +++ b/livebooks/03_evaluate_and_optimize.livemd @@ -29,7 +29,7 @@ if repo do Mix.install([{:imp, path: repo}], install_opts) else - # Standalone notebook: install the private source release. + # Standalone notebook: install the tagged Git source release. Mix.install([{:imp, github: "deepfates/imp", tag: "v0.3.2"}]) end live_provider_enabled? = System.get_env("LIVE_PROVIDER") == "1" diff --git a/livebooks/04_tools_agents_mcp_rlm.livemd b/livebooks/04_tools_agents_mcp_rlm.livemd index ebf69b55..1414bcec 100644 --- a/livebooks/04_tools_agents_mcp_rlm.livemd +++ b/livebooks/04_tools_agents_mcp_rlm.livemd @@ -29,7 +29,7 @@ if repo do Mix.install([{:imp, path: repo}], install_opts) else - # Standalone notebook: install the private source release. + # Standalone notebook: install the tagged Git source release. Mix.install([{:imp, github: "deepfates/imp", tag: "v0.3.2"}]) end live_provider_enabled? = System.get_env("LIVE_PROVIDER") == "1" diff --git a/livebooks/05_operate_and_live_checks.livemd b/livebooks/05_operate_and_live_checks.livemd index 8b82c7e1..7c47384c 100644 --- a/livebooks/05_operate_and_live_checks.livemd +++ b/livebooks/05_operate_and_live_checks.livemd @@ -29,7 +29,7 @@ if repo do Mix.install([{:imp, path: repo}], install_opts) else - # Standalone notebook: install the private source release. + # Standalone notebook: install the tagged Git source release. Mix.install([{:imp, github: "deepfates/imp", tag: "v0.3.2"}]) end live_provider_enabled? = System.get_env("LIVE_PROVIDER") == "1" diff --git a/mix.exs b/mix.exs index 0cbe7081..7b2241e3 100644 --- a/mix.exs +++ b/mix.exs @@ -212,6 +212,7 @@ defmodule Imp.MixProject do ".formatter.exs", "CHANGELOG.md", "LICENSE", + "NOTICE", "RELEASE_NOTES.md", "assets/imp-with-cards.jpg", "priv/public_api.json", diff --git a/test/package_contract_test.exs b/test/package_contract_test.exs index 7a480aee..79b6cade 100644 --- a/test/package_contract_test.exs +++ b/test/package_contract_test.exs @@ -25,6 +25,7 @@ defmodule PackageContractTest do "priv/public_api.json", "CHANGELOG.md", "LICENSE", + "NOTICE", "RELEASE_NOTES.md", "README.md", "docs/IMP_FOR_DSPY_USERS.md", @@ -41,6 +42,7 @@ defmodule PackageContractTest do "CHANGELOG.md", "CONTRIBUTING.md", "LICENSE", + "NOTICE", "SECURITY.md", ".github/dependabot.yml", ".github/pull_request_template.md", @@ -315,7 +317,7 @@ defmodule PackageContractTest do assert unavailable == [] end - test "README gives the usable private source install" do + test "README gives the usable source install" do readme = File.read!("README.md") version = Mix.Project.config()[:version]