@aaac/contracts 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1570,11 +1570,121 @@ async function writeGeneratedFiles(files, outputDir) {
1570
1570
 
1571
1571
  // src/cli/governance.ts
1572
1572
  import { createHash } from "crypto";
1573
+ import { existsSync as existsSync3 } from "fs";
1574
+ import { chmod, mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
1575
+ import { dirname as dirname6, join as join4, resolve as resolve4 } from "path";
1576
+ import { parse as parseYaml4 } from "yaml";
1577
+ import { z as z3 } from "zod";
1578
+
1579
+ // src/cli/observ-config.ts
1573
1580
  import { existsSync as existsSync2 } from "fs";
1574
- import { chmod, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
1581
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
1575
1582
  import { dirname as dirname5, join as join3, resolve as resolve3 } from "path";
1576
1583
  import { parse as parseYaml3 } from "yaml";
1577
1584
  import { z as z2 } from "zod";
1585
+ var OBSERV_CONFIG_DIR = ".agent-logs/config";
1586
+ var EVENT_MAPPING_JSON = `${OBSERV_CONFIG_DIR}/event-mapping.json`;
1587
+ var ARTIFACT_LOOKUP_JSON = `${OBSERV_CONFIG_DIR}/artifact-lookup.json`;
1588
+ var TASK_PATTERNS_JSON = `${OBSERV_CONFIG_DIR}/task-patterns.json`;
1589
+ function generateTaskPatterns() {
1590
+ return [
1591
+ { tag_prefix: "DSL_TASK", field: "task.id" },
1592
+ { tag_prefix: "AGENT_ROLE", field: "task.target_agent" },
1593
+ { tag_prefix: "WORKFLOW_PHASE", field: "workflow.phase" }
1594
+ ];
1595
+ }
1596
+ function generateArtifactLookup(artifactDeclarations) {
1597
+ const patterns = [];
1598
+ for (const decl of artifactDeclarations) {
1599
+ for (const pattern of decl.path_patterns) {
1600
+ patterns.push({ artifact_id: decl.artifact_id, pattern });
1601
+ }
1602
+ }
1603
+ return patterns;
1604
+ }
1605
+ function extractEventMappingRules(parsed) {
1606
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1607
+ const obj = parsed;
1608
+ const rules = obj.event_mapping ?? obj.mappings;
1609
+ if (rules && typeof rules === "object") {
1610
+ return rules;
1611
+ }
1612
+ }
1613
+ return {};
1614
+ }
1615
+ var ArtifactContractsSchema = z2.object({
1616
+ artifacts: z2.record(
1617
+ z2.string(),
1618
+ z2.object({ path_patterns: z2.array(z2.string()).optional() }).passthrough()
1619
+ ).optional()
1620
+ });
1621
+ function parseArtifactDeclarations(parsed) {
1622
+ const { artifacts } = ArtifactContractsSchema.parse(parsed ?? {});
1623
+ if (!artifacts) return [];
1624
+ const decls = [];
1625
+ for (const [artifact_id, decl] of Object.entries(artifacts)) {
1626
+ if (decl.path_patterns && decl.path_patterns.length > 0) {
1627
+ decls.push({ artifact_id, path_patterns: decl.path_patterns });
1628
+ }
1629
+ }
1630
+ return decls;
1631
+ }
1632
+ function serialize(value) {
1633
+ return JSON.stringify(value, null, 2) + "\n";
1634
+ }
1635
+ async function writeJsonIfChanged(absPath, value) {
1636
+ const serialized = serialize(value);
1637
+ const existed = existsSync2(absPath);
1638
+ const existing = existed ? await readFile2(absPath, "utf8") : void 0;
1639
+ if (existing === serialized) {
1640
+ return "unchanged";
1641
+ }
1642
+ await mkdir2(dirname5(absPath), { recursive: true });
1643
+ await writeFile2(absPath, serialized, "utf8");
1644
+ return existed ? "updated" : "created";
1645
+ }
1646
+ async function generateObservConfig(options) {
1647
+ const root = resolve3(options.projectRoot);
1648
+ const generated = [];
1649
+ if (options.eventMapping) {
1650
+ const bindingPath = resolve3(root, options.eventMapping);
1651
+ if (existsSync2(bindingPath)) {
1652
+ const parsed = parseYaml3(await readFile2(bindingPath, "utf8"));
1653
+ const mappings = extractEventMappingRules(parsed);
1654
+ const action = await writeJsonIfChanged(
1655
+ join3(root, EVENT_MAPPING_JSON),
1656
+ { mappings }
1657
+ );
1658
+ generated.push({ path: EVENT_MAPPING_JSON, action });
1659
+ }
1660
+ }
1661
+ if (options.artifactContracts) {
1662
+ const contractsPath = resolve3(root, options.artifactContracts);
1663
+ if (existsSync2(contractsPath)) {
1664
+ const parsed = parseYaml3(await readFile2(contractsPath, "utf8"));
1665
+ const lookup = generateArtifactLookup(parseArtifactDeclarations(parsed));
1666
+ const action = await writeJsonIfChanged(
1667
+ join3(root, ARTIFACT_LOOKUP_JSON),
1668
+ lookup
1669
+ );
1670
+ generated.push({ path: ARTIFACT_LOOKUP_JSON, action });
1671
+ }
1672
+ }
1673
+ {
1674
+ const action = await writeJsonIfChanged(
1675
+ join3(root, TASK_PATTERNS_JSON),
1676
+ generateTaskPatterns()
1677
+ );
1678
+ generated.push({ path: TASK_PATTERNS_JSON, action });
1679
+ }
1680
+ const lockEntries = generated.map((g) => ({
1681
+ path: g.path,
1682
+ type: "generated"
1683
+ }));
1684
+ return { generated, lockEntries };
1685
+ }
1686
+
1687
+ // src/cli/governance.ts
1578
1688
  var MANAGED_BLOCK_START = "# >>> aaac-governance:managed (do not edit) >>>";
1579
1689
  var MANAGED_BLOCK_END = "# <<< aaac-governance:managed <<<";
1580
1690
  var GOVERNANCE_LOCK_PATH = ".agent-logs/governance-manifest.lock";
@@ -1582,44 +1692,45 @@ var DEFAULT_RECORDER = ".cursor/hooks/observ-record.sh";
1582
1692
  var DEFAULT_CURSOR_HOOKS_JSON = ".cursor/hooks.json";
1583
1693
  var DEFAULT_BINARY_DEST = "bin/aaac.js";
1584
1694
  var CURSOR_HOOKS_VERSION = 1;
1585
- var EnvironmentsSchema = z2.object({
1586
- git: z2.object({ hooks: z2.array(z2.string()).optional() }).optional(),
1587
- cursor: z2.object({ hooks_json: z2.string().optional() }).optional()
1695
+ var EnvironmentsSchema = z3.object({
1696
+ git: z3.object({ hooks: z3.array(z3.string()).optional() }).optional(),
1697
+ cursor: z3.object({ hooks_json: z3.string().optional() }).optional()
1588
1698
  }).optional();
1589
- var BindingsObservabilitySchema = z2.object({
1590
- event_mapping: z2.string().optional(),
1591
- recorder: z2.string().optional()
1699
+ var BindingsObservabilitySchema = z3.object({
1700
+ event_mapping: z3.string().optional(),
1701
+ recorder: z3.string().optional()
1592
1702
  }).optional();
1593
- var BindingsSchema = z2.object({
1703
+ var BindingsSchema = z3.object({
1594
1704
  observability: BindingsObservabilitySchema,
1595
- hooks: z2.array(z2.string()).optional()
1705
+ hooks: z3.array(z3.string()).optional()
1596
1706
  }).optional();
1597
- var InitProjectConfigSchema = z2.object({
1707
+ var InitProjectConfigSchema = z3.object({
1598
1708
  environments: EnvironmentsSchema,
1599
- bindings: BindingsSchema
1709
+ bindings: BindingsSchema,
1710
+ artifacts: z3.string().optional()
1600
1711
  });
1601
1712
  async function loadInitConfig(configPath) {
1602
- const absPath = resolve3(configPath);
1603
- const raw = await readFile2(absPath, "utf8");
1604
- const parsed = parseYaml3(raw);
1713
+ const absPath = resolve4(configPath);
1714
+ const raw = await readFile3(absPath, "utf8");
1715
+ const parsed = parseYaml4(raw);
1605
1716
  return InitProjectConfigSchema.parse(parsed ?? {});
1606
1717
  }
1607
- var HookCommandSchema = z2.object({
1608
- command: z2.string(),
1609
- description: z2.string().optional()
1718
+ var HookCommandSchema = z3.object({
1719
+ command: z3.string(),
1720
+ description: z3.string().optional()
1610
1721
  });
1611
- var HookBindingSchema = z2.object({
1612
- hooks: z2.record(z2.string(), z2.array(HookCommandSchema)).optional()
1722
+ var HookBindingSchema = z3.object({
1723
+ hooks: z3.record(z3.string(), z3.array(HookCommandSchema)).optional()
1613
1724
  });
1614
1725
  async function loadHookBindings(projectRoot, bindingPaths) {
1615
1726
  const result = {};
1616
1727
  if (!bindingPaths?.length) return result;
1617
- const root = resolve3(projectRoot);
1728
+ const root = resolve4(projectRoot);
1618
1729
  for (const bindingPath of bindingPaths) {
1619
- const absPath = resolve3(root, bindingPath);
1620
- if (!existsSync2(absPath)) continue;
1621
- const raw = await readFile2(absPath, "utf8");
1622
- const parsed = HookBindingSchema.parse(parseYaml3(raw) ?? {});
1730
+ const absPath = resolve4(root, bindingPath);
1731
+ if (!existsSync3(absPath)) continue;
1732
+ const raw = await readFile3(absPath, "utf8");
1733
+ const parsed = HookBindingSchema.parse(parseYaml4(raw) ?? {});
1623
1734
  if (!parsed.hooks) continue;
1624
1735
  for (const [hookName, commands] of Object.entries(parsed.hooks)) {
1625
1736
  const list = result[hookName] ?? [];
@@ -1746,44 +1857,58 @@ function buildGitHookBlock(hookName, recorder, gateCommands = []) {
1746
1857
  }
1747
1858
  return lines.join("\n");
1748
1859
  }
1860
+ var DEFAULT_CURSOR_HOOK_EVENTS = [
1861
+ "sessionStart",
1862
+ "sessionEnd",
1863
+ "subagentStart",
1864
+ "subagentStop",
1865
+ "beforeSubmitPrompt",
1866
+ "afterShellExecution",
1867
+ "preToolUse",
1868
+ "postToolUse",
1869
+ "postToolUseFailure",
1870
+ "afterFileEdit",
1871
+ "preCompact",
1872
+ "stop"
1873
+ ];
1749
1874
  function buildDefaultCursorHooks(recorder) {
1750
- return [
1751
- { event: "beforeSubmitPrompt", command: `${recorder} beforeSubmitPrompt` },
1752
- { event: "afterShellExecution", command: `${recorder} afterShellExecution` }
1753
- ];
1875
+ return DEFAULT_CURSOR_HOOK_EVENTS.map((event) => ({
1876
+ event,
1877
+ command: `${recorder} ${event}`
1878
+ }));
1754
1879
  }
1755
1880
  async function ensureParentDir(filePath) {
1756
- await mkdir2(dirname5(filePath), { recursive: true });
1881
+ await mkdir3(dirname6(filePath), { recursive: true });
1757
1882
  }
1758
1883
  async function readTextFileIfExists(filePath) {
1759
- if (!existsSync2(filePath)) return void 0;
1760
- return readFile2(filePath, "utf8");
1884
+ if (!existsSync3(filePath)) return void 0;
1885
+ return readFile3(filePath, "utf8");
1761
1886
  }
1762
1887
  async function writeGovernanceLock(projectRoot, entries) {
1763
- const lockPath = join3(projectRoot, GOVERNANCE_LOCK_PATH);
1888
+ const lockPath = join4(projectRoot, GOVERNANCE_LOCK_PATH);
1764
1889
  const lock = {
1765
1890
  materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
1766
1891
  entries
1767
1892
  };
1768
1893
  await ensureParentDir(lockPath);
1769
- await writeFile2(lockPath, JSON.stringify(lock, null, 2) + "\n", "utf8");
1894
+ await writeFile3(lockPath, JSON.stringify(lock, null, 2) + "\n", "utf8");
1770
1895
  return GOVERNANCE_LOCK_PATH;
1771
1896
  }
1772
1897
  async function readGovernanceLock(projectRoot) {
1773
- const lockPath = join3(projectRoot, GOVERNANCE_LOCK_PATH);
1774
- if (!existsSync2(lockPath)) return void 0;
1775
- const raw = await readFile2(lockPath, "utf8");
1898
+ const lockPath = join4(projectRoot, GOVERNANCE_LOCK_PATH);
1899
+ if (!existsSync3(lockPath)) return void 0;
1900
+ const raw = await readFile3(lockPath, "utf8");
1776
1901
  if (!raw.trim()) return void 0;
1777
1902
  return JSON.parse(raw);
1778
1903
  }
1779
1904
  async function materializeHooks(options) {
1780
- const projectRoot = resolve3(options.projectRoot);
1905
+ const projectRoot = resolve4(options.projectRoot);
1781
1906
  const result = { materialized: [], lockEntries: [] };
1782
1907
  const recorder = options.observabilityBinding?.recorder ?? DEFAULT_RECORDER;
1783
1908
  if (options.environments.git?.hooks?.length) {
1784
1909
  for (const hookName of options.environments.git.hooks) {
1785
- const relPath = join3(".git/hooks", hookName);
1786
- const absPath = join3(projectRoot, relPath);
1910
+ const relPath = join4(".git/hooks", hookName);
1911
+ const absPath = join4(projectRoot, relPath);
1787
1912
  const blockContent = buildGitHookBlock(
1788
1913
  hookName,
1789
1914
  recorder,
@@ -1792,14 +1917,14 @@ async function materializeHooks(options) {
1792
1917
  const existing = await readTextFileIfExists(absPath) ?? "";
1793
1918
  const updated = injectManagedBlock(existing, blockContent);
1794
1919
  let action = "unchanged";
1795
- if (!existsSync2(absPath)) {
1920
+ if (!existsSync3(absPath)) {
1796
1921
  action = "created";
1797
1922
  } else if (updated !== existing) {
1798
1923
  action = "updated";
1799
1924
  }
1800
1925
  if (action !== "unchanged") {
1801
1926
  await ensureParentDir(absPath);
1802
- await writeFile2(absPath, updated, "utf8");
1927
+ await writeFile3(absPath, updated, "utf8");
1803
1928
  await chmod(absPath, 493);
1804
1929
  }
1805
1930
  result.materialized.push({ path: relPath, action });
@@ -1808,7 +1933,7 @@ async function materializeHooks(options) {
1808
1933
  }
1809
1934
  if (options.environments.cursor) {
1810
1935
  const rawHooksJsonValue = options.environments.cursor.hooks_json;
1811
- const hooksJsonPath = rawHooksJsonValue ? resolve3(projectRoot, rawHooksJsonValue) : join3(projectRoot, DEFAULT_CURSOR_HOOKS_JSON);
1936
+ const hooksJsonPath = rawHooksJsonValue ? resolve4(projectRoot, rawHooksJsonValue) : join4(projectRoot, DEFAULT_CURSOR_HOOKS_JSON);
1812
1937
  const relPath = hooksJsonPath.startsWith(projectRoot + "/") ? hooksJsonPath.slice(projectRoot.length + 1) : DEFAULT_CURSOR_HOOKS_JSON;
1813
1938
  const newEntries = buildDefaultCursorHooks(recorder);
1814
1939
  const existingRaw = await readTextFileIfExists(hooksJsonPath);
@@ -1816,20 +1941,31 @@ async function materializeHooks(options) {
1816
1941
  const merged = mergeCursorHooks(existing, newEntries);
1817
1942
  const serialized = serializeCursorHooksFile(merged);
1818
1943
  let action = "unchanged";
1819
- if (!existsSync2(hooksJsonPath)) {
1944
+ if (!existsSync3(hooksJsonPath)) {
1820
1945
  action = "created";
1821
1946
  } else if (serialized !== existingRaw) {
1822
1947
  action = "updated";
1823
1948
  }
1824
1949
  if (action !== "unchanged") {
1825
1950
  await ensureParentDir(hooksJsonPath);
1826
- await writeFile2(hooksJsonPath, serialized, "utf8");
1951
+ await writeFile3(hooksJsonPath, serialized, "utf8");
1827
1952
  }
1828
1953
  result.materialized.push({ path: relPath, action });
1829
1954
  result.lockEntries.push({ path: relPath, type: "cursor-hook" });
1830
1955
  }
1956
+ if (options.observabilityBinding) {
1957
+ const { generated, lockEntries } = await generateObservConfig({
1958
+ projectRoot,
1959
+ eventMapping: options.observabilityBinding.event_mapping,
1960
+ artifactContracts: options.artifactContracts
1961
+ });
1962
+ for (const g of generated) {
1963
+ result.materialized.push({ path: g.path, action: g.action });
1964
+ }
1965
+ result.lockEntries.push(...lockEntries);
1966
+ }
1831
1967
  if (result.lockEntries.length > 0) {
1832
- const lockExisted = existsSync2(join3(projectRoot, GOVERNANCE_LOCK_PATH));
1968
+ const lockExisted = existsSync3(join4(projectRoot, GOVERNANCE_LOCK_PATH));
1833
1969
  await writeGovernanceLock(projectRoot, result.lockEntries);
1834
1970
  result.materialized.push({
1835
1971
  path: GOVERNANCE_LOCK_PATH,
@@ -1840,54 +1976,54 @@ async function materializeHooks(options) {
1840
1976
  return result;
1841
1977
  }
1842
1978
  async function unmaterializeHooks(projectRoot, lockEntries) {
1843
- const root = resolve3(projectRoot);
1979
+ const root = resolve4(projectRoot);
1844
1980
  for (const entry of lockEntries) {
1845
1981
  if (entry.type === "generated") {
1846
- const absPath = join3(root, entry.path);
1847
- if (existsSync2(absPath)) {
1848
- await writeFile2(absPath, "", "utf8");
1982
+ const absPath = join4(root, entry.path);
1983
+ if (existsSync3(absPath)) {
1984
+ await writeFile3(absPath, "", "utf8");
1849
1985
  }
1850
1986
  continue;
1851
1987
  }
1852
1988
  if (entry.type === "git-hook") {
1853
- const absPath = join3(root, entry.path);
1989
+ const absPath = join4(root, entry.path);
1854
1990
  const existing = await readTextFileIfExists(absPath);
1855
1991
  if (existing === void 0) continue;
1856
1992
  const updated = removeManagedBlock(existing);
1857
- await writeFile2(absPath, updated, "utf8");
1993
+ await writeFile3(absPath, updated, "utf8");
1858
1994
  continue;
1859
1995
  }
1860
1996
  if (entry.type === "cursor-hook") {
1861
- const absPath = join3(root, entry.path);
1997
+ const absPath = join4(root, entry.path);
1862
1998
  const existingRaw = await readTextFileIfExists(absPath);
1863
1999
  if (existingRaw === void 0) continue;
1864
2000
  const existing = parseCursorHooksFile(existingRaw);
1865
2001
  const commandsToRemove = buildDefaultCursorHooks(DEFAULT_RECORDER).map((h) => h.command);
1866
2002
  const updated = removeCursorHooks(existing, commandsToRemove);
1867
- await writeFile2(absPath, serializeCursorHooksFile(updated), "utf8");
2003
+ await writeFile3(absPath, serializeCursorHooksFile(updated), "utf8");
1868
2004
  }
1869
2005
  }
1870
- const lockPath = join3(root, GOVERNANCE_LOCK_PATH);
1871
- if (existsSync2(lockPath)) {
1872
- await writeFile2(lockPath, "", "utf8");
2006
+ const lockPath = join4(root, GOVERNANCE_LOCK_PATH);
2007
+ if (existsSync3(lockPath)) {
2008
+ await writeFile3(lockPath, "", "utf8");
1873
2009
  }
1874
2010
  }
1875
2011
  async function copyCLIBinary(srcPath, projectRoot, destRelPath = DEFAULT_BINARY_DEST) {
1876
- const dstPath = join3(projectRoot, destRelPath);
1877
- const srcContent = await readFile2(srcPath);
2012
+ const dstPath = join4(projectRoot, destRelPath);
2013
+ const srcContent = await readFile3(srcPath);
1878
2014
  const srcHash = createHash("sha256").update(srcContent).digest("hex");
1879
- if (existsSync2(dstPath)) {
1880
- const dstContent = await readFile2(dstPath);
2015
+ if (existsSync3(dstPath)) {
2016
+ const dstContent = await readFile3(dstPath);
1881
2017
  const dstHash = createHash("sha256").update(dstContent).digest("hex");
1882
2018
  if (srcHash === dstHash) {
1883
2019
  return { path: destRelPath, action: "unchanged" };
1884
2020
  }
1885
- await writeFile2(dstPath, srcContent);
2021
+ await writeFile3(dstPath, srcContent);
1886
2022
  await chmod(dstPath, 493);
1887
2023
  return { path: destRelPath, action: "updated" };
1888
2024
  }
1889
2025
  await ensureParentDir(dstPath);
1890
- await writeFile2(dstPath, srcContent);
2026
+ await writeFile3(dstPath, srcContent);
1891
2027
  await chmod(dstPath, 493);
1892
2028
  return { path: destRelPath, action: "created" };
1893
2029
  }
@@ -1897,7 +2033,9 @@ var SCAFFOLD_PROJECT_YAML = `schema: aaac/project/0.1
1897
2033
  #
1898
2034
  # environments:
1899
2035
  # git:
1900
- # hooks: [pre-commit, pre-push, post-commit]
2036
+ # # commit-msg/post-commit are observability-only (promotion axis): post-commit
2037
+ # # records promotion.commit + promotion.file, feeding Enricher R1/R2/R5.
2038
+ # hooks: [pre-commit, commit-msg, post-commit, pre-push]
1901
2039
  # cursor:
1902
2040
  # hooks_json: .cursor/hooks.json
1903
2041
  #
@@ -1954,4 +2092,4 @@ export {
1954
2092
  copyCLIBinary,
1955
2093
  SCAFFOLD_PROJECT_YAML
1956
2094
  };
1957
- //# sourceMappingURL=chunk-JWJLY3HJ.js.map
2095
+ //# sourceMappingURL=chunk-F57V745S.js.map