From a41a67d98989a0c2223eaa8dbc45710a6508ac43 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:21:30 +0200 Subject: [PATCH 01/40] chore: add implementation payload part 00 --- .bootstrap/part-00 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-00 diff --git a/.bootstrap/part-00 b/.bootstrap/part-00 new file mode 100644 index 0000000..bd83a05 --- /dev/null +++ b/.bootstrap/part-00 @@ -0,0 +1 @@ +H4sIAAAAAAAAA+xca3PaWJrOZ37FqWQ+Ar47M+5UqjDghA4GL+BkemurQEYHUFtIjI5km8121X7aH7C1v3B+yb6Xc0MmjtPdcc/sWlXdMdLRub23570c1XdefPdrF67XR0f4797ro13/X3O92Dva3z/a3T06ODyE+68P9o5eiKPvP7UXLwqVB5kQL9IgerDd157/k171nXowl0muviMffAP99/eOjl/s7u0eH+0/0/8pLkd/dR3F8Xdhg2+nP/xz8Ez/p7ju0X8VB0ktSG6i+HdjhW+g/8EB/L27d7i/e/hM/6e4HqL/8EOn260vw986BhL4mOz6Nvrv7e4dHxr6vz44OAD6HwEDvBC7v8cCv3b9P6d/rVarJMFSnghH+Eoo1TSLVnmUJifinUxkFuRSBEkoboI4CumHyKJ5mqWFqopcqrwWZtGNTES0XMVyCQwV4NvUqYgSgf9XaQxvhuJdlIvbNLvOMynr4lJJkSbxWtwu4HV5t4qjaZTD7yi5Sa+heaDEn9zc6qInb2TmxhFpBm/JaQGTyhdSzPV0Qxq7XsEFVl6JC/jRoMVVmpnk5YigCKM8uIpledrTNMmzYJpX4a/lEuaLfSVRMhdBlkczeKJo0lWRyVWa5TRyJlURwyu4TypPV3UY95U4TYskDLJ1pVLTU1+mYTRbi1WWhsU0hxFCiYswv3E3Vd22NmsLvJUBy87pHeRdHhy31jROM/c6tFALnKaSuJpYBklVhHIVpzD5ZTTHDukx9aRkdhNNJdBU3Ub5dAGjxkBWodYql8sqTbNQC/x3KbM57/hVACS8yoJkusBxP0i5ovsqLbKptKQWBTQIkrkM62KEJBDTIEmTaBrEYhbFUtHGIXMAxcMiI7rAtHB+SYr7lMCCFBNoKZdptsbhWql5mkdJAZRM8rRMzmCGmxOsYIuBgZEfaX7A9iIrEqbTJ5jmLE5vK5W9uhjIIBS4f2t8CziSJoO0VhFsLzKnyjOgFvUO055kciYzmcDe7cTRTE7XsNWgOid10SyyjPh0NgPOhuGbQPA7EabTws1wAWteRPMFTrPIF2kW5WuYJPDoFbBPDDR3A9Qr+3UxtJQPJSxuGSWRyqOpuErTHKYWrJiH0ziW2UmlIoSYTCa5vMvxz9UahkjElzU/iz/fGrPcrdaa2/4NexCiVtP0ffmni0+tl+72PIU1vnwj70BKRAEcJfDOW68FcvxdDYmJS3/5BhoW8A4wVZFcJ+lt4jcGaZHx1xqtcAcUdkftv9o8S3+W07wGJFS5eDMaXA5H7dZ/XPbcXx96/U+9t+6VRZpec99v3vf7H4Zj05R/tTrDxmnX/nQ9md+Nj41OF5u81bQgmowWkRIw+VmaLRWQOAhrpAtXQO0Y2AG1Cd6O4X+0X8iGKCLwfIdFbsfI106UwLbuGIWVpVcgOEZv1awUshqGnapiGxA8eFpFMRBqGsxmaRzSDWRqI4SOp+RNFCIP1kUf+X4NopfUcNprq/1WqGoy0Bmm7YaOZK64itPptcx8VXkAgmJEmLZAC2km8yJLtDYnDWxXgi/jvDOYXl2cFXG8pi2kByBQoL3i2JdfX2hJ45DiS+Mb0mMRKMtpuuJ+YRVTqaePv29BIFnb+Z0sYUtATy7EBP4ae08UiAuIfgP6XwYRTRskKiddB3IJtDW7oHiVqIUO4YUkiNf/rg0ZytEsS5e+3nEEGMhpmoWg6ZYFm7CJebYTYC8qUqh/WDvVf1ZpMtFzzejNsW2lp2onqAXGzA+3NEqkUj8QtW2zYHkVzQvUU5n8WxFlpMDtBGtXwRStN6hjmcFuGk2MGEJmEahCo8hBFYX1yhEiAdwnXDrYmhUaNDYJTvNVtXIUk4tuo4fLq6JS0oZijlYokjNsNp3KVQ7iIWlZMGAAtI7UtaoavYjEB+2I00Q2mKao7avWSCimO0gTWBIkPcABGVyBuOTruvhE7KDXjVpcCRBhkFUlVwGBJd8e4zqBwmzG+BbN2SIAMosKlDpKOm6AwR+aYgrujy3yIIJVjoEFgPknBpGNgdlRSYN2W6BBhj0HybyJ5C1QVxtJGHAqgShFAsyvtPyTtZ8ugFEVSm90E0xhH7Ry1+xFy65u8D5tGOw56xjBD4oMfvtbZXcdNxNXZhUSay8BUGhGcroKFFi213VxWkQxt3W8zQvRtlBvCiwQ9lqO+dmYnzEztyK1Chi+zIAvF55m5dZAGuwkLTSyg9/QBGSElaEWLaAqsiRqQNCSoVZxm1JET/QccPAqzpzILSbIPG6GWs5Aac6CCC064zdvdSV5q1f+rGnMOn1MgJZ66aAFWAGGYvUxi0CWxRwlpsqqyr/P6tdAWQauuOXpbQyYwVOtO1o0HMh16lxtg3RM1oSAJuJCxCZ/QdVE+h6xG7oHVnMzyS2mHr5vaOYBYsFtYIBiSU4HvKSVEKlo2h0fXdNUjKRZGavhpgNPQx+Ej3Jwaia9e2DwFqCWBtWhwVGe4DI6w64Kq4+cGHP3aJy0BqpPwIjLxAP8LTmNCNisUlDzgPsb6pp6ISzkXB26lWgDBMbWvLYMSF+hNdOKAfheEUewgYJNK4DtAOvJRXATpWhHs+kCqK4FMMo8tOAaKVgE4sodLeQ7sZwDe/A0qxroE+wnKSBYj+obfQTCC8CwTvs7DUs6WqtSz0C1JHqEWoOTQKGYp/nC996o55rlELMJig0f0Rk4EjcBiHQDckPqwA5CGz6w9gF9rC8icfH3//wf9idgISGiDwRSHhwCdoNNW0QrZjINUlSpT0LJRj/bfrUpYFnSsAYNEjaEZZb6MPJ1vx/nEmnP575mJngCAgP+y0zm61LXLC0A48MasaTpWJsJWqjRZtjSSGNVo6aMAVmpVydj92dsTBUawA3BZBNYkj4QrMofHfN4vtz1UPzv90oMfXv8/+jw9XP+70muR9AfTE4SRPV1sIx/3RgPx393dw8Pj0r0f3188Po5/vsUF/lnYIvkSUUAGFdA/vWYA8Ivbcz0JTxT4Hfl443I8EsXGraB4XBrBNiAbW1HwNJHOXYaylkAqG7MsAp6xGiwF+0VeWrDnqX48/ZQMxuhSJH3bP0eFyw2Lkj9ZYVxDy6bsPAYG2HoeYyBZ/ZOTwCqx0r+XzZYD8m/BwB+0xjfrv+PDw6e9f+TXI+kv4+kv3mMr+j/w6O9fS//B+32d4/3D571/1Ncr0x+DxSnJTL4rDYJQb7SiZiWsxh9QAWNzrZkRlVM4Lfa6ZxfdNvn7d6oMer0e+PhRbvJIbtNb9U4Q87VoaBbRL4le45wK1jpiBL5peDAwJvyLkDFrtgNPAf7EFCQ1HPyKpXJsH85aLbHF4P2Wbfz7v1I/P2//lu864zGzcZF47TT7Yx+Gjfft5sf6EFz0G6MoDV4971O7934dNDoNd+PG73W+FN/8GE0aLf9dv3B+GOj22nRO4P+WafbHtLzVmfY7H9sD8ad3nA0uGziFvCTRq/R/elf2+N3/UaX59LutQfYQWMw6pw1miPdQ3vUHpx3ep3hqNM0o0Av9PC024EZ4SzHg/bHTvsTT6p/ftEYdIaw2zjhsw4MVX4T2pzD4u0CNwcdtC/6gxG9PRz1LyaVSi/V+7kMYO/BvbuOViuMnJzarAD8L1ERBW6AmtLGjDD664WlnQ6haPQPOtKpA6yqmIKiUbMiJr+c8hcCsyPbO5tH4D1bpuAecU7gF+MUmJdqDpWYnACHpNOyow0rA+hwL7q/AqjC3DXkyJdNzFQqoy0pzshL4tTFRwx0r3E5VT+Gj/kKkJH37UZrolOyMYV3qjY3QCHsHMMnuBcAwDkEA7d10oeDM7AVOQVZcXXQBwbczVxUXVyYyYol5rkoTcq5b5v9mNkupbIRQor0uAnX4hT3CYPyaRbAAsIIxBKeREb0cJKehBLtKhXEcpgRuAOEmWztYE0TL5Lob4XUFEfoqezWuVd4qoGNIZZWW6Ul8fJIBVEyTBSrkKIoOommA48FPMusRjO7uKOiOUVBMdWnbFiM6FPomJBNYRvKm+kYatKw3Jb2GPanYYaFPZ5eI4ssraZCuDpBXQTapPXTBEOnmO6C+WICKsK8OkehqKWjt55qVdBcq8LlPzEAbLhRFSuO/MJ+52sTUdKM5TMVpi4om5MWCvPJwRTlhNfEFL4wETobL7N1FJNVkalCEnDYeYN6pdZpvd15o+Ji/nbiAnmc9oF+iXc5LJgHXBtieUST9V6yry48ceOkmvILChqYQdDpDJsYdLUaqBKY9UMd/qaKAPIU7HbJu4gqL0iy76cbIw6Bm6SoiZVz9rGTk37Em7gkGmNS1zsz/Gk4ap8b+8A20AYMgZKoeLKCJHKzesUE5HeM2vMj8xQHRLCmVsAqYJU3rTCKP6eXysUQlN70ak1od4C/rqIQBtFVK8h2uHwO4uvQ6mm33/zQbo1Pfxoj0w7BsrcnWx5coOEaDtHklR8PLnujzjmZ40H7Xy47w879LjyTOW72e2C2m6Nym+agA2YRzJtO1dNzsofO3o3PGrDfLTBiF+WkNOe3yZlFmxbMiKtkGOm94+KZBTSmbE2B2U3K+8A7bCC0bkbZhr6Abf5oJPfrrkfi/3LU+5vG+Ar+PzgCn0/j/8PDPcT/e4fgBjzj/ye4WLWXMhZIZEDOJsmuUbgyuXaXpcHX5kWQhRkIiaJsms3CW2XosmdoWrCED4dUTvxuF4GGKFeYaC90wRfqtQKNDYgawMK4pMg09tCTdArVpFxAIRiDqVP5OlGhC4/UD9ACQMyck6dpEIMhLHIQaJ3XDOUsSgjWgtcDyjWR+MbcukuYJxFXurwPHz2YkqQGtr5E3k3jws7iC5lPRIORV4RilBe9srWsRZmVcoUJJRdpIjSMqeJDzA2rSRAZBHlgynBg5jWsgAPcADoN0R2+FEpw9HDYSFtWtrmAi2DWto6DuvcrMQgI4V2vSII8DH6Mf+nKDNhe/IV1Anxb2zy0TXTD6my/sAC7xhaEgghhb6QqtYHDzv1yk+01H5haNkS3RYJkkPWyKI1NpUtg1mHnRAKAhYAUdslgz2XaN+pCgEkHEovNgK4ajyF6BKsfoPurqroGABFcgDRBCAQDFMsrYFPkBoubuGqTNtJYHcqfT+UijUNqjSDR54YcJcuVRm4CAV1h5Rja1kKyGNMOVCptQIOaalilGHhT7bTQbVtgweYEwMC7dm33YIKTsL8aAHVww6xg6Qy243/Yvxn4hQR5gnyh8PUwUkwbrlgJKU4wcSy/UWo1ofd2qOBrCQqGWdpn25Jf9ZjSIJwz1elGWBqSAoECrBLII1wD8jb3npe4C1+bpgvJjkW5ptjlWbGdpatBkuQfrFLgY6DCENaa87bDnk+zVKmNccOUMHCVSgi4rhq4CcRaRSQgtOwQa0ITVAR6fXbBjpe0t2fy91qfWdeuWaoKA4YgbOjKVGzhNhPR1RvYWgFXCagLFxoXHa8dVyHjFrl7Tkw3ihlY5JRfy+B7Pq6KGnuztQzo7KNB0UgPZJhUO/gNwN3EZnaqvrYiiwTLBAZnWm3WHlApj33R101iHqxMNc9Ex2jIvfsHxIiPxH/bKhYePcZX8d9BOf67v4/532f89/2vV6Jh4q8O+WFRDQCXOFiD3gYgaBxZMBBq5w36b6Dfzy/ejq27P34z7F6+e7szMahP+TWaE7AX0QysNcfp4AahDfvLBXztrY16S32TXeVQTCggVdvow5SFTVhlUq9Wn9JPNs78J6pD/MMIM/6NlYh0M07n9C9oTgKQSnc/ISM/KYW/mjaQuAxQ2+gzCxgu+HHY79XFeZBdh1hPC3cWBewEFUyTLnHVc2jtMhjNvHR6r+QatD+YTGzxcBCUp/rloCuVFZvaX6xJU99UQ6ytgl00ncpISCsj4r4cndX+XBXdM6wgJahzLdd4ROg2ralVMGVgaBMFfHIBuknkLeIewsgYuTUgXUz26nv1XfTuB2dNcXBw8BcYo0mGGPZ5ucLyrOH7Rm3/6BiTw4WkiPEsusPgIBfPLgJ4eIJdmMpmMLtxiKHan9lm6XpY7/ARpYRliEA7T5dgsoB7EGmRYcBYnNkxIjY0W6ZgYXBPfN6uY40VLgMH9/HjBAHkmK0ZPnMU8JhWV6HBhulCXhf9Yc+HK8KABQlZUJTbRrxcxFd7YcEV+QJScDSXsFaVahIp5Fo17OvCSe4w0DST5ElRWTQVokE/TNhpml5riLVCMDOpy+Rmov0Kssfc2ot/Xw66KDjn5fFwYtBAgZ2OU7Da5hiAFvsTCkF9IaZGi0Je9duwuhpcckDyntKoVD5yegDHpP1C6E/F90qaI0mYE9BqhwPAqJiuCTogCbw6PMD5fJaAzw1RGW5V8xjCAzq8BD6mWi8xyinA+w1WuHOTOsjxxNTtgsZVGHYKZYiwUp+Xc4B/GihZA/0qKeWCw5l+yIsrrgC2Flgkzd1xybl3qI4ROKolKpA2ZcBKl7t6YX/ClTjCRX/Y+StzjI73+zoE7MMDWuP+I62lMr++2+qjKFnB+jnai5rQhh7siYgFnWfb9D4ZwJc9iaoHPL/gYeMUrX7GnrcehPDzW/q0BhamPBiO/EfEetuuR+K/+2Wl3zDG1/Df7uFeCf/tvd59jv89yfVKfHxUZTAVBXN5u3/c0JUVg1/IKVTrGFbZbVq70JxLz7hcv0USKO7m3Il3XG3jAEr59IhVXw4csnnTua7NAyucaeap6WBVp6W2HVipWZ/cnXKx9ddXivBYOisFXyh8NIdJE0i4kvmtBMeYtJivZ0yCxe00bB2deQnMARdtsyNjBFHplCKV7kwemAeH8nxf257uKSW1q57i3UCD5fSTiwpv3SRlwqRbGAIsPxgy0OV1nQf+4kEc/3ASzv3+gRw6KCPjmUZBbBzsOR4y3KDeEcBtkpj9GbCiVu27ANyGPXDBBhtR9I6B2fjYjjldbQK9Nvr3xSgA2ks+K2bcD9avPPsdH9zdO6yXUpDhPYa1rrCsQVco8KGiCNGlaNq/jbm3IWjefc/DADihTwv5Qq7hPCeo8QCRFWMj/JnUMWxkJletw7JYpfNbnnAY1WHOzunZOTVhcgRfPITkMCwsHkC1X4lg8t5czYGpb8c9eCxd43izCTGrHqlMAQgF1LMlBmABs/Haz/zI7eYZiMqTHGQqHy7SEsOPGLixOkO18iQnmigDbo40/dEG6vn6rtcj8d/WA0CPHeNr+O/w+Hiz/hf/PH7Gf09xvRLD7VlLFw0ckT9M2SBy29DU5PipF6yju//JFarrW1PLxHyChGzu1dp9hUWf3EsNHgRVk8bpfM3FN5sfM+EgFSAIuK2Db7Xpgg4J67dOxI/REkMRGSBPPgX7o0ySNR7pU9qWwwS42oW/24JRmHJhzJyi/pz18V4zxTLaqaQP2pQTQIRXuCrJQhxW8Z8QfUHvn9J4Jrd968GEGZ0T7FUoqegO9mERFGrL0Yogx/o4yjHi+hP3dZmIwmCb35fh78rojdnelmFySJ930JGq0qZ4tliDeZMWY4q2TbRS1xGf6oxOjbLGuqAIU1pA05NKZfJu0G73xGlj2O52elxZ2/7rRbs5arfEAP7DG5t1xHTr7LLbFfwutei12hdt+F9vJD62B50zcMWxLVsykUl7dpvQIlb02OOKmDYGSrrEFaGBgPBVD2TB3PYmThVr4NIAqsHNkRtrNmdSc9gi+naJMef0yQpNMRo9pVgxCs58rY+Nb2kV+AeCEW1xctG8SFWeXNvEx8pr+m0/UWVZydQy8Qc/HuJB4/PpIKoX6rjsDdrDfvcj/ML6qstBe+KqQG2hBfhO9jwtUCFQ1xo1ndiCwXu1gnXRcTn8e829/P6WVzEKysNq10/j7aofUd0so8CW/ndGgmjrd0ZcIR1JEmkrUiS6EMJ+rQTXSAl4twavGJfS6MZBMcU2wHkY83oob0wxF6qFYLQJK+XitAB0I7AG+h34xZgHP8sE/EguuEOUts5BuxXl098baddSrWj5ZLgtGsgllm/rU+vM9yaV7+otBNECSwBWsDTvI1Q8OoxwRfysHeryeWJjl8iXMMuiCg7vMxU4NXTBiPb6RAFM1Xqv5dPqmjHubQ5V3fo7AWp49U9b67ftegj/2c+w/MYjwN9w/utod28Pz3/t7z5///NJrsfRX7uGv3KMr+H/g93j8vnf/dfP3398kuuV6GyCSoToJ+Lz51Fn1G3/8gup9o6uo8QMHJWLdlpglz9/ptqWTuuXXyg/W9j7g0t3u6n19YkD/2K/vgdPGpsHv04EpXrhwamzXNQdwkN9EIv7pAbD9w33FH7wo4vNGI2dpneYCxviqvp+RLVS+fwZT2TpFfe5Xu0LdaDYuH85avbP23RUqtXvma16t708tFJxq3fukn+iOeTTCHQ4mY4TmATu/7L3r2ttJFmiMDy/uYpsVc9bkksSJx966M30yCDb6sLAlqCqazCdFigBjYWkVkq2acx+9q/3At5nfn5XN1fyrUOcI1JKAcZUlXKmyygzzrFinWIdtPMyBlwjvqGcFUOSGJNAfMfMaI6SinssA/NF6M+kjAKnWbdKJrdryE3afridOvGctPpJWeXiFXVAZ8WBzoA9ReuEGWYkAbMQGRoT1pIW2uAGp2rIZShKyzkMuY7+ObByIiSn0s2zOaict7QLVZHwMO7NuQpn5kQYIzAZcDS9y256ideyYsHxohZBrbW1ty/hq64MJ/FL/W9bO4fkZyE+17LvOSWvg/Vqrdbh233ySZQ3lq24/lMDJKgt2VMtbGGM1U2fRlG6RTBlGgjr+2GYAd/Wk+tjqyHrbHumxdatLlaUct1Wo96io7a1A2NXAp7s3LM8pk7RBjVG2fBvotyBoZ7HEgfN2lZd+oDCirytNX+RRfkmgIaVZe9JTdRbB4Ba5On3DJENgaiCrkLSqhawTYP9LBu7B/XXTXM6+1nGywZ/bkESNrff3NsWPjOmCCyabEqOV4ZjQk4cqzX3dnZe1rZ+pKE06+SzKtegSXbRqgoewq6aOAiBh2/regPGk1TcNijTaCQX/IXQMLoLHbYY \ No newline at end of file From e73dc88cbf80d92ecf3fde2c6c4c6282e9bde6cd Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:23:21 +0200 Subject: [PATCH 02/40] chore: add implementation payload part 01 --- .bootstrap/part-01 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-01 diff --git a/.bootstrap/part-01 b/.bootstrap/part-01 new file mode 100644 index 0000000..45d4b3a --- /dev/null +++ b/.bootstrap/part-01 @@ -0,0 +1 @@ +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 \ No newline at end of file From 99aae2d71eaf6ecf3c9ce72555f5c9983ad529b8 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:24:25 +0200 Subject: [PATCH 03/40] chore: add implementation payload part 02 --- .bootstrap/part-02 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-02 diff --git a/.bootstrap/part-02 b/.bootstrap/part-02 new file mode 100644 index 0000000..230bef0 --- /dev/null +++ b/.bootstrap/part-02 @@ -0,0 +1 @@ +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 \ No newline at end of file From 2627302dff972c487824acd023a116651174419f Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:26:10 +0200 Subject: [PATCH 04/40] chore: add implementation payload part 03 --- .bootstrap/part-03 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-03 diff --git a/.bootstrap/part-03 b/.bootstrap/part-03 new file mode 100644 index 0000000..6e7fb31 --- /dev/null +++ b/.bootstrap/part-03 @@ -0,0 +1 @@ +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 \ No newline at end of file From 5f7deeb57fcab253e69d793f0236fdbd9b900b92 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:28:03 +0200 Subject: [PATCH 05/40] chore: add implementation payload part 04 --- .bootstrap/part-04 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-04 diff --git a/.bootstrap/part-04 b/.bootstrap/part-04 new file mode 100644 index 0000000..62a0bd2 --- /dev/null +++ b/.bootstrap/part-04 @@ -0,0 +1 @@ +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 \ No newline at end of file From 3416d8bb83310dc4a12a57e419bbbf5ce13108e8 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:29:02 +0200 Subject: [PATCH 06/40] chore: add implementation payload part 05 --- .bootstrap/part-05 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-05 diff --git a/.bootstrap/part-05 b/.bootstrap/part-05 new file mode 100644 index 0000000..c11088e --- /dev/null +++ b/.bootstrap/part-05 @@ -0,0 +1 @@ +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 \ No newline at end of file From 34e06aecf5fdc7360ef413857417448c2aadddda Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:30:05 +0200 Subject: [PATCH 07/40] chore: add implementation payload part 06 --- .bootstrap/part-06 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-06 diff --git a/.bootstrap/part-06 b/.bootstrap/part-06 new file mode 100644 index 0000000..49274e9 --- /dev/null +++ b/.bootstrap/part-06 @@ -0,0 +1 @@ +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 \ No newline at end of file From 3472a23e568790a7f11e1ae28c1dd8191b48e50c Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:31:37 +0200 Subject: [PATCH 08/40] chore: add implementation payload part 07 --- .bootstrap/part-07 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-07 diff --git a/.bootstrap/part-07 b/.bootstrap/part-07 new file mode 100644 index 0000000..0224821 --- /dev/null +++ b/.bootstrap/part-07 @@ -0,0 +1 @@ +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 \ No newline at end of file From 48f805d269debde45606a599cc0a88a5de32ab3c Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:32:37 +0200 Subject: [PATCH 09/40] chore: add implementation payload part 08 --- .bootstrap/part-08 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-08 diff --git a/.bootstrap/part-08 b/.bootstrap/part-08 new file mode 100644 index 0000000..aa68fbe --- /dev/null +++ b/.bootstrap/part-08 @@ -0,0 +1 @@ +h92xlZDbeKXKoGJWQKxRzHh7G3lyOEqMFuKTSb+jhcrgRyvF1gnQyY4zqMAnN1l5r+enKe/1lMyqI0Y2qTpH0MgprybQ63hA/9D1i3CK4fxZg2Eai5ANse018JA3CVlcl/YSlk+Q4XrcUuOtROQ8nHxmDge/qEbxVq7yXsb1fe6lCswt4waPGJJNn0EJXxP6+dLDO9X5iE4+7E6zGY4eMpth1IsjLy70G+eyFh+BEjbD2CDs8h5Yp9nj4gaz2F7Rq8rooy/f8H1QILCqBDNUmA9Fln6JSIuDQzPqUVEAMS/be7w2eK+DeIkeks7SEqa5UAH/rHh/KSdxKkciMI7pecVBBWTErnDW5aoMwUfsM8VgpIsajDWjMs97oUE5rp6ORSXwMOejkBkVjAg6GLSIbnd0KFB5YqPxxWgwOb+QwYrLMrAVui7r8YuoEFbIULxR46gNXijJAzf1A4WKKpvhSOwIgnZL6EVYMYNlyqYpAp50F3AiPi9zYECM3qWiPuM4zq2Q0KmIkaQigoUDJcrgTn0RnG1pCaHDyR5hPtmZJMzHzyphPv65MDx/5ZFQUBFW/qjP5p3s0XFuYVeEX9sMEfqHwq/iaKt499ZRnyaIbhZwlzLWXq4MuQRtKqf7W1lViWU6EggqNm4jaQR+G8zMdWWGHpOzu0csq3tRBs3qTQD7K92GwZE+PiKaa0O8e/fWwd7+vnfd7tS2VTKOp6mMSzqXWgdj4s6sQnuVpWcmDclys76/1zxgn60uw6x7Zx9cieBaz68HxmeKLlhuVinTrDBj1/EJpIL1psV5VjPHbSeCdR9WImf3oAwdM1iFW4Hgwyy8rYT//S39Qn34e31y6v8k78dWwxwtJbcL4Az7j/WVZ88d/d/66vNnC/3fQzzfwP7j1jq/21p9GDpC66XSnb0U0F3rd/YZtnPqzXTwGCkl6ZPysYueOV0O/yTDiz/Cq8gH1Iw9fiWYSJmVMRQZgyZYbaayhArl8eo3H7prrdEdq1TKioD9fHK6l5dJpwsQ3btiGIj+2uU0M9rrXoUdDorH+HwdMTtwx2ss/t3ksnu/9VXRuZAxUee6Is91RZ7rijrXd7rcXXBki+cxPDn5P3JYIOYv6ZwLZXqalwE0+D98nH+B1Xv+QsV/eL66jvzfi9UXD8z/Ic6ZVm7W91/pc9v4n0p2vW/u0IkFMTMURNkPZJQzvgOgwbQr7jhRUy0n4rxfWmru7R3Ie8mY41LGGJ8nHfQ+JsWSiBaUHj09XkKXlBaUpSroJoi2cp+X2U1J8Ztv4CfwmnU4Sph9KJnNbdIBJOYRAy5hiO2NiPKv40pxovUyJv/oi+TswZiOghrrvfP1JUAyroBZ6q8LDQnPZ1n06ZoXSv8U+y1lddnEjah2JpfDtEjjcqhhhspEqEmMIfqKESiTjEbTywQNHoMxikxNp23fKJ2TqtxhyVhJio5JM0T71rSoC8LoS+hnZr2RfjtRAuOJro2AdxygKmHfON5eRDRyR5+UMR1ZQntNzu6Youp1fbfepCQe6CKkUk9sokRB+451zX3P54InLXZvF/QTde6iwKrzaTLsZMTkXNtYCcbkxDlDWfzH+aIDlIsQisLeF5ccixMT464SL3uh/rf61iHZCTd2MQLj62bdu9UoCMfzWIa/x0XNKEI30DiU7UZra++nejM2bJG9hjHrWNyWkeSvCzL5Atos2/WiAlCk84RWa7rw44Z+BOQyjjVEQANGrjS7KMYaY3dQ2NhAWgcdx5HsaSmIpBWzUf4lwtppv2gj/if8ZzlkUk0RhBlrBhwoNUhmhaijNr3ziENwLITJ6RUWsJuk5OJOK/iR3RtZk0UJalBWPc0MKZlPNu/In8FYOxzFzzzsRE1UpZJr7EIEDw5jAXBsgc4/u+gJn9eYcCpx7iJXwMFg0DtkF9kx/Kk+vYTtK9g5tmlBOmpURFo8OaOgGcHK+aQ96pBpS0DGC/lxXz95wlOQoyGaQHCP72HpcWiwC4gnk3FUqVxAD9EbOMuFGweqZwXkockc0aq0hskp3n7vkUIBQyEO0TyAEoRswydCUHiLBZWuHIFb5EN7HKvCaC6iYBij8bxLIqZShhPr3E4SnCMhefLkSfQyOcccf/jqXR9fHBKijl4BmAPEKbXNu/5//Me7fmXQ67zr/9BPPnHhOtp8cN1CALpi2dXXW83wXYd7XsKlZpyhcCXrXGGOviue5dTyoT2mWjd+rdtAPg/h7vAvWuNEdL/dbfsZ55dzw4jTF+kWHQM/UqYQhS1weuWOS4zxudV+0g7cbj8DxI9wQRoLQyMGFiJ9ZMFwKiy6RdhUzS08Ilo4B87ymA+hsJ0Tgz0EKfi9Iy+LRpklrbykv+EtuDUiygJyBy1R3Pz72ibeDYeheBBcwALwJst0SoJzIxSSHDPPgdXYby6Qyc2Nb3H7xI2PuufnyYiO3WQ8cPdkRvARMbUj2tpuf5L4bpCdZIxmqJ34Au+WcFfiy0lv3B0C0GAtzh0dy7AgeB3Zvjzpnk8Gk/Rr4nknvqje04z4P+EIKYPxBSyeEQvFXq+LthNbxQoWRAJFzjgqZiNECKEg2wDxAhcokVDWQIz4ObkCkc66v8obAwfzw8a1ty8brw/3Dl0LycxGbhW+lKTuWCp6iIlAc81RjDaXSf8MLaXueMGdAVDcsxlA3wamLLdtX3/g3xGqpnNTiHwaMVXc0IwFkrZQkbk1ZKqm0JT5isGMoWeozzKKz1aGeUXnUoqp2g+gHFN9+UqyKdOapSZTBaery+QzFffnD8VH/sf+1bB7cxG+8J4G8fhIBwN10jdXwwX7aDxOALWZEYVhqudObbe288t/1uPXe7WdTIMDBRaUrHb+SgQrm1OSB81AmLTSfqQ+QJBwdghNwlR/arR8nmSO3fzQHQ6TzsPtZwYaMvez1jxovKptHbQkUqlvT9/N7fpBvfm2sdtoHTS24p9qO43taZjI39nm4a6sttecY2tFfMNl7fyznE5AVhllpmiateW8Hf6mN3ZpfGLbD5q13VZDMKO/XkOKnPf/MgOvCClJ3hnsSYS5sGbYAcy4/197saL8v5+tUv6HZ89Wny7u/x/i+TXZf85pBlB2o4Y9Un9webYcX3D5+gF8x2uiq1q/wx6cDXm082auEN6R8aT/oT/4JFimNOZo+OxTztsOkuhj8RpHr7JkdNnG3OG9K1jGy8HHBPVP0QSoAUXccmj679R+VnoMGu6SEjiD1rCy/Gz34e8i9AFW+d3f9d/1t5NeQu6iKXkLs1spKrXw3XDQ655ekbuqgLSHtmkVcdi8dQi7jeYQQGWj4eGFRVB8CnR0la8vykPEmLw6zGKMqRb6HmPZN43Xb6aVs8GQstbPBkSqKeEN65zZ2sprCaLfc8bX749vlhV4Am44R6PXyjmABMLVtE5g6pNL4s6mSWVUVAAKlcsshU/2Wqu2cPC4ejXGZWMKxkbbV9FAyoAL+FyC6JR1Vi1LDAqtT3ckUzVMT28c094JavrINNw/MIYfeQRDSkazBnWT+TVjrQPS7hSLcIfG5ceZQU9YhUC0c7P8w/iG27SJ/8kx0Ntbmmdq6wwd21YTBIet2k58uPvj7t7PruhILT5U/MRw/GynMmbxmzZ+YZJz5OhLnJX6BiECLa5LJQsdty+BIUWlOIozGD4/UVINRTN4LCzK42I/fr+BbcJYJ9PXPhB0Zj6ckyPmjFv7rpFm/AZv5wolyThehczr8OS6Uam2yAvqgE6tCjlJM8yMODktEwI+QoSaIyaOnY7Bj3qDzKuKe4M/OPJNzhAh+dWFI/wS0BbySHNGF8EnP6CHI4dI+2gRHiTYTx5SSfPx1W2oV63/HL883N3eqcdbb2q7r4NkKgtoZsOE15RFCczgMPS+MgVErJp55J4c4POq1th5L17LUEb4symC+uhgQ6g76KeTM2AHu2hT+8Ay0fzhdHLKRdnRZPA5ui50yWLyVWN3u7H7ukIpBAtpgpzx+EpLOfCONcL4avbqFW5yRUt5RJF8LOib5nW4WUCguvdIPl89Cg/z4G4YnhzIZS722eKLcaE8fPPb88rMqf83cxfAkM9AqhwLf0BOdjjNGXC6/n/lxfqLF07+j+fPnq0v9P8P8fxK8n/MVu7Pp7KXNhzMUKMbt6Met/KBGIlAtiTwo/+eAP2cSvJJX7gMdrS+PHSuhPL8VySD9mF6ZH6XEYAeZcgpQei5usNf73Kb5tYh87OL1D1im2tTsjtJLtofu4NR3vjz30UYxJCzwaSRHK5mCgb93hX5948v4DvuHwdVSCmDHAd2w0EHaKEAEIMbUu/uxg6pZjL4oUxOf7pms6BVvHqTyu6uTVGxUiNzKTALdBImQnWZbX+DT1gTmZNFe/icMQ+iDxGjFWSY+LUpwPHQ6k3TGGhrb/fVTmPr4Nem4gzO4dGqOc8HPYAfyYsBt3h6AQJcLI3SUC+Ofh9M9TIpC5rSpF2kITm93dUycrvCDVQ0gc6gmaylqKFRIRnkpRsRpkM8Gk9gFkfsAo3/PT6Gpo90f4iXkT3GuCuweJew3BUmCTIhc3I2MV8JK+oKGcUfO4Rx0vcGLpnaAvygjlBBNHEwNw+5ilkh+x0fo4TRMSY2xdYu2/3uGXILfMLVEpqf+J0A/DASkM0ZR8Rqi9/P0RDKWL0uKi8DrRkf52jSDN4caNT6PEezCmfad7BW2+rTbdrFPLM6QXCgdafAbfrowU5TEOdA8/rbjJaPrTelKUAq/ad1J3gfbLdPp4tsreF0yQFjMQxTed4bnBQLzUbrx8oTUd5LsavqCMs8OvasDVgmbYlUpHF9lTo1gDB58EBZafBztWvPkj9Y8wyoMXJ3pzURGadEfMzoUCRsRoR5jb4kuNqlDVv4sLZKb4p8g5vD48Uln1JTs08epZTDsJ2wRugn3z0di3DVIbRIR4O41YouXQh1JDPo6jaNu4NQ1txZdVu/tA7qb2Nhvu628uu1w/xWT3VZhKj5in2QkufZsyz9D/0t438+f/b8X1ZWV6H8v0TPvuKY1PM71/+o/Res2tfoY579f/bsBez/2jqAwWL/H+Bx99/wkRSJOUbV8eCyd5c+Zuh/V9eerTv7/wJTQi/0vw/wkHSzyb6xMe27TMQ4Kix1Eo77xaYThWbS7lRIMWawBbI0cSjqulor0s7b6MCJujXSn2n9RtTppqeDj8noqlpYSuHjyeBzzDGckOkSXeEgPiY9ELhHtnp3E5PPLL2m1s3xWBq8aoRjxsBo8MXsmxR/aD953ge+4gSqfQY5mdleHCcZ10GVcar8ZyL07KpGb9vDqD0C+RpzjgL3VAYpHPlF6LOLrBRyF8snk26vEwmf+VSoDahkb3CFMVm9JC9Co0QjSKvRdpdywUy66UX0U73ZeNWob5ejw1a9SdqIRvMt/m7svqo3m/gXtiGMsSKS+KGJAakqk053TNNNMQdNgioX3OuUEu/AqiU6UCxrUvn6HZnfy8mYw83qiQxwrQEAqFwfXSC50mVyiYsPDPBpuz/oU6Yclj1hByg6ExQ/7aaJviwmPbbeuIrMbctLQDOSe0kJYha82td4puB/kajp6+P/9ZXVBf7/Rk8A/8t99/D/KxDF8MhKKkBCt8znxQRABE5OOgYpoNgzhJNuj+fZRoZvZdDCOZ0Mhz0MYta9RCx1Athcdyjsd9gETiFCjHKD1zgwyknKSLBPpKMN0jnl3ULZsyJtm4ajLpS0kBxnzWpjxi2+MTTRJip1q9EWiuSo7AeUmURE3ij7l0l7tBaNCAOOnRysAb0aycck7gslP5N5wwS5ocG/BjTfTUVo6rLOGmZSGjRZQVJIs8Mw90w4xmY6Lz/fF6Jw4SnVP0XTco3DgXBKcxuZz+y0N4GtRYswXCS0orBJkUGqiSr9WYbvG/RlxjVx75bIaSJ3MR4Igxu141cLqnAPj8L/FKL262gB5pD/XjxbfYby39rqQv57kMfZf4MM4Ite9yR3lpfsZzr9X11Zfa7p/4sX67D/z5+uLex/HuS5t/jf6ZUwrUEPGzKbSZQNjnqVbSrEIbmvhihuiPe1PtCnxhjI0gna4nB8gdoO+9+3VKRilZKOL0bUba/4Kez4xC+SoGpbW/X9A+dls/7X+taB1wzeBR/uNuutvZ2f4Be2dtisQ6GbpaWl/1ATK8L4/5n0Rfxa4VVLUa2akz6rnuWtL8d2plfymtt4RUITx/A+ogDfsArH0BVe9ZIpPYWaKqr43roQ92LZ5wD9nyCbpSJVF2GXMAZSVzgQsNF1VKQCf23t7W4niA2ER/Vei63OzRtiItXXfKkgfnEv3TNgP5DNQe6lSO/KIhS5inpNs8DYuzjp4umnDge2/hJZoavFb+7VDPoDFZCnKFQLxn20GMmM2OZ+7je6c3HjRVHA1U+V8QBYO+BGTWOOQMDyWcHK/UDl2/Wfdg93dnQRL045z0cHENcRyaM/bEYr3lbgSpmbQQsVDD5urhnvBLDvHzC2mwDMtKiDydNm0F083b9v3HaVZZQ02Qd+xGanJNd7pAt9hFM5VjApTRVoebR1AnKuaDuvM8KoXQCef4yfrJvOLu1CUiWzuxRVIkW1VlHBuRJl3ZC4nqSNprrsuI5xx7qfrdrGjpdMGGEFC4xUzImhISY7HA40gyUMQLARjXU+p+OblFqa5gNk4yGBccpRCCH5eMgF/nyYiGrxnGXgwUk/DPwKhYsTcIYi0Yb7zd5+tQEAAsETZs5jQhKuquIEUC+YcEIyLLzEvKUYMt0BDhkf0DKSMQKndftcm2/wn5hx2Z2WpF2WCRC6Ie+6H8fFVWSH1fNkXJQGWCXs2aHdgZt+d/SicaM9CnVWou6gxetALgQ3SORNzn5oV+W5UttatOyTxeyF9ZMMQW8dqxSYlqRTpNbK0YfkarPXvjzptClF1Ab9tyopfhX1LiUPCuMzTCVHFN5I5qGPHkGmGqF1EEXQRUVdqT6vHAatLDnHwv1M6No4IAZ6hHa7qWcq5hxABmT3PFnrg2+PKqvH1CqWd08jR9GE4UyZvM5tMWqji5Y7D58Wtj8ZeNBZBfgoJk5xJqBFGhNWrOI4fJoJhw+xdLdfNPN0nEJ1MsAwEMjJYNAL4EhV1DCpk6rveMzZOVy8bcxJ+ZJ6KPMnRHQZiJLonoQ2EdLVCAl9IRA+rYQ19P5gdNnudf9JxiACl4OMCEtXePcOj9yyWPJPF3ijootbFK26bOIYq03942ht49jcPbPYJuBFgOzuObxMCohosnoS2LMg9wsjYxdZx6fnp2FZZanRTIyT/yQQh3sjYFBN5eoIjLt54gGHAnlviDjeuUo3aUpQh+dm19E2P0ZUBsH6qyzBvG/6LdvfF4VrJC2esDst6vC2IusQvn3Y5dRDCCxPu9Ppsmp2i0cMFfCfr7MqZ3BYxwnG5MNrzZQ5jA1EUbQaUmJFxCXYhiBHgqunD8VVN+l1mIHh493LZmN0LTMBIZWo0n89YzpunWRsd/RYvTStS2R2pnU5Z0/fWuGxeKwnoP9zAqrfvY8Z+r+1p2trOv/fU3i/+uzF2iL/34M8c+j/Rsm86jvhyucrlWUZJhMh/pexcYhX4S9IKfkvxTXyTwfr8EvFtZUFhyEVaeUlwOrbGFqguXfYwuDXZPRaxTs6NKXl4oXiX7ppqfiXjb9/Ofrz//Pl+F36pATsCLx4l/5Q2YL/vGv9UPoL/AuvAJ7Siy+U1+gLeXx8GU7gxWUyOk/g9Uk7Tb6cXiSj0VVl2D39AK8+JqPxFxly/AtyMqcXpXcnBRibHlrzcPeg8baed3jwa3SJoxudfekkPfhr+Sj9x/EXVhZUEBe/Ozn6+7v+8ZPKKDkFrin5UhDNfZicJKfjHk+HUkVgE8kYhj+ADcExnrZ7SekLULpRG7bs0i4KSz+4KqnmgJhCb6pBYte+YJgdXCT8UfrSIU8aXk+c2yBN5HJOhl/Qx12Xlc32h9jtcHICBOrii6g10q/ECu7XDrbexPDfN/bS4apdlv7+7gn9H3VV63S+cD6RLxSFLinBe8osAitarP7wF/j95I/ABxzukkHOlFZ/oP+jVk+WS38pwkqPYa1/KEHtn5uNg3r8815zu+VX7sKwoRJxHV/YXucLhwf/gtenXyj7htoO2swv9B8QS4E5+iLYc5w8zf1N/GP9F1KWk5sfsuw6m4T4If+l/AU6wjbllcHbZQ4xhrH4mWFDrSk6Z0mNbizsg4o6bYVmhwAYQkyQLuoxNVKLpIsI+U6kINEyUQ6+io+71g5Nr+vwOkblAkgg/zUAsQ+1msTJ+JyQJXwWCnJ1OOcOKd2KYg6adyZVkuYUWTW3GWmoreJlOwYrElVLupz06iD9jum1YcKnVx9nTgX/AFLVcif5uNyf9Hq25HxEop5QHIt/vy+8+/572zuERqH0h5enQzFLhyN25mgq0fCtVp/lZXk/JFdlh+/FXx7bC+1B0SrSkFGRFFH6RLA3r+oM64dgRw1Y6oc0vywfVBlkVRI7ZKwN1b9HhjtHP2JTqaTYLHZ/wM3p9kWOWKKHhJD0LZNBni3tjqunUtoiUVboi1BQ5zdVX5H3h0CmTk9xscKOjogKyDl9ZCqudD6dEt0LCRjWeMPWDxlJdbgg3idtulon4VoJc+FON0UKRUODwwcJNaQ+4rOQk8VYVNME7UbVObS3kfQUBW3DJOxxyFZ1MDrpdtLISGBJ9kcUo5cNNNH4RxppVqPDNNGWUh0gFKPLbh8NSk8NIym27GI7S+lrWhF8VsR+plU3QYvck+AUBYNyq2kmMA4OOIbj/rNlKHvZPR8Joyag7x+7p0nELBKZPRGxP5VGTzAXc5WEwy3Fi+VVhP5nzsoGPQkIpHOud/h+i5M3GfploQfX2kEB9lqHDAA2Yy3IJhmJfEoDJp0PxhjgvRShPdnEK9F7pi4PZs5L0hYDSWTALU6FL7mmDvh0MAFZnwqPMHTyWERUqJChF3MRiApgW2VKNQ/SiNDMGjmiwFH7U2zRHef6Q6pV5WWxLO/dV2gFLIazP6E4BEnI+zAY6oLH \ No newline at end of file From a7c5fc503533c398ad3641cee0b0482ae37b2db3 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:34:27 +0200 Subject: [PATCH 10/40] chore: add implementation payload part 09 --- .bootstrap/part-09 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-09 diff --git a/.bootstrap/part-09 b/.bootstrap/part-09 new file mode 100644 index 0000000..8ebe79e --- /dev/null +++ b/.bootstrap/part-09 @@ -0,0 +1 @@ +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 \ No newline at end of file From d34ff0f7dcde8e8dd1e9b51e2187966ad228d1bf Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:35:51 +0200 Subject: [PATCH 11/40] chore: add implementation payload part 10 --- .bootstrap/part-10 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-10 diff --git a/.bootstrap/part-10 b/.bootstrap/part-10 new file mode 100644 index 0000000..18a13f4 --- /dev/null +++ b/.bootstrap/part-10 @@ -0,0 +1 @@ +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 \ No newline at end of file From e2389b9c01eb40a92d316734a5c3490eeb4f137f Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:36:47 +0200 Subject: [PATCH 12/40] chore: add implementation payload part 11 --- .bootstrap/part-11 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-11 diff --git a/.bootstrap/part-11 b/.bootstrap/part-11 new file mode 100644 index 0000000..4544c47 --- /dev/null +++ b/.bootstrap/part-11 @@ -0,0 +1 @@ +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 \ No newline at end of file From e532196d440b331ab7888ebc1341982a8a25648a Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:36:58 +0200 Subject: [PATCH 13/40] chore: add implementation payload part 12 --- .bootstrap/part-12 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/part-12 diff --git a/.bootstrap/part-12 b/.bootstrap/part-12 new file mode 100644 index 0000000..a810e36 --- /dev/null +++ b/.bootstrap/part-12 @@ -0,0 +1 @@ +/7+Wptl/IPNDRCNBMDADcgRrz2Q6vwvHiMvIDD3wmYSjMTk0RssFgkbOScJCi9MJ6BCyH4wLwrjjOaiPk7RxC31Vrer8z+jGjtMPt/uAQFaef7tY/9Vs9L+aGup/049aEoGm1K2LtdEDbpcTJhQILJZG5/umWtX53zP0H1ul/dcqxf+5ZnP+a2k5/L8sgP1fkEnOyAPQyCQOpjPQDnhIlIzKpt9K0mbBv4wsIC1RP0YE0pXGWoiDu+pfvx3c3AwuL2S9TT32/7frwRDCuW6G14OTYUN4nqBVnf/H8ANVnX/bt4v832nOfz0Nzz/d+UAR+YdP3ybOGQb5zNI98zcYTPLKexsRieaQP3KrOv+P4QeqlP9L9b8s22rq/9bSGv/Pj9208w9h82/3KPOztlWcf8vpFPCfLMds8J/qaYD/ki/7K74HNAhmxOAcABBbmKUwA4TReZTSe6x+DJMQtUJCMYkQRJvVj5kuF7PlwshuwxnJjgza6z2+DXAEBF6/fD37iUgpwcoqgAC6US3hVtt4n0F9Hl7B8r3xz//6X9oFMcbTz20AXjBG5Db8lE7nvP4LvOu9KiX6/gi7yNfBZL0kEP4CYXGfoUgPIGPTAYzGxLhLP8zzEfCr+tRjK1iHYQ5aRyDuZIvpbMZq84igHAGvIGJzsL9VvJr1C8bYO7IIISTXEDfZ8KYzBt86X07oQiRTqO3MBLIM8F5hbMq8S7XAI4EGFMb38rOAgF+D5cgYPEfGeI8ZMu8PNTgfOq4xixlCnnJIN+5uiTZjAyDWyWcjo1schXN6C1eTbg/tiTEUXjRJlz2w6/mCfj/nD0LB0omNp5MPAGURk7nxXoe2fkFHCCBEULuoMUI3rWlNa1rTmta0pjWtaU1rWtOa1rSmNa1pTWta05rWtO+1/X/QoBuxAPgHAA== \ No newline at end of file From 02a39c1a1f9b4487d4ab07123335fb67fa8cadc8 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:37:10 +0200 Subject: [PATCH 14/40] chore: materialize PlanAnvil implementation --- .github/workflows/materialize-plananvil.yml | 47 +++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/materialize-plananvil.yml diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml new file mode 100644 index 0000000..46104bf --- /dev/null +++ b/.github/workflows/materialize-plananvil.yml @@ -0,0 +1,47 @@ +name: Materialize PlanAnvil implementation + +on: + push: + branches: + - agent/implement-plananvil-skill + +permissions: + contents: write + +concurrency: + group: materialize-plananvil-${{ github.ref }} + cancel-in-progress: false + +jobs: + materialize: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Restore implementation archive + shell: bash + run: | + set -euo pipefail + cat .bootstrap/part-* > /tmp/plananvil.tar.gz.b64 + base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz + tar -xzf /tmp/plananvil.tar.gz -C . + rm -rf .bootstrap .github/workflows/materialize-plananvil.yml + - name: Validate implementation + shell: bash + run: | + set -euo pipefail + python -m unittest discover -s .agents/skills/plan-anvil/tests -v + python -m compileall -q .agents/skills/plan-anvil .codex/hooks + find . -type d -name __pycache__ -prune -exec rm -rf {} + + git diff --check + - name: Commit materialized implementation + shell: bash + run: | + set -euo pipefail + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "Implement PlanAnvil skill" + git push From 3cffafb3dd4550b429f06aa55acfd55ff83144a1 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:38:38 +0200 Subject: [PATCH 15/40] chore: allow PR materialization --- .github/workflows/materialize-plananvil.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index 46104bf..209faea 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -4,6 +4,9 @@ on: push: branches: - agent/implement-plananvil-skill + pull_request: + branches: + - main permissions: contents: write @@ -20,6 +23,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + ref: agent/implement-plananvil-skill - name: Restore implementation archive shell: bash run: | @@ -44,4 +48,4 @@ jobs: git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add -A git commit -m "Implement PlanAnvil skill" - git push + git push origin HEAD:agent/implement-plananvil-skill From 5ab19a826bce665fd3e89a37077aa2d702ed0076 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:40:37 +0200 Subject: [PATCH 16/40] fix: restore implementation payload part 01 From e29eee2b01042f0b6330748154180462c96a8bc9 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:42:53 +0200 Subject: [PATCH 17/40] fix: add verified payload fragment 01-00 --- .bootstrap/fix-01-00 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-00 diff --git a/.bootstrap/fix-01-00 b/.bootstrap/fix-01-00 new file mode 100644 index 0000000..a6a7e3d --- /dev/null +++ b/.bootstrap/fix-01-00 @@ -0,0 +1 @@ +Te/qUvRtt/43WI0tHvF7XzFvmlRj7+zayt6qMIZvTUV/vU8+/o+O0q0ZwBn83+qz9RfK/2ftOcZ/f/F0ZeH//yAPhsdm/isWJncbUYEYscIS4dO424E3CpsCV1dYEtb89F7wQfjaRt/01UXXhSXzJG9ER4hI/vdho0kKPkAOx0vSSJ0+ol0NYLMafqA7Z67SaP1IZU0rf/pi0gsskOEzQGVr+/s7MLCXO/XYJmhQjc3/YrpVjUnxy1V2dvZ+rm/HP+Ow4v3awRsqLmKMm4tEsdFsLlrwlCbzuF0/qDUkz3krep/Hd4LIA4/1FpTdp9LSmSJMoIXDpurM97cgDmRrq75/AOx4PdZ7zFQHt9mkm9QPbbns4AColmzf1TjDIgk+Jt76ZUst/lvpzKEj0ArPjlSQwbpsUdyGMysjuUUsJEIn0CAwYMT+HtBuh8CaNPXXQJhy4n/Xg3muPmbh/1U3/tfayounqwv8/xCPkRmB4raKy519Fo1I4Oc/hRWEx8m91tLsmD7KcCbbce1AaAbMSyMQDUbDUbfPhYGPe11v7jfpIGFZdZxPsmR85ky1SYgMPMwssRFahmUAxGaHTYkGdkA0mbBBEwiXZEUurZgElrvC8AxQYsR4gd3VJWogOy02E6IQFMo4DvXwFXV5Iq11JdIAjNHSEoJpM0/V/zFpC4OhsRYNmocaI+1zvHpXTHUQdvy2tq9xtnDvKquwD2aUViWEAPre2fsFaa+BfXkl0cddRFYTgWwZC8f7e4Dff3HRL3lBoo0XGl+ZaPjXgAV/v8+t8L+0ts/Zx6z4j8+1/5e0/1iBVwv8/wCPif93yHRWoX5KTiHNajm8jvTtwkQAaXI6Ssa+24h045BBNISRHN1cGvpZeTVqa2hljC0mBi07vBLTHg7nZRecSYQI9w9ORQwgxM2MuIWLC+KrnT2033fQ9Zuk3RtfqHtERwEzMpg+rg6MO6tyFOpW/qkceGWSXlTGo+75uQiNLIQlVuHosCkPhjTznX/HUHXOPmbGf9Xyvzj/q6tri/ivD/JIS3S61mkKc3Sh++uh7ydr+nbUKSIpVZpfd1xx9RW0BcdD6ui24UzLk2AqXwWHoSRDaQdvq2RtVaxpp+1pPx2h8LVvs61vYoCd3Dvc3da63q1BXwjZoikhZP8eOJd85588Xyusi73/8/9izZX/QCRc0P8HeUz6zxp3NnqforvPecVqFGQWgAoKHYp1X6vvklFLxe+z3IyorBHiSyOniuVTw/fQFBrTKqNdJuRwZMRMG80ZF2nC8VOGv7Bvz1AZJG/QBDqhuw3Mc0AKu/rWIQ0UeGeog0W+ugH/PFgr3/k3/DpvAWPG+SdbH+fflWeu/c/ayosHj/+Ol3PTys36/it9PGdeov3SaWbgqazV1aCXksyR+YmwhkJFMefcTYlrDl7nOkptcoNXYWnoAL56RSbCsaXV1ifWOaSiwKE4wl4SMizunGE0Ori8ZMNgkVrMGgEp+h+OS/96z7Tz \ No newline at end of file From a155efee85997f3e86bf389aa90c470d4e1e7057 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:43:08 +0200 Subject: [PATCH 18/40] fix: add verified payload fragment 01-01 --- .bootstrap/fix-01-01 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-01 diff --git a/.bootstrap/fix-01-01 b/.bootstrap/fix-01-01 new file mode 100644 index 0000000..c4bf0e7 --- /dev/null +++ b/.bootstrap/fix-01-01 @@ -0,0 +1 @@ +L5w075wAZA77v+dPXzzF/B/Pnz5f2P89xJNn/5XZDb8g25p5+pjB/71YX1X834un68+Q/3u+uuD/HuS5Xoqiwh87yVla2IiuKdtpAQMhqF/we4guBaM+vCr8XURTOVqp/Fu7cnZ8/fzpzR8LZVlyfDVMsFg6HgGjUqDXN/y1YIQ8MRtvdzpkW9fu7Y/QzhwjlxVE4g3V7tD8JKtif+3ReTK23ulRHBnvIjWmsv22P+n1CsarY/X3Tdnoh1u0egHmdCfpn49xqVbLgf6tVaAWl5yWC9Iz3hot1y97sxQvjr3VHpzg7YC92pS5t9vJ2sb91xXcwuPrP92IP57DH7XKK/o7957KECF0RW72FVycQn9g75U5pOJfNv7+5egdPMvHpXfvqvD/8Eq8+PLH0pe/w8/lLzDG/2xX/nmsvrwTT6ngre7UkU+mLY9cmwO5Nv8Zz1qx+AiGhX//AOOsqB+lJzmXEg7WtNHQYXu6Us5/3qT1RlarHKKRp7J2g+t6/JecTavoS2bb6NfWxv0toDlrBcvMaG1JtFj4I42ycDEeD9ON5eUPydXZ2WWKYXEuJifV7mBZyahTaVKBG+M3ZoP4sSIKDkbny51R+2y8vAZyRmV1TTTJlWdhoxAmKkgbVmlBYyKpu+E36QsfqzlZKAg6TmnFhcGO/GCiLlvUjFFNn9nMWnU13AhhEznNKaNYsUaRE92FRpjZdzl7cebCjyIafNw2p1P44yg5wxrfLRNJXNaAblVWISHkjk/FIz8AKnP+yHnOSP65N2DSUfbcHXSnbaP1IETQFWBMd8v30Bru8T00o71TY2HbfR+NAqVA4f8emrqv5TLDjNy2uZyHU83e3S1vWuUgpGWNevquZQDaXTkgd21kEYenkcO5t5OHtiwxa0vvgYssOw3bnENwolgk2IBhjzOrDZIKMk8v6nkzpmgiRDNXyCyOank2RzV9oXKCuLkG7tqKGYWWfMoCzAWnPifqHeGJD6W2za5ZO8QUaFbLWwK3Jef02IP0iWcmRfRPk0XUZEse67Qk1g2YzDHhb52GMpJMH/Nq7qL++pVx3+DJo/8x/apuowKaof959nx9xdH/rK0t9D8P8yz0Pwv9z0L/4y7PQv/z2PU/GTTpW6mAKLXk/YnqLPTklGEdxjwnkrG7mA+33KtaYupc7yYeKb5cWpDeb/Mcq/Y+G8+5d27HU6fsydK32vMHkVJkLZ5e2m8P0wuLZNxRDA+Kp/fPLVwk7c6sQ5spkZP7euywYMEmsgVydtW5TSM5AZBmWPZWNmMI4dnNBX6cyHVede3SvFKvLeYanYZkV4HzM4B2aYoca8So/taibB757/aSHz8z5L/na6uu/Le6urrI//Mgz0L+W8h/C/nPXZ6F/PfY5b9HI/mpW+jcIqAB/9O4MR+Og/fYnMU+HkJVE0X5SNBHgBbyOw42S0B0Nwi65Qh67XQc6/gL9zc1DMprtpb0J5d2a+SKIDwIG3u7ZrP0SRn1hzvIIHTu \ No newline at end of file From 8b3f85bd8d50c7b980bada5149325c814e306303 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:43:22 +0200 Subject: [PATCH 19/40] fix: add verified payload fragment 01-02 --- .bootstrap/fix-01-02 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-02 diff --git a/.bootstrap/fix-01-02 b/.bootstrap/fix-01-02 new file mode 100644 index 0000000..1289066 --- /dev/null +++ b/.bootstrap/fix-01-02 @@ -0,0 +1 @@ +XpvFrPoAKv2Y0kcCc2q20B0nly4BDJIaH3Tao1FbX7oWJv3uPyZJQ7SHKZcdtM5pyxyM3r2klVrxWqeIV8noXmQ/khum789u/WdzT4RH6H6z/mqn8frNQbxfa7Xq22YRcqjHHJzuXlpOp4Ei7PDsf3Dc7v0CMtRZ4EvzoPGqtnXQipWTqvl5u36AbqC7jRYllNr5hRPam0Ve7jQoWBc5t2AomoO6BaSGU4tXlwCYnXCcjlsHe/v7dacjivpsvsKQz/Yb7eLiTVV/apADzOtmvdUyC1CN+NVeM2b3WSMWWoyR1ax1+7nWwFBr8WGr3oy1C5BZhj5xaBl7kPShWf8ruQ0EphgObB0+3w8li8pDmCmNEiazz00QfQdJRQBZZWDeIFoqh6nf0hSp91HIu4vHfvLI/0Z61lspAWbJ/89ePHXvf1fXFvnfHuRZyP8L+X8h/7vLs5D/H7v8H6ZJ38wDQCbhtjFUSGLLg++yMR7KQ8Lf1nkf7E18yGkTbJ0eZ+NYgFzKKFjouhdeDrBt1fbxsPwnQFvFNH+fAh6hbgx8eR1u4WQw6CXtfnYTnoAp3ntipnjPwZQtoUF82d7bOsTIaaFvnpgk3vsSlfgg/I/9D7t7B7GOVGpv1rE5yyDhChIY3q/QqoQXuxwEP/Xy2OgvRJKy9REWUsEY9p/vjTPA7JCxo+rh8Yf2ufBmb+/HVgwifcvfTvFxu9HCHcj4erg7tfLhbu0nAAl3C8PcBqWNymBqpts7qGBTwannaoJDDcbj0ST1GKvw2mVMPHNFJKjPXAdfdTR9GjnZK1vOple84lNWMnOFyiGQm4tTu52ezEhme68qQqsTESf3ll5Sn9ojtES5XxWmwznkVaaYM7HwjfxhEvDAErtTWpqi59Csiche/5h1Hnnkf9Nx5zYagOny/+ra+tMXrvz/9Pki/u+DPAv5fyH/L+R/d3kW8v9jl/+zaNI30wCIXAVfW/rvJOnpqDsc+3zxNJQ0h4g9U5I/aO44UKN+3lquN6Nx3du0gpg8r0BsrnP2UNWH+5KBRYaMrw1FAWjN7E02dksYmLpHvr4J9lqaJWRttW3LID5mWDQEOnmcCjQ5qDjAamRJ3vC+dniw95biXDvX5eI7xu1sbKnEa36Bt7Xdw9qOlTLML7T3slVv/pTxUarBhEFCoIuGvNKX4QGnaLHmwkW1rXvHRJRk6JbHArMjfKVjcV+w79pzideed4LkHe4Nn5qWCLIqLbX1SuGlKWfjYbSR5+3hV6fliO0xffcdtNkdTFseaOA+OIH5MNHhLuUOrKNhkkroFURIr+vxz42DN3uHB9OLirxQgDdkcYU/vLKUmEQWE8HAAy3yB1XwZf1N7afGXtMvuX/4cgfwpizgDngbVfLNvZ9qO/elkPdBW0FHaMPvG9zNrGwPAfYOk5PZm2zsVkj/8bEe93DiZ9FEgNB7J4qEvOehinnoyTfZgHHy2VUXfSMBg0aS48CLtfdK0gm6bzTwtaPKWGjG \ No newline at end of file From 166e1c2cd42c001be156d1b67ea08c290e49c8ee Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:44:06 +0200 Subject: [PATCH 20/40] fix: add verified payload fragment 01-03 --- .bootstrap/fix-01-03 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-03 diff --git a/.bootstrap/fix-01-03 b/.bootstrap/fix-01-03 new file mode 100644 index 0000000..ecf952d --- /dev/null +++ b/.bootstrap/fix-01-03 @@ -0,0 +1 @@ +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 \ No newline at end of file From 6860ae3ed0641dd17f6794067cd6ec7c3fb6dde7 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:44:44 +0200 Subject: [PATCH 21/40] fix: add verified payload fragment 04-00 --- .bootstrap/fix-04-00 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-04-00 diff --git a/.bootstrap/fix-04-00 b/.bootstrap/fix-04-00 new file mode 100644 index 0000000..398bbb6 --- /dev/null +++ b/.bootstrap/fix-04-00 @@ -0,0 +1 @@ +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 \ No newline at end of file From 50738326da6e079e161e21aabeafa3395f10b14d Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:45:11 +0200 Subject: [PATCH 22/40] fix: add verified payload fragment 04-01 --- .bootstrap/fix-04-01 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-04-01 diff --git a/.bootstrap/fix-04-01 b/.bootstrap/fix-04-01 new file mode 100644 index 0000000..608ff80 --- /dev/null +++ b/.bootstrap/fix-04-01 @@ -0,0 +1 @@ +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 \ No newline at end of file From be1a7dd538a2b241f3cc78636510fb526f1b26e2 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 00:54:34 +0200 Subject: [PATCH 23/40] Retry PlanAnvil materialization --- .github/workflows/materialize-plananvil.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index 209faea..d5b07bc 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -28,8 +28,27 @@ jobs: shell: bash run: | set -euo pipefail - cat .bootstrap/part-* > /tmp/plananvil.tar.gz.b64 + cat \ + .bootstrap/part-00 \ + .bootstrap/fix-01-00 \ + .bootstrap/fix-01-01 \ + .bootstrap/fix-01-02 \ + .bootstrap/fix-01-03 \ + .bootstrap/part-02 \ + .bootstrap/part-03 \ + .bootstrap/fix-04-00 \ + .bootstrap/fix-04-01 \ + .bootstrap/part-05 \ + .bootstrap/part-06 \ + .bootstrap/part-07 \ + .bootstrap/part-08 \ + .bootstrap/part-09 \ + .bootstrap/part-10 \ + .bootstrap/part-11 \ + .bootstrap/part-12 \ + > /tmp/plananvil.tar.gz.b64 base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz + tar -tzf /tmp/plananvil.tar.gz >/dev/null tar -xzf /tmp/plananvil.tar.gz -C . rm -rf .bootstrap .github/workflows/materialize-plananvil.yml - name: Validate implementation From 2510f69aa5bad77a74772b09d966db29d5c75ebc Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:12:36 +0200 Subject: [PATCH 24/40] Add missing archive fragment 01-04 --- .bootstrap/fix-01-04 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-04 diff --git a/.bootstrap/fix-01-04 b/.bootstrap/fix-01-04 new file mode 100644 index 0000000..17d7c8c --- /dev/null +++ b/.bootstrap/fix-01-04 @@ -0,0 +1 @@ +7+RqnMS97qVtNa4Tvfo9BRO9Aqt71uuePkzguDtGT3O3JnO082xToCN7y9YybpJmxIQFXn/Qm4RjIgdpXBaVC9C5u8Qq5EUsB7cmawLq9T1dYwHUkKdxfNbtJf325cy8W/OJkXkPE/b+1eE+E7Fk9ik+3A/0To/Flwm9iF0Cgw2gF6ddC8mEWj4DWAbZ1vMlMcTuqUEAHWZl3sVyGhslp0lGPOlAzux555q2z5LxVSzPVzya9EKrmgkC8wTAzLmxrr3u3daPBYrZzZl3zn4rsN99jskeU0CBuSjE3MivEJpBAPgzoDawmlkgZb138MDUBcgBRPeNks+TfjK6vQLya+vSrOFJXii0oiHaMo13skiBxxMtTVGgGUxsBEzst1Cf5dH/tIF0XaXd9LYWwIb+Bx/332fPVr3737W19QfW/4wGg/G0crO+/0qfh9P//Hp1BY9A3A0dwYWcO13OTdPJJYVK+vqCKWD7rJwi8+eVxZBTGMP+VaP5NvS9sfuq3mzqKyl+so0dv2W+E+fjryJSdyAyt97f8MreNyt12gPoDWVEClxgNlp7O24Es63mXqtFjmN7u3ZuBcoIU391aN1ximwHtf2GVbK+ddhsWC7zhZ3GT/V4bz/gTy3TwNSy3anvdD8dgOJ7wDe3Qy3nA2Ci57+fv4upqy3U3G+8wNtmoP3Qh8n8GrR+94pLrJa/feKyvHkEvk7esqV5pTDfokEfpuAxCWNE81hMleUU2ghwBS4gL00R1XCUkeTCfkN2DnnkP2BMKypB8i0yAM+Q/576+X/X11ce2v53If99Zfnv3i84H4FYln0yvpklYjtNYi920y0Cz1BDzp5lxmrSfCvQ4Ym1IXcL5jAaDUYeR3DZ/ixZM0uvnicqg2cSyOOWfA5ZA+qKHg0MG2xYRnnmwCW75a14yGTDt1ZUw3rdwNRjte1f7qQylbUoYnCc9tvD9MLSsnyNiGH3b4xzpyhi3X4n+ewy4MEm7AsHsw0OmXGbRnLCkxuby4/eZQ4hPLu5QC8dJ18/3WHIB/U+ePDgkc4+1Hd11xTd3YqFNtVbK97OzCeEMkM/tzg9N8du9mNjKpNSWCCqiUcGyrHAzqEd07jwtN0HGPxn0oled8eRpryRxeb/Njjzh3ny8P+9LkhWV7A/t7wAmsH/r6+tuPa/KAAs+P+HeEL8/+Km5g4iQfCwfCtpIPn4EAldH/aC4QGyhM7PUVjVU6CsGQZB7c/CIOipP6u7mkUhTzjHBRRHp433m/VXO43Xbw5inFTovkkLH94nGcs2/nmv+eNBs17PLNjce9XYqZtCjHxub4eo1jmwDKH9vMe7G0MEfapfash86iGYoHva6WDUeaz2MubolDKV0Mk0Du0EyCTg0vYwUohwwZw94mc6/4e5htLlu/ZBTl7PnmX5fxEvKPk/tAVaWX32YuXFv0TP7mOCs57fuf9Xnv0/HVxeDvrV4dUt+5ju/7f+dO254v+frtL+A7Q8tP3X73T/z0aD \ No newline at end of file From ebbe3a5b29dffd55b82fba0ab59d0be2c1568d15 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:12:52 +0200 Subject: [PATCH 25/40] Add missing archive fragment 01-05 --- .bootstrap/fix-01-05 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-01-05 diff --git a/.bootstrap/fix-01-05 b/.bootstrap/fix-01-05 new file mode 100644 index 0000000..9a740a6 --- /dev/null +++ b/.bootstrap/fix-01-05 @@ -0,0 +1 @@ +yyiOzybjySiJ46h7iTGFonYfuHq6akuXluS70fmwPUoT+Ru5aaRNUTuNOmP5FpVPve6J/IkMrvx7kMq/RqqRNDkdJWP1IZ2cAJ95mqT6zZX6E2jrEK0sl2jQ0H2bbgWTNNIj4ldcAnlJGIr8ug8/+QOQIGD25fta/6ocAeEetU96STlqCa6Ci05GPWiiShOXFeBdOux1x2X8a9Knv5eWWltv6m9r8U/1ZquxtxttKvIr4s/vNc1vK/xta2/3oFnbOjA/rVVXC0tLFLaqsQ0cE7wbJVX0soa5F0fkvPeug35o8F/Xba+01DwM1iMKDpWp5gHVJKe2jJamuLMtlZbIdyxjdOxXBg1qp7LS0pta602ocPA6Cdp/UwuV9u6JSkvG6pJlSwsqCbZmty4tImbwuh6HO4OvdbhZ8bKx2zpoHm6h+Uv8trZvf6zt1nZ+aTVaztvmQeMV7H5L5ijQQ9quH9Sbbxu7jRYFttv5Jf6pttNQnzm0GUc1i39uNg4OVF5DCiZdazZaMA6rDkEUfHyLpdXb1sHe/j79PF5a4j5rOxw0DRf0sEVLem00YU1BhEfAVIkyCF8s41L7RXChaZsyvu1j/y08CK1ACXOF0T5up7F1ECgGB+Cg8ZZ2u1n/34eNVkP3RxOgVSE7pRijPdDkb+AA17eadQQNWJ7mrgakIoi+3Y+oOgD5v1C2YbKCz8v668ZuBAel2apFX+pb0RfMM9lqvYlKf9lvNn6CCUc/1n+hsoVSqSyaJYv07mllPPiAIffthot/6ZbenUCb7WH3KK4c/wU6/9I+RdRIP6nSF0afX4aA8z4Btw413qVPjjY2j/Gfd4Xvj/8iVCuYWaO6/MNm5fh6da18Y46ClBnhQbw7Ob84Gg4m6eg41g0dX6+tlG/enRiNtD+lFR5caJHendR+bNTw9CJCuF59LisDyNVetvZ2Dg/quO5v/MV31uR//cGcT+W4tAwrdDG4TL4cpiC+fBE79eVje/RlfDn8MhiOv6Sjj18u++MvPw16E5CkSstHf3+XvofF+V//fvxDQUzBW3u7r+MSqq1w9KiiWj4uzWwDtVdQ6N279PgH/VdGd960/s/R8rt3x24nsFxLRN8iJXDV8aKx2Jz0kRLTj9IG9QCiI9D1br87juNimvTOyhFMPgVmbyMCAa0cPSlHp4MO/0Kyg0ejtvtTYyeuN5t7TdjDTjJud3vpBlJIKLE76CeicXzSyTAZFUtV1YlovqRLQK9V7AMq4z/2B9E6fBN/weT+Q1HwIlDffyb9zYPRBFrkSW8BH9rud5okzfNAgCeB8Y0nw15yRLOqVqvHYoWBo+nzDLv9Mb1Lx53BZEwzlr+T0Yh/Ly3hik3Gp3F/8KlYiir/jq83jLaAyalKnqeKheA3/v1PWJcqVCxVRwlwz6dJ8bJ7OhrA0Rz0O5srpWo3HbAOsqiLFH5YWdlYWYFVLvwnkjHqXUn6cbdzyyFAhTN8Uyz86y//evmvnYN/ffOvb/+1 \ No newline at end of file From 22a3871d1f39d315146eff00ff702aebf99f8afa Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:13:03 +0200 Subject: [PATCH 26/40] Complete archive assembly and verify checksums --- .github/workflows/materialize-plananvil.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index d5b07bc..926ac6d 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -34,6 +34,8 @@ jobs: .bootstrap/fix-01-01 \ .bootstrap/fix-01-02 \ .bootstrap/fix-01-03 \ + .bootstrap/fix-01-04 \ + .bootstrap/fix-01-05 \ .bootstrap/part-02 \ .bootstrap/part-03 \ .bootstrap/fix-04-00 \ @@ -47,7 +49,9 @@ jobs: .bootstrap/part-11 \ .bootstrap/part-12 \ > /tmp/plananvil.tar.gz.b64 + test "$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" = "d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz + test "$(sha256sum /tmp/plananvil.tar.gz | cut -d' ' -f1)" = "addffaecbf114a6a7fff2dff227b50fe66a47c14f1fb62df88113b49636e29d2" tar -tzf /tmp/plananvil.tar.gz >/dev/null tar -xzf /tmp/plananvil.tar.gz -C . rm -rf .bootstrap .github/workflows/materialize-plananvil.yml From a58191c395105b643bd4cd40b113812cd19ffbdc Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:13:55 +0200 Subject: [PATCH 27/40] Diagnose archive checksum mismatch --- .github/workflows/materialize-plananvil.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index 926ac6d..36f426b 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -4,17 +4,10 @@ on: push: branches: - agent/implement-plananvil-skill - pull_request: - branches: - - main permissions: contents: write -concurrency: - group: materialize-plananvil-${{ github.ref }} - cancel-in-progress: false - jobs: materialize: if: github.actor != 'github-actions[bot]' @@ -49,7 +42,17 @@ jobs: .bootstrap/part-11 \ .bootstrap/part-12 \ > /tmp/plananvil.tar.gz.b64 - test "$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" = "d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" + actual_b64="$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" + expected_b64="d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" + if [ "$actual_b64" != "$expected_b64" ]; then + printf 'actual_b64=%s\nexpected_b64=%s\n' "$actual_b64" "$expected_b64" > .bootstrap/diagnostic.txt + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add .bootstrap/diagnostic.txt + git commit -m "Record PlanAnvil archive diagnostic" + git push origin HEAD:agent/implement-plananvil-skill + exit 1 + fi base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz test "$(sha256sum /tmp/plananvil.tar.gz | cut -d' ' -f1)" = "addffaecbf114a6a7fff2dff227b50fe66a47c14f1fb62df88113b49636e29d2" tar -tzf /tmp/plananvil.tar.gz >/dev/null From ef4ef9a01c619f1838e762dd48b593300ba3abff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 23:14:01 +0000 Subject: [PATCH 28/40] Record PlanAnvil archive diagnostic --- .bootstrap/diagnostic.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .bootstrap/diagnostic.txt diff --git a/.bootstrap/diagnostic.txt b/.bootstrap/diagnostic.txt new file mode 100644 index 0000000..402e188 --- /dev/null +++ b/.bootstrap/diagnostic.txt @@ -0,0 +1,2 @@ +actual_b64=ad9bace931813c297823659bb246c0ed9104b12f9935658ec3f35ba060bda99e +expected_b64=d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10 From a436c7d55069930bfdcda279d5abde2a62ae59bf Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:14:19 +0200 Subject: [PATCH 29/40] Record per-fragment archive diagnostics --- .github/workflows/materialize-plananvil.yml | 38 +++------------------ 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index 36f426b..445862f 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -17,11 +17,11 @@ jobs: with: fetch-depth: 0 ref: agent/implement-plananvil-skill - - name: Restore implementation archive + - name: Diagnose archive fragments shell: bash run: | set -euo pipefail - cat \ + sha256sum \ .bootstrap/part-00 \ .bootstrap/fix-01-00 \ .bootstrap/fix-01-01 \ @@ -41,37 +41,9 @@ jobs: .bootstrap/part-10 \ .bootstrap/part-11 \ .bootstrap/part-12 \ - > /tmp/plananvil.tar.gz.b64 - actual_b64="$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" - expected_b64="d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" - if [ "$actual_b64" != "$expected_b64" ]; then - printf 'actual_b64=%s\nexpected_b64=%s\n' "$actual_b64" "$expected_b64" > .bootstrap/diagnostic.txt - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add .bootstrap/diagnostic.txt - git commit -m "Record PlanAnvil archive diagnostic" - git push origin HEAD:agent/implement-plananvil-skill - exit 1 - fi - base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz - test "$(sha256sum /tmp/plananvil.tar.gz | cut -d' ' -f1)" = "addffaecbf114a6a7fff2dff227b50fe66a47c14f1fb62df88113b49636e29d2" - tar -tzf /tmp/plananvil.tar.gz >/dev/null - tar -xzf /tmp/plananvil.tar.gz -C . - rm -rf .bootstrap .github/workflows/materialize-plananvil.yml - - name: Validate implementation - shell: bash - run: | - set -euo pipefail - python -m unittest discover -s .agents/skills/plan-anvil/tests -v - python -m compileall -q .agents/skills/plan-anvil .codex/hooks - find . -type d -name __pycache__ -prune -exec rm -rf {} + - git diff --check - - name: Commit materialized implementation - shell: bash - run: | - set -euo pipefail + > .bootstrap/diagnostic.txt git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "Implement PlanAnvil skill" + git add .bootstrap/diagnostic.txt + git commit -m "Record PlanAnvil fragment diagnostics" git push origin HEAD:agent/implement-plananvil-skill From e4e60034430d897c43bb635a2f26a67bb98e1bed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 23:14:25 +0000 Subject: [PATCH 30/40] Record PlanAnvil fragment diagnostics --- .bootstrap/diagnostic.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.bootstrap/diagnostic.txt b/.bootstrap/diagnostic.txt index 402e188..545bc1d 100644 --- a/.bootstrap/diagnostic.txt +++ b/.bootstrap/diagnostic.txt @@ -1,2 +1,19 @@ -actual_b64=ad9bace931813c297823659bb246c0ed9104b12f9935658ec3f35ba060bda99e -expected_b64=d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10 +278b1126142d5d6a1c7a0a398bd03e01b1ab05a608cfcde2aa2189f5d069b794 .bootstrap/part-00 +1038a66a086d68d6e6853efdc161e8ec9230ab8326588ac22728e6aec798c372 .bootstrap/fix-01-00 +969b1d29d516e6f884aaa1238f1ce1040eb79bd53c777bc48b5d5ca1ee3de776 .bootstrap/fix-01-01 +4ed9ff03b6060ef19cf5487850288a1a192b08d40631a3a6f73d7d8c1990c7e4 .bootstrap/fix-01-02 +d522c6cd22cb9169ace4e2624f5c22103cea3ae236018cac76a6784bd6d4ba40 .bootstrap/fix-01-03 +9f4b935b5dc750ab06116079971bc156fe3946de98bcfb3936b78748108485bd .bootstrap/fix-01-04 +6dc8cb1408f44785a781dba5b5ed22b0b2eaf63fd8f94b148bdc15a0493cfba1 .bootstrap/fix-01-05 +05e4003e4584cec8e25899e1ce20c891c7a24149181dd9bd907484213483d8eb .bootstrap/part-02 +093e88fd0b8fc2714d3f083ef10bddf2d0992a29a7e679032fdd9f415c4ba684 .bootstrap/part-03 +124543941a2fef6b58c228e1642e1f0ac080c8293887fdcb8700ed5c61e10042 .bootstrap/fix-04-00 +2225460971a6672bf560ef630a007f54f368fd31f18a87b30574984b02732230 .bootstrap/fix-04-01 +00f988ff3456e2d14acadfc85b0d32532736860c6aaadabb2efd804696f00cba .bootstrap/part-05 +b63ebc9bc7c64eeb6b4f7fde1f4dcf25764134b16c5f2f94e428252fbf78ab6b .bootstrap/part-06 +f77c10a5fbf088a311f9ae7c613f53a49eee306da80b202fe2c8baddb1fc0a44 .bootstrap/part-07 +ccb94a4bdb728ae855f4fdec22711b3168b97cc2a215f11ef5886c1cd5f8b0a2 .bootstrap/part-08 +37cc095b9b582c69bc9b4e2cf5c5e9c9a780147573c2c4e2ffecf5344549b445 .bootstrap/part-09 +24cf9ca867f5dea1cee9bf85ec4d300bb8e8c7b913bbdac3e27d2c3d61b70bd1 .bootstrap/part-10 +ca5804aba885b243d6bf94b221b60ac6d93b656d12abc2e77fc2807cd545d8b7 .bootstrap/part-11 +e8d0a065720a4d4fc28aa0859f5f153c469ae2723020fc7e7fba2623dda152ad .bootstrap/part-12 From b02d0e1af1bec21f08265ab9e478f8879e015397 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:15:52 +0200 Subject: [PATCH 31/40] Replace corrupted PlanAnvil fragment 01-03 --- .bootstrap/fix-01-03 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bootstrap/fix-01-03 b/.bootstrap/fix-01-03 index ecf952d..3baf905 100644 --- a/.bootstrap/fix-01-03 +++ b/.bootstrap/fix-01-03 @@ -1 +1 @@ -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 \ No newline at end of file +lXmUXt7iAZgSL03Rt3txpR6pqv1RPnn0/8io3cH9b7b/37ob/3flxbOF/d+DPAv9/0L/v9D/u8uz0P8/dv2/S5O+ld6/LXJVxHjrP+jnkJ9m2TuEuODpdlO5bh5uo7+9/7Hm02/PL+7d+0jD9ywZeG3aWQGBPfGI3mPdn2xskU+3OXUlupdDO3p0wLVvZ89y7Xtb324cvjXfvGm8fpPhMJp8tKzm7rf1S0AN5+791C3AAXDIiR+5937HKvPk3W2kd4ndc8eeXafj6eqEeVxH9/ZtV8m3jYPGa9cFUzoQklNgq26qBwtbO3uOb2mzXttp/Ce8s/dCEbe8srGOO2N57TFYB7CSveDlbHIUgDz7RHqYKqdkbpwJF/LsLVmaIr0jIV9I7d/syeX/p3xBv4b/3+rqsxfPPf+/B8//tpD/F/J/tJD/F/L/Qv6f2fQjkP/DNOmbaQGQhMZOENC7obYMK6WMO7f8FkrBO37XOsnEfUGHuQxXIIw8stOoebf5hd09ijoS/jjdISgn0vQ82DzbkHyI81vHc7pTXqLu1w6WereAuXcKjDoXHO7Ua66pWmG70Tz4ZT7YM7qX8XRjkHFyOhVyYCK3Rxl2yH1/UGv96L4z4uHc7XT4AVrdEK72/Px1n+sQZVOdrTf1rR/392BinjaJ3YPjSu70WI8+kpcXlG1+XQh6kH1M7FxED6BUHiXppDdDV4dhtswVRZ9n87f0dQ4urWtnecfUZr1B6nmFZ5FKT615W7OYHMQTgyY9lmHlRBU05LK3tnOd/1vHfvtGwQbHQE3vDxofD+s2ubxsj7wUcXeVT2Wzd+a1PqGCMU5PB8MF3/yr5ZuXbq/o9vOIOSHttBrcClonqJPB9Vrn2CIxkq3XEloA+AL03qW/GeLB0jRHcDuG3qNUcOey/wKISD7d3gJsVv6v1afrbvz39ZVF/q8HeRb634X+d6H/dZdnof997PpfnyZ9K93vnTR2Z91+J0eMnDv73MzyGnnV2N1u7EoQXyvfwVckQQ9pLy91FusbuZYu4qVn7yLek9WL9xZdxTBadl7H0rBgNA2pT1+BINHI7RopVyw4RPXunlw8uv3hJJesO7daG9bOasBXNIUIFUzyQ2fwqe9mq5rSqaY+GJ3J9ZjWKgaOk06KPuGb7FT/yjqur+9No+efKVGJ/Q5KTgr7BPdimmhz0oOqESPhKAV58bQ9erxCzuLJfPLG/26DND3of5X4309Xn7r+P2urC/+fh3kW8t9C/lvIf+7yLOS/xy7/hWnSt5IBiR2KmR26BSNrVRfc1C2auZMkitbfI0zylI67p/HHdq/b8dwd5ueP3zZaLbR1CPLHMFzYlq8RH/a3wuH77LzNwPtwNxOiZm23szfThADB/uujuJAAfnVPHv6/C6A8mhDnVrlsD+cWAmbw/y/wm83/r6NIsOD/H+BZ8P8L/n/B/7vLs+D/Hzv/P4UmfTMnAOl7iYdhFleby+5oLvtN9XpGctf2ZDyAjQKu \ No newline at end of file From c2fc94c7731083292992a84b6c87fc95cb980ba3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 23:15:57 +0000 Subject: [PATCH 32/40] Record PlanAnvil fragment diagnostics --- .bootstrap/diagnostic.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bootstrap/diagnostic.txt b/.bootstrap/diagnostic.txt index 545bc1d..24813eb 100644 --- a/.bootstrap/diagnostic.txt +++ b/.bootstrap/diagnostic.txt @@ -2,7 +2,7 @@ 1038a66a086d68d6e6853efdc161e8ec9230ab8326588ac22728e6aec798c372 .bootstrap/fix-01-00 969b1d29d516e6f884aaa1238f1ce1040eb79bd53c777bc48b5d5ca1ee3de776 .bootstrap/fix-01-01 4ed9ff03b6060ef19cf5487850288a1a192b08d40631a3a6f73d7d8c1990c7e4 .bootstrap/fix-01-02 -d522c6cd22cb9169ace4e2624f5c22103cea3ae236018cac76a6784bd6d4ba40 .bootstrap/fix-01-03 +c27fd9ab6b60434442326282a665ed5a28c94c247b8d93378110fd420b95db84 .bootstrap/fix-01-03 9f4b935b5dc750ab06116079971bc156fe3946de98bcfb3936b78748108485bd .bootstrap/fix-01-04 6dc8cb1408f44785a781dba5b5ed22b0b2eaf63fd8f94b148bdc15a0493cfba1 .bootstrap/fix-01-05 05e4003e4584cec8e25899e1ce20c891c7a24149181dd9bd907484213483d8eb .bootstrap/part-02 From 49407d0b0ebb35fc63fd754770ad39b0ee7fe522 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:16:44 +0200 Subject: [PATCH 33/40] Add replacement PlanAnvil fragment 09-00 --- .bootstrap/fix-09-00 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-09-00 diff --git a/.bootstrap/fix-09-00 b/.bootstrap/fix-09-00 new file mode 100644 index 0000000..22ecfc8 --- /dev/null +++ b/.bootstrap/fix-09-00 @@ -0,0 +1 @@ +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 \ No newline at end of file From 9fdb84872cb4e94780390b4b5dc48102ae015af4 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:17:09 +0200 Subject: [PATCH 34/40] Add replacement PlanAnvil fragment 09-01 --- .bootstrap/fix-09-01 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-09-01 diff --git a/.bootstrap/fix-09-01 b/.bootstrap/fix-09-01 new file mode 100644 index 0000000..11182df --- /dev/null +++ b/.bootstrap/fix-09-01 @@ -0,0 +1 @@ +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 \ No newline at end of file From 0ac3cf5ccf87c769a7d93f9e86ea060704aa9b9f Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:17:34 +0200 Subject: [PATCH 35/40] Add replacement PlanAnvil fragment 09-02 --- .bootstrap/fix-09-02 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-09-02 diff --git a/.bootstrap/fix-09-02 b/.bootstrap/fix-09-02 new file mode 100644 index 0000000..484e285 --- /dev/null +++ b/.bootstrap/fix-09-02 @@ -0,0 +1 @@ +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 \ No newline at end of file From e45b3dc7e3dd86224d018f0c0dce10aab15653f7 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:18:04 +0200 Subject: [PATCH 36/40] Add replacement PlanAnvil fragment 11-00 --- .bootstrap/fix-11-00 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-11-00 diff --git a/.bootstrap/fix-11-00 b/.bootstrap/fix-11-00 new file mode 100644 index 0000000..6e549e0 --- /dev/null +++ b/.bootstrap/fix-11-00 @@ -0,0 +1 @@ +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 \ No newline at end of file From 794406533aa83311a579434867b56ab4718fd5fb Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:18:32 +0200 Subject: [PATCH 37/40] Add replacement PlanAnvil fragment 11-01 --- .bootstrap/fix-11-01 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-11-01 diff --git a/.bootstrap/fix-11-01 b/.bootstrap/fix-11-01 new file mode 100644 index 0000000..f4b313d --- /dev/null +++ b/.bootstrap/fix-11-01 @@ -0,0 +1 @@ +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 \ No newline at end of file From cfd76c4d2de913e8de5ea0b1edfd32409d708c9a Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:18:58 +0200 Subject: [PATCH 38/40] Add replacement PlanAnvil fragment 11-02 --- .bootstrap/fix-11-02 | 1 + 1 file changed, 1 insertion(+) create mode 100644 .bootstrap/fix-11-02 diff --git a/.bootstrap/fix-11-02 b/.bootstrap/fix-11-02 new file mode 100644 index 0000000..b901db5 --- /dev/null +++ b/.bootstrap/fix-11-02 @@ -0,0 +1 @@ +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 \ No newline at end of file From 1d8ec0849d0a5c9a3c970c783bdca155a69803e1 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:19:11 +0200 Subject: [PATCH 39/40] Materialize verified PlanAnvil implementation --- .github/workflows/materialize-plananvil.yml | 36 +++++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml index 445862f..3f12df4 100644 --- a/.github/workflows/materialize-plananvil.yml +++ b/.github/workflows/materialize-plananvil.yml @@ -17,11 +17,11 @@ jobs: with: fetch-depth: 0 ref: agent/implement-plananvil-skill - - name: Diagnose archive fragments + - name: Restore implementation archive shell: bash run: | set -euo pipefail - sha256sum \ + cat \ .bootstrap/part-00 \ .bootstrap/fix-01-00 \ .bootstrap/fix-01-01 \ @@ -37,13 +37,35 @@ jobs: .bootstrap/part-06 \ .bootstrap/part-07 \ .bootstrap/part-08 \ - .bootstrap/part-09 \ + .bootstrap/fix-09-00 \ + .bootstrap/fix-09-01 \ + .bootstrap/fix-09-02 \ .bootstrap/part-10 \ - .bootstrap/part-11 \ + .bootstrap/fix-11-00 \ + .bootstrap/fix-11-01 \ + .bootstrap/fix-11-02 \ .bootstrap/part-12 \ - > .bootstrap/diagnostic.txt + > /tmp/plananvil.tar.gz.b64 + test "$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" = "d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" + base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz + test "$(sha256sum /tmp/plananvil.tar.gz | cut -d' ' -f1)" = "addffaecbf114a6a7fff2dff227b50fe66a47c14f1fb62df88113b49636e29d2" + tar -tzf /tmp/plananvil.tar.gz >/dev/null + tar -xzf /tmp/plananvil.tar.gz -C . + rm -rf .bootstrap .github/workflows/materialize-plananvil.yml + - name: Validate implementation + shell: bash + run: | + set -euo pipefail + python -m unittest discover -s .agents/skills/plan-anvil/tests -v + python -m compileall -q .agents/skills/plan-anvil .codex/hooks + find . -type d -name __pycache__ -prune -exec rm -rf {} + + git diff --check + - name: Commit materialized implementation + shell: bash + run: | + set -euo pipefail git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add .bootstrap/diagnostic.txt - git commit -m "Record PlanAnvil fragment diagnostics" + git add -A + git commit -m "Implement PlanAnvil skill" git push origin HEAD:agent/implement-plananvil-skill From cc5393b0da5d5a73316fb19f480040361382064e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 23:19:20 +0000 Subject: [PATCH 40/40] Implement PlanAnvil skill --- .agents/skills/plan-anvil/SKILL.md | 53 +++ .agents/skills/plan-anvil/agents/openai.yaml | 6 + .../references/artifact-contract.md | 38 ++ .../references/execution-contract.md | 33 ++ .../skills/plan-anvil/references/lifecycle.md | 36 ++ .../plan-anvil/references/plan-contract.md | 33 ++ .../plan-anvil/references/review-and-stop.md | 25 + .../plan-anvil/schemas/analysis.schema.json | 140 ++++++ .../plan-anvil/schemas/checkpoint.schema.json | 252 ++++++++++ .../plan-anvil/schemas/comparison.schema.json | 103 ++++ .../plan-anvil/schemas/compliance.schema.json | 163 +++++++ .../schemas/git-capability.schema.json | 115 +++++ .../schemas/instruction-map.schema.json | 182 +++++++ .../plan-anvil/schemas/lifecycle.schema.json | 74 +++ .../schemas/local-state.schema.json | 141 ++++++ .../plan-anvil/schemas/manifest.schema.json | 170 +++++++ .../plan-anvil/schemas/review.schema.json | 127 +++++ .../plan-anvil/schemas/risk.schema.json | 166 +++++++ .../plan-anvil/schemas/state.schema.json | 152 ++++++ .../schemas/traceability.schema.json | 230 +++++++++ .../skills/plan-anvil/scripts/commit_plan.py | 189 ++++++++ .agents/skills/plan-anvil/scripts/common.py | 431 +++++++++++++++++ .../plan-anvil/scripts/compare_review.py | 106 +++++ .../scripts/create_planning_worktree.py | 140 ++++++ .../plan-anvil/scripts/map_instructions.py | 267 +++++++++++ .../skills/plan-anvil/scripts/plan_anvil.py | 150 ++++++ .../skills/plan-anvil/scripts/preflight.py | 112 +++++ .../scripts/prepare_review_bundle.py | 127 +++++ .../plan-anvil/scripts/profile_repository.py | 283 +++++++++++ .../plan-anvil/scripts/record_analysis.py | 198 ++++++++ .../plan-anvil/scripts/record_blind_review.py | 151 ++++++ .../skills/plan-anvil/scripts/scaffold_run.py | 385 +++++++++++++++ .../plan-anvil/scripts/schema_validator.py | 152 ++++++ .../plan-anvil/scripts/seal_artifacts.py | 62 +++ .../scripts/test_git_capabilities.py | 220 +++++++++ .../plan-anvil/scripts/transition_state.py | 116 +++++ .../skills/plan-anvil/scripts/validate_all.py | 88 ++++ .../plan-anvil/scripts/validate_artifacts.py | 221 +++++++++ .../plan-anvil/scripts/validate_diff.py | 126 +++++ .../plan-anvil/scripts/validate_plan.py | 445 ++++++++++++++++++ .../plan-anvil/scripts/validate_profile.py | 95 ++++ .agents/skills/plan-anvil/templates/PLAN.md | 88 ++++ .agents/skills/plan-anvil/templates/STAGE.md | 62 +++ .../templates/SYSTEM_PROFILE.local.md | 19 + .../plan-anvil/templates/SYSTEM_PROFILE.md | 38 ++ .../skills/plan-anvil/templates/analysis.md | 29 ++ .../plan-anvil/templates/blind-review.md | 29 ++ .../plan-anvil/templates/final-report.md | 19 + .agents/skills/plan-anvil/tests/_helpers.py | 391 +++++++++++++++ .../test_analysis_and_review_integrity.py | 119 +++++ .../tests/test_boundary_and_privacy.py | 42 ++ .../tests/test_common_and_schema.py | 89 ++++ .../tests/test_hooks_and_edge_states.py | 182 +++++++ ...test_instruction_conflicts_and_examples.py | 77 +++ .../tests/test_preflight_and_git.py | 101 ++++ .../test_profiles_instructions_scaffold.py | 59 +++ .../tests/test_validation_review_commit.py | 121 +++++ .bootstrap/diagnostic.txt | 19 - .bootstrap/fix-01-00 | 1 - .bootstrap/fix-01-01 | 1 - .bootstrap/fix-01-02 | 1 - .bootstrap/fix-01-03 | 1 - .bootstrap/fix-01-04 | 1 - .bootstrap/fix-01-05 | 1 - .bootstrap/fix-04-00 | 1 - .bootstrap/fix-04-01 | 1 - .bootstrap/fix-09-00 | 1 - .bootstrap/fix-09-01 | 1 - .bootstrap/fix-09-02 | 1 - .bootstrap/fix-11-00 | 1 - .bootstrap/fix-11-01 | 1 - .bootstrap/fix-11-02 | 1 - .bootstrap/part-00 | 1 - .bootstrap/part-01 | 1 - .bootstrap/part-02 | 1 - .bootstrap/part-03 | 1 - .bootstrap/part-04 | 1 - .bootstrap/part-05 | 1 - .bootstrap/part-06 | 1 - .bootstrap/part-07 | 1 - .bootstrap/part-08 | 1 - .bootstrap/part-09 | 1 - .bootstrap/part-10 | 1 - .bootstrap/part-11 | 1 - .bootstrap/part-12 | 1 - .codex/agents/plan-anvil-profiler.toml | 6 + .codex/agents/plan-anvil-reviewer.toml | 6 + .codex/config.toml | 3 + .codex/hooks.json | 74 +++ .codex/hooks/plan-anvil-agent-context.py | 27 ++ .codex/hooks/plan-anvil-compaction.py | 38 ++ .codex/hooks/plan-anvil-guard.py | 134 ++++++ .codex/hooks/plan-anvil-recovery.py | 24 + .codex/hooks/plan_anvil_hooklib.py | 153 ++++++ .gitattributes | 1 + .github/workflows/materialize-plananvil.yml | 71 --- .gitignore | 8 + AGENTS.md | 31 ++ CHANGELOG.md | 25 + README.md | 91 ++-- capabilities/C01/README.md | 8 + capabilities/C02/README.md | 8 + capabilities/C03/README.md | 8 + capabilities/C04/README.md | 8 + capabilities/C05/README.md | 8 + capabilities/C06/README.md | 8 + capabilities/C07/README.md | 8 + capabilities/C08/README.md | 8 + capabilities/C09/README.md | 8 + capabilities/C10/README.md | 8 + capabilities/C11/README.md | 8 + capabilities/C12/README.md | 8 + capabilities/C13/README.md | 8 + capabilities/C14/README.md | 8 + capabilities/C15/README.md | 8 + capabilities/C16/README.md | 8 + capabilities/README.md | 22 + capabilities/index.json | 135 ++++++ examples/README.md | 10 + examples/blocked-plan/expected.json | 10 + examples/blocked-plan/fixture.md | 3 + examples/blocked-plan/request.md | 3 + examples/blocked-plan/run/PARTIAL_PLAN.md | 3 + examples/blocked-plan/run/SYSTEM_PROFILE.md | 38 ++ examples/blocked-plan/run/compliance.json | 55 +++ .../blocked-plan/run/evidence/analysis.json | 22 + .../blocked-plan/run/evidence/analysis.md | 3 + .../run/evidence/git-capability.json | 59 +++ .../blocked-plan/run/evidence/lifecycle.json | 38 ++ .../run/evidence/original-goal.md | 3 + examples/blocked-plan/run/manifest.json | 27 ++ examples/blocked-plan/run/state.json | 18 + examples/blocked-plan/run/traceability.json | 7 + examples/blocked-plan/sanitization.json | 6 + examples/git-write-restricted/expected.json | 7 + examples/git-write-restricted/fixture.md | 3 + .../git-write-restricted/git-capability.json | 8 + examples/git-write-restricted/preflight.json | 5 + examples/git-write-restricted/request.md | 3 + .../git-write-restricted/sanitization.json | 6 + examples/small-change/expected.json | 8 + examples/small-change/fixture.md | 3 + examples/small-change/request.md | 3 + examples/small-change/run/PLAN.md | 88 ++++ examples/small-change/run/SYSTEM_PROFILE.md | 38 ++ examples/small-change/run/compliance.json | 58 +++ .../small-change/run/evidence/analysis.json | 25 + .../small-change/run/evidence/analysis.md | 29 ++ .../run/evidence/git-capability.json | 59 +++ .../run/evidence/instruction-map.json | 27 ++ .../small-change/run/evidence/lifecycle.json | 38 ++ .../run/evidence/original-goal.md | 3 + examples/small-change/run/manifest.json | 27 ++ .../run/reports/plan-review/blind-review.json | 13 + .../run/reports/plan-review/blind-review.md | 9 + .../run/reports/plan-review/comparison.json | 9 + .../run/reports/validation/summary.json | 14 + .../small-change/run/risks/RISK-01-01.json | 25 + examples/small-change/run/stages/STAGE-01.md | 62 +++ examples/small-change/run/state.json | 16 + examples/small-change/run/traceability.json | 38 ++ examples/small-change/sanitization.json | 6 + examples/stateful-change/expected.json | 12 + examples/stateful-change/fixture.md | 3 + examples/stateful-change/request.md | 3 + examples/stateful-change/run/PLAN.md | 92 ++++ .../stateful-change/run/SYSTEM_PROFILE.md | 38 ++ examples/stateful-change/run/compliance.json | 58 +++ .../run/evidence/analysis.json | 32 ++ .../stateful-change/run/evidence/analysis.md | 29 ++ .../run/evidence/git-capability.json | 59 +++ .../run/evidence/instruction-map.json | 41 ++ .../run/evidence/lifecycle.json | 38 ++ .../run/evidence/original-goal.md | 3 + examples/stateful-change/run/manifest.json | 27 ++ .../run/reports/plan-review/blind-review.json | 13 + .../run/reports/plan-review/blind-review.md | 9 + .../run/reports/plan-review/comparison.json | 9 + .../run/reports/validation/summary.json | 14 + .../stateful-change/run/risks/RISK-01-01.json | 26 + .../stateful-change/run/risks/RISK-02-01.json | 26 + .../stateful-change/run/risks/RISK-03-01.json | 26 + .../stateful-change/run/risks/RISK-04-01.json | 26 + .../stateful-change/run/risks/RISK-05-01.json | 26 + .../stateful-change/run/stages/STAGE-01.md | 62 +++ .../stateful-change/run/stages/STAGE-02.md | 62 +++ .../stateful-change/run/stages/STAGE-03.md | 62 +++ .../stateful-change/run/stages/STAGE-04.md | 62 +++ .../stateful-change/run/stages/STAGE-05.md | 62 +++ examples/stateful-change/run/state.json | 16 + .../stateful-change/run/traceability.json | 150 ++++++ examples/stateful-change/sanitization.json | 6 + 192 files changed, 10673 insertions(+), 145 deletions(-) create mode 100644 .agents/skills/plan-anvil/SKILL.md create mode 100644 .agents/skills/plan-anvil/agents/openai.yaml create mode 100644 .agents/skills/plan-anvil/references/artifact-contract.md create mode 100644 .agents/skills/plan-anvil/references/execution-contract.md create mode 100644 .agents/skills/plan-anvil/references/lifecycle.md create mode 100644 .agents/skills/plan-anvil/references/plan-contract.md create mode 100644 .agents/skills/plan-anvil/references/review-and-stop.md create mode 100644 .agents/skills/plan-anvil/schemas/analysis.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/checkpoint.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/comparison.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/compliance.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/git-capability.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/instruction-map.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/lifecycle.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/local-state.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/manifest.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/review.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/risk.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/state.schema.json create mode 100644 .agents/skills/plan-anvil/schemas/traceability.schema.json create mode 100644 .agents/skills/plan-anvil/scripts/commit_plan.py create mode 100644 .agents/skills/plan-anvil/scripts/common.py create mode 100644 .agents/skills/plan-anvil/scripts/compare_review.py create mode 100644 .agents/skills/plan-anvil/scripts/create_planning_worktree.py create mode 100644 .agents/skills/plan-anvil/scripts/map_instructions.py create mode 100644 .agents/skills/plan-anvil/scripts/plan_anvil.py create mode 100644 .agents/skills/plan-anvil/scripts/preflight.py create mode 100644 .agents/skills/plan-anvil/scripts/prepare_review_bundle.py create mode 100644 .agents/skills/plan-anvil/scripts/profile_repository.py create mode 100644 .agents/skills/plan-anvil/scripts/record_analysis.py create mode 100644 .agents/skills/plan-anvil/scripts/record_blind_review.py create mode 100644 .agents/skills/plan-anvil/scripts/scaffold_run.py create mode 100644 .agents/skills/plan-anvil/scripts/schema_validator.py create mode 100644 .agents/skills/plan-anvil/scripts/seal_artifacts.py create mode 100644 .agents/skills/plan-anvil/scripts/test_git_capabilities.py create mode 100644 .agents/skills/plan-anvil/scripts/transition_state.py create mode 100644 .agents/skills/plan-anvil/scripts/validate_all.py create mode 100644 .agents/skills/plan-anvil/scripts/validate_artifacts.py create mode 100644 .agents/skills/plan-anvil/scripts/validate_diff.py create mode 100644 .agents/skills/plan-anvil/scripts/validate_plan.py create mode 100644 .agents/skills/plan-anvil/scripts/validate_profile.py create mode 100644 .agents/skills/plan-anvil/templates/PLAN.md create mode 100644 .agents/skills/plan-anvil/templates/STAGE.md create mode 100644 .agents/skills/plan-anvil/templates/SYSTEM_PROFILE.local.md create mode 100644 .agents/skills/plan-anvil/templates/SYSTEM_PROFILE.md create mode 100644 .agents/skills/plan-anvil/templates/analysis.md create mode 100644 .agents/skills/plan-anvil/templates/blind-review.md create mode 100644 .agents/skills/plan-anvil/templates/final-report.md create mode 100644 .agents/skills/plan-anvil/tests/_helpers.py create mode 100644 .agents/skills/plan-anvil/tests/test_analysis_and_review_integrity.py create mode 100644 .agents/skills/plan-anvil/tests/test_boundary_and_privacy.py create mode 100644 .agents/skills/plan-anvil/tests/test_common_and_schema.py create mode 100644 .agents/skills/plan-anvil/tests/test_hooks_and_edge_states.py create mode 100644 .agents/skills/plan-anvil/tests/test_instruction_conflicts_and_examples.py create mode 100644 .agents/skills/plan-anvil/tests/test_preflight_and_git.py create mode 100644 .agents/skills/plan-anvil/tests/test_profiles_instructions_scaffold.py create mode 100644 .agents/skills/plan-anvil/tests/test_validation_review_commit.py delete mode 100644 .bootstrap/diagnostic.txt delete mode 100644 .bootstrap/fix-01-00 delete mode 100644 .bootstrap/fix-01-01 delete mode 100644 .bootstrap/fix-01-02 delete mode 100644 .bootstrap/fix-01-03 delete mode 100644 .bootstrap/fix-01-04 delete mode 100644 .bootstrap/fix-01-05 delete mode 100644 .bootstrap/fix-04-00 delete mode 100644 .bootstrap/fix-04-01 delete mode 100644 .bootstrap/fix-09-00 delete mode 100644 .bootstrap/fix-09-01 delete mode 100644 .bootstrap/fix-09-02 delete mode 100644 .bootstrap/fix-11-00 delete mode 100644 .bootstrap/fix-11-01 delete mode 100644 .bootstrap/fix-11-02 delete mode 100644 .bootstrap/part-00 delete mode 100644 .bootstrap/part-01 delete mode 100644 .bootstrap/part-02 delete mode 100644 .bootstrap/part-03 delete mode 100644 .bootstrap/part-04 delete mode 100644 .bootstrap/part-05 delete mode 100644 .bootstrap/part-06 delete mode 100644 .bootstrap/part-07 delete mode 100644 .bootstrap/part-08 delete mode 100644 .bootstrap/part-09 delete mode 100644 .bootstrap/part-10 delete mode 100644 .bootstrap/part-11 delete mode 100644 .bootstrap/part-12 create mode 100644 .codex/agents/plan-anvil-profiler.toml create mode 100644 .codex/agents/plan-anvil-reviewer.toml create mode 100644 .codex/config.toml create mode 100644 .codex/hooks.json create mode 100644 .codex/hooks/plan-anvil-agent-context.py create mode 100644 .codex/hooks/plan-anvil-compaction.py create mode 100644 .codex/hooks/plan-anvil-guard.py create mode 100644 .codex/hooks/plan-anvil-recovery.py create mode 100644 .codex/hooks/plan_anvil_hooklib.py create mode 100644 .gitattributes delete mode 100644 .github/workflows/materialize-plananvil.yml create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 CHANGELOG.md create mode 100644 capabilities/C01/README.md create mode 100644 capabilities/C02/README.md create mode 100644 capabilities/C03/README.md create mode 100644 capabilities/C04/README.md create mode 100644 capabilities/C05/README.md create mode 100644 capabilities/C06/README.md create mode 100644 capabilities/C07/README.md create mode 100644 capabilities/C08/README.md create mode 100644 capabilities/C09/README.md create mode 100644 capabilities/C10/README.md create mode 100644 capabilities/C11/README.md create mode 100644 capabilities/C12/README.md create mode 100644 capabilities/C13/README.md create mode 100644 capabilities/C14/README.md create mode 100644 capabilities/C15/README.md create mode 100644 capabilities/C16/README.md create mode 100644 capabilities/README.md create mode 100644 capabilities/index.json create mode 100644 examples/README.md create mode 100644 examples/blocked-plan/expected.json create mode 100644 examples/blocked-plan/fixture.md create mode 100644 examples/blocked-plan/request.md create mode 100644 examples/blocked-plan/run/PARTIAL_PLAN.md create mode 100644 examples/blocked-plan/run/SYSTEM_PROFILE.md create mode 100644 examples/blocked-plan/run/compliance.json create mode 100644 examples/blocked-plan/run/evidence/analysis.json create mode 100644 examples/blocked-plan/run/evidence/analysis.md create mode 100644 examples/blocked-plan/run/evidence/git-capability.json create mode 100644 examples/blocked-plan/run/evidence/lifecycle.json create mode 100644 examples/blocked-plan/run/evidence/original-goal.md create mode 100644 examples/blocked-plan/run/manifest.json create mode 100644 examples/blocked-plan/run/state.json create mode 100644 examples/blocked-plan/run/traceability.json create mode 100644 examples/blocked-plan/sanitization.json create mode 100644 examples/git-write-restricted/expected.json create mode 100644 examples/git-write-restricted/fixture.md create mode 100644 examples/git-write-restricted/git-capability.json create mode 100644 examples/git-write-restricted/preflight.json create mode 100644 examples/git-write-restricted/request.md create mode 100644 examples/git-write-restricted/sanitization.json create mode 100644 examples/small-change/expected.json create mode 100644 examples/small-change/fixture.md create mode 100644 examples/small-change/request.md create mode 100644 examples/small-change/run/PLAN.md create mode 100644 examples/small-change/run/SYSTEM_PROFILE.md create mode 100644 examples/small-change/run/compliance.json create mode 100644 examples/small-change/run/evidence/analysis.json create mode 100644 examples/small-change/run/evidence/analysis.md create mode 100644 examples/small-change/run/evidence/git-capability.json create mode 100644 examples/small-change/run/evidence/instruction-map.json create mode 100644 examples/small-change/run/evidence/lifecycle.json create mode 100644 examples/small-change/run/evidence/original-goal.md create mode 100644 examples/small-change/run/manifest.json create mode 100644 examples/small-change/run/reports/plan-review/blind-review.json create mode 100644 examples/small-change/run/reports/plan-review/blind-review.md create mode 100644 examples/small-change/run/reports/plan-review/comparison.json create mode 100644 examples/small-change/run/reports/validation/summary.json create mode 100644 examples/small-change/run/risks/RISK-01-01.json create mode 100644 examples/small-change/run/stages/STAGE-01.md create mode 100644 examples/small-change/run/state.json create mode 100644 examples/small-change/run/traceability.json create mode 100644 examples/small-change/sanitization.json create mode 100644 examples/stateful-change/expected.json create mode 100644 examples/stateful-change/fixture.md create mode 100644 examples/stateful-change/request.md create mode 100644 examples/stateful-change/run/PLAN.md create mode 100644 examples/stateful-change/run/SYSTEM_PROFILE.md create mode 100644 examples/stateful-change/run/compliance.json create mode 100644 examples/stateful-change/run/evidence/analysis.json create mode 100644 examples/stateful-change/run/evidence/analysis.md create mode 100644 examples/stateful-change/run/evidence/git-capability.json create mode 100644 examples/stateful-change/run/evidence/instruction-map.json create mode 100644 examples/stateful-change/run/evidence/lifecycle.json create mode 100644 examples/stateful-change/run/evidence/original-goal.md create mode 100644 examples/stateful-change/run/manifest.json create mode 100644 examples/stateful-change/run/reports/plan-review/blind-review.json create mode 100644 examples/stateful-change/run/reports/plan-review/blind-review.md create mode 100644 examples/stateful-change/run/reports/plan-review/comparison.json create mode 100644 examples/stateful-change/run/reports/validation/summary.json create mode 100644 examples/stateful-change/run/risks/RISK-01-01.json create mode 100644 examples/stateful-change/run/risks/RISK-02-01.json create mode 100644 examples/stateful-change/run/risks/RISK-03-01.json create mode 100644 examples/stateful-change/run/risks/RISK-04-01.json create mode 100644 examples/stateful-change/run/risks/RISK-05-01.json create mode 100644 examples/stateful-change/run/stages/STAGE-01.md create mode 100644 examples/stateful-change/run/stages/STAGE-02.md create mode 100644 examples/stateful-change/run/stages/STAGE-03.md create mode 100644 examples/stateful-change/run/stages/STAGE-04.md create mode 100644 examples/stateful-change/run/stages/STAGE-05.md create mode 100644 examples/stateful-change/run/state.json create mode 100644 examples/stateful-change/run/traceability.json create mode 100644 examples/stateful-change/sanitization.json diff --git a/.agents/skills/plan-anvil/SKILL.md b/.agents/skills/plan-anvil/SKILL.md new file mode 100644 index 0000000..8cd57d3 --- /dev/null +++ b/.agents/skills/plan-anvil/SKILL.md @@ -0,0 +1,53 @@ +--- +name: plan-anvil +description: Generate and validate a rigorous, test-driven implementation plan in an isolated Git worktree. Use only when explicitly invoked as $plan-anvil. Never implement or execute the generated plan. +--- + +# PlanAnvil + +Create an auditable implementation contract, commit planning artifacts only, report the result, and stop. + +## Boundary + +- Never modify product code or product tests. +- Never execute a generated stage or start the later executor. +- Never stash, reset, clean, deploy, migrate, restart services, switch a live system, or push or merge the base branch. +- Keep the source worktree unchanged. Treat canonical files and Git as durable state, not conversation memory. +- Do not continue into implementation after approval in the same run. + +## Workflow + +1. Read every applicable repository instruction and `references/lifecycle.md`. Current official Codex documentation has higher authority than bundled references. +2. Start the deterministic bootstrap controller: + + ```text + python .agents/skills/plan-anvil/scripts/plan_anvil.py start \ + --source "$PWD" \ + --goal "" \ + --codex-version "" \ + --model "" \ + --permission-mode "" \ + --project-trust \ + --hook-mode + ``` + + This performs read-only preflight, a real reversible Git ref/branch/worktree/index/commit probe, planning-worktree isolation, profiling, run scaffolding, and durable bootstrap evidence. On any non-ready result, preserve evidence, report the exact blocker, and stop. +3. Continue only in the returned planning worktree and run root. Fully read and hash all applicable instruction files, resolve their scope and precedence, and write the instruction map with `map_instructions.py`. A remaining critical conflict blocks the run. +4. Analyze the goal from repository evidence. Record immutable `evidence/analysis.md` and `.json` with `record_analysis.py`. A critical unknown blocks readiness; non-critical ambiguity requires an evidence-backed interpretation and verification method. +5. Using the templates and references, author `PLAN.md`, stable stage briefs, acceptance criteria, risks, controls, rollback, recovery, approvals, and complete traceability. Write requirements for a separate later execution run, not executable product changes. Seal the contract with `seal_artifacts.py`. +6. Run `validate_all.py --phase pre-review`. Do not proceed unless profiles, schemas, privacy, source immutability, instruction coverage, plan structure, traceability, risks, and the planning-branch diff all pass. +7. Build the immutable review bundle with `prepare_review_bundle.py`. Dispatch a fresh read-only reviewer without planner reasoning, record its single blind result with `record_blind_review.py`, then run `compare_review.py`. Any failed or stale review blocks readiness. +8. Run `commit_plan.py`. It repeats the final gates, writes the final report, commits only allowlisted planning/control artifacts, preserves the source worktree, and never pushes. +9. Report status, planning branch, commit SHA, plan path, assumptions, unknowns, review result, and the separate execution-run prompt. State: `No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md.` Then stop. + +## Decision policy + +Ask the user only when the unresolved decision materially changes business scope, public behavior, architecture, irreversible behavior, security/privacy/legal policy, live switching, base integration, or critical acceptance and rollback evidence. Derive and record all other implementation-planning decisions from the strongest available evidence. + +## References + +- `references/lifecycle.md` — state order, Git isolation, ownership, and blockers +- `references/plan-contract.md` — required plan and stage content +- `references/artifact-contract.md` — canonical state, schemas, privacy, and path safety +- `references/review-and-stop.md` — validation, blind review, commit, and hard stop +- `references/execution-contract.md` — contract for the separate later implementation run diff --git a/.agents/skills/plan-anvil/agents/openai.yaml b/.agents/skills/plan-anvil/agents/openai.yaml new file mode 100644 index 0000000..abe1fb6 --- /dev/null +++ b/.agents/skills/plan-anvil/agents/openai.yaml @@ -0,0 +1,6 @@ +interface: + display_name: "PlanAnvil" + short_description: "Generate a validated implementation plan without executing it" + default_prompt: "Use $plan-anvil to generate and validate an implementation plan for this goal. Do not implement the plan." +policy: + allow_implicit_invocation: false diff --git a/.agents/skills/plan-anvil/references/artifact-contract.md b/.agents/skills/plan-anvil/references/artifact-contract.md new file mode 100644 index 0000000..4be5711 --- /dev/null +++ b/.agents/skills/plan-anvil/references/artifact-contract.md @@ -0,0 +1,38 @@ +# Artifact contract + +## Run layout + +`.pursue/runs/__/` contains `PLAN.md`, `manifest.json`, `state.json`, `compliance.json`, `traceability.json`, ignored `local-state.json`, and the `stages`, `checkpoints`, `reports`, `risks`, `evidence`, `diffs`, `logs`, `incidents`, and `final` directories. + +Canonical machine state is JSON. Markdown is human-readable and never overrides JSON. Bootstrap evidence includes `evidence/git-capability.json` and `evidence/lifecycle.json`; goal analysis uses immutable `evidence/analysis.md` and `.json`. + +## Canonical conventions + +- UTF-8, LF, sorted keys, two-space indentation, terminal newline +- schema version `1.1.0` +- RFC 3339 UTC timestamps +- SHA-256 values prefixed with `sha256:` +- unknown fields rejected unless explicitly allowed +- atomic replacement for mutable state +- monotonic `state.json.revision` +- exactly one `next_action` +- immutable checkpoints and blind-review artifacts + +## Privacy + +Committed artifacts must not contain absolute local paths, usernames, machine-specific services, credentials, private keys, cookies, copied `.env` data, or private repository URLs. + +Machine-specific locators belong only in ignored: + +- `.pursue/SYSTEM_PROFILE.local.md` +- `.pursue/runs//local-state.json` + +Validators must prove these files are ignored and untracked. + +## Path safety + +Resolve every write, reject traversal, symlink escapes, `.git` writes outside dedicated Git commands, case-insensitive escapes, and submodule writes not explicitly in scope. Match allowlists using repository-relative POSIX paths. + +## Goal analysis + +`evidence/analysis.md` and `evidence/analysis.json` are immutable analysis inputs. The JSON records the goal hash, classification, risk, affected paths, evidence, assumptions, unknowns, and Markdown hash. A critical unknown transitions the run to `BLOCKED_BY_CRITICAL_UNKNOWN`. diff --git a/.agents/skills/plan-anvil/references/execution-contract.md b/.agents/skills/plan-anvil/references/execution-contract.md new file mode 100644 index 0000000..0fac043 --- /dev/null +++ b/.agents/skills/plan-anvil/references/execution-contract.md @@ -0,0 +1,33 @@ +# Separate execution-run contract + +These rules are written into the generated plan; they are never started by PlanAnvil. + +## Roles and topology + +The later executor uses a flat direct-child topology: Jim coordinates, Jenny owns approved tests only, one implementation agent modifies approved product paths, an independent verifier remains read-only, and Winston Wolfe performs read-only incident analysis only after six exhausted implementation attempts. + +Jim never modifies product code or tests. Jenny never modifies production code. Only one agent modifies repository files at a time. + +## Evidence cycle + +Behavior-changing stages use: + +`GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION` + +The red result must fail for the intended behavioral reason. Non-behavior stages use an equivalent evidence cycle. + +## Retry model + +Use three attempts for one strategy, then three attempts for a materially different strategy. Preserve failed-attempt evidence. After six failures, run read-only incident analysis and stop with `BLOCKED_BY_UNRESOLVED_FAILURE`. + +## Git and control ownership + +Task branch: `pursue//`. Integration branch: `pursue/integration//`. + +Control state, reports, checkpoints, and evidence stay in the retained planning worktree. Product code and tests change only in task or integration worktrees. Each completed stage ends in one coherent implementation-and-test commit. + +Never automatically push or merge the base branch. Require explicit approval before live switching, irreversible operations, or base integration. + +## Stateful changes + +Use discover, recovery point, expand, migrate, switch, observe, and a separate later contraction. Require resumability, integrity checks, compatibility, rollback evidence, and explicit approval for irreversible steps. diff --git a/.agents/skills/plan-anvil/references/lifecycle.md b/.agents/skills/plan-anvil/references/lifecycle.md new file mode 100644 index 0000000..fa9375c --- /dev/null +++ b/.agents/skills/plan-anvil/references/lifecycle.md @@ -0,0 +1,36 @@ +# Generator lifecycle + +Authority order: current official OpenAI Codex documentation, `docs/IMPLEMENTATION_SPEC.md`, architecture, artifact schemas, compliance record, capability baseline, examples. + +## Mandatory state order + +`SOURCE_PREFLIGHT → GIT_CAPABILITY_CHECK → CREATE_PLANNING_BRANCH_AND_WORKTREE → CREATE_OR_VALIDATE_PROFILES → DISCOVER_INSTRUCTIONS → ANALYZE_GOAL → GENERATE_ARTIFACTS → DETERMINISTIC_VALIDATION → BLIND_PLAN_REVIEW → COMPARISON_AND_FINAL_VALIDATION → COMMIT_PLANNING_ARTIFACTS → REPORT_AND_STOP` + +No state may be skipped. Bootstrap transitions are preserved in `evidence/lifecycle.json`; the complete successful Git probe is preserved in `evidence/git-capability.json`. Both are schema-validated and hashed into canonical state before instruction mapping. + +## Source preflight + +The source worktree is read-only. Verify Git, repository root, `HEAD`, cleanliness, conflicts, active Git operations, branch/base identity, and linked worktrees. Preflight must not create files, refs, branches, commits, or repository-local temporary directories. + +## Git capability probe + +Use an external temporary directory and unique probe names. Verify temporary refs, a branch, linked worktree, file creation, index update, a real commit under current identity/signing/hooks policy, cleanup, and unchanged source branch, `HEAD`, index, and files. + +A commit check is mandatory for `GIT_READY`. Return a precise blocker for identity, signing, hooks, permissions, worktree support, dirty state, active operations, or ambiguous detached `HEAD`. + +## Planning isolation + +Create `pursue/plan//` from the verified base and retain an external linked planning worktree. The source remains unchanged. All profiles and run artifacts are created only after this worktree exists. + +The planning worktree is the durable control root. It may contain only `.pursue/SYSTEM_PROFILE.md`, required ignore rules, generated plan/control/evidence artifacts, and plan-specific documentation. Product implementation and product tests are forbidden. + +## Blocking statuses + +- `BLOCKED_BY_GIT_STATE` +- `BLOCKED_BY_GIT_PERMISSIONS` +- `BLOCKED_BY_RUNTIME_PREREQUISITE` +- `BLOCKED_BY_INSTRUCTION_CONFLICT` +- `BLOCKED_BY_CRITICAL_UNKNOWN` +- `PLAN_VALIDATION_FAILED` + +Preserve evidence and describe safe remediation. Never hide failures with destructive Git commands. diff --git a/.agents/skills/plan-anvil/references/plan-contract.md b/.agents/skills/plan-anvil/references/plan-contract.md new file mode 100644 index 0000000..61d13a4 --- /dev/null +++ b/.agents/skills/plan-anvil/references/plan-contract.md @@ -0,0 +1,33 @@ +# Plan and stage contract + +`PLAN.md` records stable decisions and guardrails. Stage briefs contain execution detail. Plans describe what must be true, not speculative full implementations. + +## PLAN.md required content + +- identity and contract versions; +- original goal, outcome, and definition of done; +- generator stop boundary; +- separate execution-run prompt; +- scope and exclusions; +- assumptions, unknowns, confidence, and evidence; +- applicable instructions and conflict resolutions; +- system, component, data, and state-flow summaries; +- dependencies and change classification; +- stable stage index; +- requirement → stage → criterion → risk → control/test → evidence traceability; +- testing, Git, integration, production verification, rollback, recovery, resume, and approval rules; +- status, exactly one next action, and final report requirements. + +Reject unsupported signatures, stale permanent line numbers, unverified deployment commands, placeholders, or instructions that continue implementation in the generator run. + +## Stage rules + +Each stage has a permanent ID such as `STAGE-03` or `STAGE-03A`, one outcome, scope, exclusions, affected paths or discovery procedure, `applicable_instructions` path/hash metadata, dependencies, conflicts, acceptance criteria, risks, controls, one modifier role at a time, independent verification, one coherent implementation commit, and one verified control checkpoint. + +Split stages across independent domains, unrelated responsibilities, distinct risks, criteria, deployments, or rollback boundaries. + +## Critical unknowns + +Block readiness when expected behavior, critical evidence, public API behavior, migration behavior, rollback, irreversible actions, security/permissions, or production switching cannot be safely defined. + +Every critical requirement must reach verifiable evidence. Any critical traceability gap blocks `PLAN_READY`. diff --git a/.agents/skills/plan-anvil/references/review-and-stop.md b/.agents/skills/plan-anvil/references/review-and-stop.md new file mode 100644 index 0000000..f224dc4 --- /dev/null +++ b/.agents/skills/plan-anvil/references/review-and-stop.md @@ -0,0 +1,25 @@ +# Validation, blind review, commit, and stop + +## Deterministic validation + +Before readiness, verify required files and schemas, canonical JSON, source-worktree immutability, planning-branch allowlist, ignored local state, instruction completeness, stable IDs, traceability, risk-control coverage, privacy, absence of placeholders, and agreement between JSON and Markdown. + +## Blind review + +Build a bundle containing only the original goal, bootstrap Git/lifecycle evidence, profiles, instruction map, immutable goal analysis, generated plan and stages, traceability, risks, and deterministic validator output. + +Use a fresh read-only reviewer. Do not provide planner reasoning or self-review. The reviewer must assess completeness, contradictions, unsupported assumptions, rollback, testing, approvals, generator/executor separation, and critical traceability gaps. + +Write `reports/plan-review/blind-review.md` and `.json` once. Hash both before comparison. Comparison writes separate output and never edits the blind review. + +## Commit gate + +Before commit, rerun profile, artifact, plan, diff, privacy, review, and comparison validation. Stage only allowlisted planning artifacts. Honor repository signing and hooks. Do not push unless separately requested and confirmed safe. + +## Final report and hard stop + +Report status, planning branch, commit SHA, plan path, assumptions, unknowns, review result, and the execution prompt. + +Use the explicit statement: `No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md.` + +Then stop. diff --git a/.agents/skills/plan-anvil/schemas/analysis.schema.json b/.agents/skills/plan-anvil/schemas/analysis.schema.json new file mode 100644 index 0000000..c37b3e2 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/analysis.schema.json @@ -0,0 +1,140 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/analysis.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "affected_paths": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "assumptions": { + "items": { + "additionalProperties": false, + "properties": { + "confidence": { + "enum": [ + "VERIFIED", + "USER_CONFIRMED", + "INFERRED" + ] + }, + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array", + "uniqueItems": true + }, + "text": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text", + "confidence", + "evidence" + ], + "type": "object" + }, + "type": "array" + }, + "classification": { + "enum": [ + "ISOLATED", + "CROSS_COMPONENT", + "STATEFUL", + "PUBLIC_API", + "SECURITY", + "LIVE_OPERATION", + "DOCUMENTATION" + ] + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array", + "uniqueItems": true + }, + "goal_hash": { + "$ref": "#/$defs/hash" + }, + "markdown_hash": { + "$ref": "#/$defs/hash" + }, + "risk": { + "enum": [ + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "schema_version": { + "const": "1.1.0" + }, + "unknowns": { + "items": { + "additionalProperties": false, + "properties": { + "critical": { + "type": "boolean" + }, + "text": { + "minLength": 1, + "type": "string" + }, + "verification": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text", + "critical", + "verification" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "schema_version", + "created_at", + "goal_hash", + "markdown_hash", + "classification", + "risk", + "affected_paths", + "evidence", + "assumptions", + "unknowns" + ], + "title": "PlanAnvil goal analysis", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/checkpoint.schema.json b/.agents/skills/plan-anvil/schemas/checkpoint.schema.json new file mode 100644 index 0000000..138d256 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/checkpoint.schema.json @@ -0,0 +1,252 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/checkpoint.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "agent_tree": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array" + }, + "status": { + "enum": [ + "COMPLIANT", + "NON_COMPLIANT", + "UNKNOWN" + ] + } + }, + "required": [ + "status", + "evidence" + ], + "type": "object" + }, + "artifact_hashes": { + "additionalProperties": { + "$ref": "#/$defs/hash" + }, + "type": "object" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "git": { + "additionalProperties": false, + "properties": { + "branch": { + "minLength": 1, + "type": "string" + }, + "head": { + "$ref": "#/$defs/sha" + }, + "status": { + "enum": [ + "CLEAN", + "DIRTY", + "UNKNOWN" + ] + }, + "worktree_role": { + "enum": [ + "SOURCE", + "PLANNING", + "TASK", + "INTEGRATION" + ] + } + }, + "required": [ + "branch", + "head", + "worktree_role", + "status" + ], + "type": "object" + }, + "id": { + "pattern": "^CHECKPOINT-[0-9]{2}[A-Z]?-[A-Z0-9_-]+$", + "type": "string" + }, + "mode": { + "enum": [ + "PLAN_GENERATION", + "PLAN_EXECUTION" + ] + }, + "next_action": { + "$ref": "#/$defs/next_action" + }, + "phase": { + "minLength": 1, + "type": "string" + }, + "recovery": { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "result": { + "enum": [ + "PASS", + "FAIL", + "BLOCKED" + ] + }, + "risks": { + "additionalProperties": false, + "properties": { + "closed": { + "items": { + "pattern": "^RISK-", + "type": "string" + }, + "type": "array" + }, + "open": { + "items": { + "pattern": "^RISK-", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "open", + "closed" + ], + "type": "object" + }, + "schema_version": { + "const": "1.1.0" + }, + "stage": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": [ + "string", + "null" + ] + }, + "tests": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "summary", + "evidence" + ], + "type": "object" + }, + "write_scope": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array" + }, + "status": { + "enum": [ + "COMPLIANT", + "NON_COMPLIANT", + "UNKNOWN" + ] + } + }, + "required": [ + "status", + "evidence" + ], + "type": "object" + } + }, + "required": [ + "schema_version", + "id", + "created_at", + "mode", + "stage", + "phase", + "result", + "git", + "tests", + "risks", + "agent_tree", + "write_scope", + "next_action", + "recovery", + "artifact_hashes" + ], + "title": "PlanAnvil checkpoint", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/comparison.schema.json b/.agents/skills/plan-anvil/schemas/comparison.schema.json new file mode 100644 index 0000000..807993e --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/comparison.schema.json @@ -0,0 +1,103 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/comparison.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "blind_review_hash": { + "$ref": "#/$defs/hash" + }, + "blind_review_sidecar_hash": { + "$ref": "#/$defs/hash" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "deterministic_validation": { + "enum": [ + "PASS", + "FAIL", + "MISSING" + ] + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "result": { + "enum": [ + "PASS", + "FAIL", + "BLOCKED" + ] + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "created_at", + "result", + "blind_review_hash", + "blind_review_sidecar_hash", + "deterministic_validation", + "reasons" + ], + "title": "PlanAnvil review comparison", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/compliance.schema.json b/.agents/skills/plan-anvil/schemas/compliance.schema.json new file mode 100644 index 0000000..533abab --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/compliance.schema.json @@ -0,0 +1,163 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/compliance.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "capabilities": { + "items": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array" + }, + "id": { + "pattern": "^CAP-[A-Z0-9-]+$", + "type": "string" + }, + "required": { + "type": "boolean" + }, + "status": { + "enum": [ + "VERIFIED", + "DOCUMENTED", + "FAILED", + "BLOCKED", + "UNKNOWN", + "NOT_APPLICABLE" + ] + } + }, + "required": [ + "id", + "status", + "required", + "evidence" + ], + "type": "object" + }, + "type": "array" + }, + "codex": { + "additionalProperties": false, + "properties": { + "hook_mode": { + "enum": [ + "HOOKS_TRUSTED", + "HOOKS_DISABLED", + "HOOKS_UNTRUSTED", + "HOOKS_UNAVAILABLE" + ] + }, + "model": { + "type": "string" + }, + "permission_mode": { + "type": "string" + }, + "project_trust": { + "enum": [ + "TRUSTED", + "UNTRUSTED", + "UNKNOWN" + ] + }, + "version": { + "type": "string" + } + }, + "required": [ + "version", + "model", + "permission_mode", + "project_trust", + "hook_mode" + ], + "type": "object" + }, + "schema_version": { + "const": "1.1.0" + }, + "unsupported": { + "items": { + "type": "string" + }, + "type": "array" + }, + "verified_at": { + "$ref": "#/$defs/timestamp" + }, + "warnings": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "schema_version", + "verified_at", + "codex", + "capabilities", + "unsupported", + "warnings" + ], + "title": "PlanAnvil compliance record", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/git-capability.schema.json b/.agents/skills/plan-anvil/schemas/git-capability.schema.json new file mode 100644 index 0000000..f9e1a0e --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/git-capability.schema.json @@ -0,0 +1,115 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/git-capability.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "base_branch": { + "minLength": 1, + "type": "string" + }, + "base_sha": { + "$ref": "#/$defs/sha" + }, + "cleanup": { + "additionalProperties": false, + "properties": { + "errors": { + "maxItems": 0, + "type": "array" + }, + "result": { + "const": "PASS" + } + }, + "required": [ + "result", + "errors" + ], + "type": "object" + }, + "result": { + "const": "GIT_READY" + }, + "schema_version": { + "const": "1.1.0" + }, + "source_snapshot": { + "additionalProperties": false, + "properties": { + "branch": { + "type": [ + "string", + "null" + ] + }, + "head": { + "$ref": "#/$defs/sha" + }, + "index_hash": { + "$ref": "#/$defs/hash" + }, + "status_hash": { + "$ref": "#/$defs/hash" + } + }, + "required": [ + "head", + "branch", + "status_hash", + "index_hash" + ], + "type": "object" + }, + "steps": { + "items": { + "additionalProperties": false, + "properties": { + "id": { + "minLength": 1, + "type": "string" + }, + "result": { + "const": "PASS" + } + }, + "required": [ + "id", + "result" + ], + "type": "object" + }, + "minItems": 10, + "type": "array", + "uniqueItems": true + }, + "verified_at": { + "$ref": "#/$defs/timestamp" + } + }, + "required": [ + "schema_version", + "verified_at", + "result", + "base_branch", + "base_sha", + "source_snapshot", + "steps", + "cleanup" + ], + "title": "PlanAnvil sanitized Git capability evidence", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/instruction-map.schema.json b/.agents/skills/plan-anvil/schemas/instruction-map.schema.json new file mode 100644 index 0000000..442e381 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/instruction-map.schema.json @@ -0,0 +1,182 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/instruction-map.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "affected_paths": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "automatic_byte_limit": { + "minimum": 1, + "type": "integer" + }, + "conflicts": { + "items": { + "additionalProperties": false, + "properties": { + "critical": { + "type": "boolean" + }, + "paths": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "minItems": 2, + "type": "array" + }, + "resolution": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "paths", + "critical", + "resolution" + ], + "type": "object" + }, + "type": "array" + }, + "fallback_filenames": { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "files": { + "items": { + "additionalProperties": false, + "properties": { + "affected_paths": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "minItems": 1, + "type": "array" + }, + "bytes": { + "minimum": 1, + "type": "integer" + }, + "full_read": { + "const": true + }, + "path": { + "$ref": "#/$defs/relative_path" + }, + "precedence": { + "minimum": 0, + "type": "integer" + }, + "safety_critical_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "scope": { + "$ref": "#/$defs/relative_path" + }, + "sha256": { + "$ref": "#/$defs/hash" + }, + "truncation_risk": { + "type": "boolean" + } + }, + "required": [ + "path", + "sha256", + "bytes", + "full_read", + "scope", + "precedence", + "affected_paths", + "truncation_risk", + "safety_critical_rules" + ], + "type": "object" + }, + "type": "array" + }, + "generated_at": { + "$ref": "#/$defs/timestamp" + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "generated_at", + "affected_paths", + "fallback_filenames", + "automatic_byte_limit", + "files", + "conflicts" + ], + "title": "PlanAnvil instruction map", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/lifecycle.schema.json b/.agents/skills/plan-anvil/schemas/lifecycle.schema.json new file mode 100644 index 0000000..9d407b8 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/lifecycle.schema.json @@ -0,0 +1,74 @@ +{ + "$defs": { + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/lifecycle.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "events": { + "items": { + "additionalProperties": false, + "properties": { + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "result": { + "const": "PASS" + }, + "sequence": { + "maximum": 4, + "minimum": 1, + "type": "integer" + }, + "state": { + "enum": [ + "SOURCE_PREFLIGHT_PASSED", + "GIT_READY", + "PLANNING_WORKTREE_READY", + "PROFILE_READY" + ] + } + }, + "required": [ + "sequence", + "state", + "result", + "evidence" + ], + "type": "object" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "recorded_at": { + "$ref": "#/$defs/timestamp" + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "recorded_at", + "events" + ], + "title": "PlanAnvil bootstrap lifecycle evidence", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/local-state.schema.json b/.agents/skills/plan-anvil/schemas/local-state.schema.json new file mode 100644 index 0000000..586b179 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/local-state.schema.json @@ -0,0 +1,141 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/local-state.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "hashes": { + "additionalProperties": false, + "properties": { + "local_profile": { + "$ref": "#/$defs/hash" + } + }, + "required": [ + "local_profile" + ], + "type": "object" + }, + "paths": { + "additionalProperties": false, + "properties": { + "local_profile": { + "minLength": 1, + "type": "string" + }, + "planning_worktree": { + "minLength": 1, + "type": "string" + }, + "source_worktree": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "source_worktree", + "planning_worktree", + "local_profile" + ], + "type": "object" + }, + "run_id": { + "$ref": "#/$defs/run_id" + }, + "schema_version": { + "const": "1.1.0" + }, + "source_snapshot": { + "additionalProperties": false, + "properties": { + "branch": { + "type": [ + "string", + "null" + ] + }, + "head": { + "$ref": "#/$defs/sha" + }, + "index_hash": { + "$ref": "#/$defs/hash" + }, + "status_hash": { + "$ref": "#/$defs/hash" + } + }, + "required": [ + "head", + "branch", + "status_hash", + "index_hash" + ], + "type": "object" + }, + "updated_at": { + "$ref": "#/$defs/timestamp" + } + }, + "required": [ + "schema_version", + "run_id", + "updated_at", + "paths", + "hashes", + "source_snapshot" + ], + "title": "PlanAnvil local state", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/manifest.schema.json b/.agents/skills/plan-anvil/schemas/manifest.schema.json new file mode 100644 index 0000000..978fccd --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/manifest.schema.json @@ -0,0 +1,170 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/manifest.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "contract_versions": { + "additionalProperties": false, + "properties": { + "artifact_schema": { + "const": "1.1.0" + }, + "implementation_spec": { + "const": "2.1" + }, + "plan_contract": { + "const": "1.0.0" + } + }, + "required": [ + "implementation_spec", + "plan_contract", + "artifact_schema" + ], + "type": "object" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "generator_version": { + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", + "type": "string" + }, + "paths": { + "additionalProperties": false, + "properties": { + "compliance": { + "$ref": "#/$defs/relative_path" + }, + "local_state": { + "$ref": "#/$defs/relative_path" + }, + "plan": { + "$ref": "#/$defs/relative_path" + }, + "repository_profile": { + "$ref": "#/$defs/relative_path" + }, + "run_root": { + "$ref": "#/$defs/relative_path" + }, + "state": { + "$ref": "#/$defs/relative_path" + }, + "traceability": { + "$ref": "#/$defs/relative_path" + } + }, + "required": [ + "run_root", + "plan", + "state", + "compliance", + "traceability", + "repository_profile", + "local_state" + ], + "type": "object" + }, + "plan_id": { + "$ref": "#/$defs/plan_id" + }, + "repository": { + "additionalProperties": false, + "properties": { + "base_branch": { + "minLength": 1, + "type": "string" + }, + "base_sha": { + "$ref": "#/$defs/sha" + }, + "fingerprint": { + "$ref": "#/$defs/hash" + }, + "planning_branch": { + "pattern": "^pursue/plan/PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}/[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + } + }, + "required": [ + "fingerprint", + "base_branch", + "base_sha", + "planning_branch" + ], + "type": "object" + }, + "run_id": { + "$ref": "#/$defs/run_id" + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "plan_id", + "run_id", + "created_at", + "generator_version", + "repository", + "paths", + "contract_versions" + ], + "title": "PlanAnvil manifest", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/review.schema.json b/.agents/skills/plan-anvil/schemas/review.schema.json new file mode 100644 index 0000000..b0ee03b --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/review.schema.json @@ -0,0 +1,127 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/review.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "findings": { + "items": { + "additionalProperties": false, + "properties": { + "id": { + "pattern": "^FINDING-[0-9]{2,}$", + "type": "string" + }, + "severity": { + "enum": [ + "LOW", + "MEDIUM", + "HIGH", + "CRITICAL" + ] + }, + "summary": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "id", + "severity", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "inputs": { + "additionalProperties": { + "$ref": "#/$defs/hash" + }, + "minProperties": 1, + "type": "object" + }, + "markdown_hash": { + "$ref": "#/$defs/hash" + }, + "report_type": { + "const": "BLIND_PLAN_REVIEW" + }, + "result": { + "enum": [ + "PASS", + "FAIL", + "BLOCKED" + ] + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "report_type", + "created_at", + "inputs", + "result", + "findings", + "markdown_hash" + ], + "title": "PlanAnvil blind review sidecar", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/risk.schema.json b/.agents/skills/plan-anvil/schemas/risk.schema.json new file mode 100644 index 0000000..01bad11 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/risk.schema.json @@ -0,0 +1,166 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/risk.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "affected_components": { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "controls": { + "items": { + "pattern": "^CTRL-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "criteria": { + "items": { + "pattern": "^AC-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "description": { + "minLength": 1, + "type": "string" + }, + "detection": { + "items": { + "pattern": "^CTRL-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "id": { + "pattern": "^RISK-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "impact": { + "enum": [ + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "level": { + "enum": [ + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "mitigation": { + "minLength": 1, + "type": "string" + }, + "probability": { + "enum": [ + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "rollback": { + "minLength": 1, + "type": "string" + }, + "schema_version": { + "const": "1.1.0" + }, + "source": { + "minLength": 1, + "type": "string" + }, + "stage": { + "$ref": "#/$defs/stage_id" + }, + "status": { + "enum": [ + "OPEN", + "MITIGATED", + "ACCEPTED_BY_USER", + "CLOSED", + "REALIZED" + ] + } + }, + "required": [ + "schema_version", + "id", + "stage", + "level", + "description", + "source", + "affected_components", + "probability", + "impact", + "detection", + "criteria", + "controls", + "mitigation", + "rollback", + "status" + ], + "title": "PlanAnvil risk", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/state.schema.json b/.agents/skills/plan-anvil/schemas/state.schema.json new file mode 100644 index 0000000..e7222ea --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/state.schema.json @@ -0,0 +1,152 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/state.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "artifact_hashes": { + "additionalProperties": { + "$ref": "#/$defs/hash" + }, + "type": "object" + }, + "current_phase": { + "type": [ + "string", + "null" + ] + }, + "current_stage": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": [ + "string", + "null" + ] + }, + "last_checkpoint": { + "type": [ + "string", + "null" + ] + }, + "mode": { + "enum": [ + "PLAN_GENERATION", + "PLAN_EXECUTION" + ] + }, + "next_action": { + "$ref": "#/$defs/next_action" + }, + "open_blockers": { + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "revision": { + "minimum": 0, + "type": "integer" + }, + "schema_version": { + "const": "1.1.0" + }, + "status": { + "enum": [ + "NEW", + "SOURCE_PREFLIGHT_PASSED", + "GIT_READY", + "PLANNING_WORKTREE_READY", + "PROFILE_READY", + "INSTRUCTION_MAP_READY", + "ANALYSIS_READY", + "ARTIFACTS_GENERATED", + "DETERMINISTICALLY_VALID", + "BLIND_REVIEW_WRITTEN", + "COMPARISON_VALID", + "PLAN_COMMITTED", + "STOPPED", + "BLOCKED", + "FAILED", + "EXECUTION_READY", + "EXECUTION_IN_PROGRESS", + "READY_FOR_LOCAL_INTEGRATION_TEST", + "AWAITING_USER_VALIDATION", + "USER_ACCEPTED", + "USER_REJECTED", + "BLOCKED_BY_UNRESOLVED_FAILURE" + ] + }, + "updated_at": { + "$ref": "#/$defs/timestamp" + } + }, + "required": [ + "schema_version", + "revision", + "updated_at", + "mode", + "status", + "current_stage", + "current_phase", + "next_action", + "last_checkpoint", + "open_blockers", + "artifact_hashes" + ], + "title": "PlanAnvil state", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/schemas/traceability.schema.json b/.agents/skills/plan-anvil/schemas/traceability.schema.json new file mode 100644 index 0000000..5bd8cf4 --- /dev/null +++ b/.agents/skills/plan-anvil/schemas/traceability.schema.json @@ -0,0 +1,230 @@ +{ + "$defs": { + "hash": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "next_action": { + "additionalProperties": false, + "properties": { + "target": { + "type": [ + "string", + "null" + ] + }, + "type": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "target" + ], + "type": "object" + }, + "plan_id": { + "pattern": "^PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}$", + "type": "string" + }, + "relative_path": { + "minLength": 1, + "not": { + "pattern": "(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)|^(?:/|[A-Za-z]:[\\\\/]|\\\\\\\\)" + }, + "type": "string" + }, + "run_id": { + "pattern": "^[0-9]{8}T[0-9]{6}Z_PG-[0-9]{8}-[0-9]{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "sha": { + "pattern": "^[0-9a-f]{40,64}$", + "type": "string" + }, + "stage_id": { + "pattern": "^STAGE-[0-9]{2}[A-Z]?$", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "type": "string" + } + }, + "$id": "https://keyffms.github.io/PlanAnvil/schemas/traceability.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "controls": { + "items": { + "additionalProperties": false, + "properties": { + "description": { + "minLength": 1, + "type": "string" + }, + "id": { + "pattern": "^CTRL-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "verification": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "id", + "description", + "verification" + ], + "type": "object" + }, + "type": "array" + }, + "criteria": { + "items": { + "additionalProperties": false, + "properties": { + "controls": { + "items": { + "pattern": "^CTRL-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "evidence": { + "items": { + "$ref": "#/$defs/relative_path" + }, + "type": "array" + }, + "evidence_type": { + "enum": [ + "AUTOMATED_TEST", + "STATIC_ANALYSIS", + "MANUAL_VERIFICATION", + "OBSERVATION", + "DOCUMENT_REVIEW", + "MIGRATION_EVIDENCE" + ] + }, + "id": { + "pattern": "^AC-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "risks": { + "items": { + "pattern": "^RISK-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "stage": { + "$ref": "#/$defs/stage_id" + } + }, + "required": [ + "id", + "stage", + "risks", + "controls", + "evidence_type", + "evidence" + ], + "type": "object" + }, + "type": "array" + }, + "gaps": { + "items": { + "additionalProperties": false, + "properties": { + "critical": { + "type": "boolean" + }, + "detail": { + "minLength": 1, + "type": "string" + }, + "type": { + "enum": [ + "UNCOVERED_REQUIREMENT", + "STAGE_WITHOUT_REQUIREMENT", + "CRITERION_WITHOUT_EVIDENCE", + "RISK_WITHOUT_CONTROL", + "CONTROL_WITHOUT_BEHAVIOR", + "PUBLIC_BEHAVIOR_WITHOUT_REQUIRED_APPROVAL" + ] + } + }, + "required": [ + "type", + "critical", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "requirements": { + "items": { + "additionalProperties": false, + "properties": { + "criteria": { + "items": { + "pattern": "^AC-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "critical": { + "type": "boolean" + }, + "id": { + "pattern": "^REQ-[0-9]{2}[A-Z]?-[0-9]{2}$", + "type": "string" + }, + "stages": { + "items": { + "$ref": "#/$defs/stage_id" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "text": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "id", + "text", + "critical", + "stages", + "criteria" + ], + "type": "object" + }, + "type": "array" + }, + "schema_version": { + "const": "1.1.0" + } + }, + "required": [ + "schema_version", + "requirements", + "criteria", + "controls", + "gaps" + ], + "title": "PlanAnvil traceability", + "type": "object" +} diff --git a/.agents/skills/plan-anvil/scripts/commit_plan.py b/.agents/skills/plan-anvil/scripts/commit_plan.py new file mode 100644 index 0000000..9b9381c --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/commit_plan.py @@ -0,0 +1,189 @@ +from __future__ import annotations + +import argparse +import fnmatch +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_text, + cli_main, + compare_snapshot, + discover_repo, + emit, + git, + load_json, + repo_relative, +) +from transition_state import transition_state +from validate_all import validate_all + + +def _staged_paths(repo: Path) -> list[str]: + result = git(repo, "diff", "--cached", "--name-only", "-z", "--") + return sorted(item for item in result.stdout.split("\0") if item) + + +def _allowed(path: str, run_rel: str) -> bool: + patterns = [".gitignore", ".pursue/SYSTEM_PROFILE.md", f"{run_rel}/**"] + return any(fnmatch.fnmatchcase(path, pattern) for pattern in patterns) + + +def _commit(repo: Path, message: str) -> str: + result = git(repo, "commit", "-m", message, check=False, timeout=180) + if result.returncode != 0: + raise PlanAnvilError( + f"Git commit failed: {message}", + code="PLAN_COMMIT_FAILED", + details={"stdout": result.stdout, "stderr": result.stderr}, + ) + return git(repo, "rev-parse", "HEAD").stdout.strip() + + +def commit_plan( + planning: Path, + run_root: Path, + *, + source: Path | None = None, + message: str | None = None, +) -> dict[str, Any]: + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + manifest = load_json(run / "manifest.json") + local_state = load_json(run / "local-state.json") + state_path = run / "state.json" + state = load_json(state_path) + if state.get("status") != "COMPARISON_VALID": + raise PlanAnvilError( + f"Commit requires COMPARISON_VALID, found {state.get('status')}", + code="INVALID_STATE_FOR_COMMIT", + ) + + final_validation = validate_all( + repo, + run, + source=source, + phase="final", + advance_state=False, + ) + if not final_validation["ok"]: + raise PlanAnvilError("Final validation failed", code="PLAN_VALIDATION_FAILED", details=final_validation["findings"]) + + source_repo = discover_repo(source) if source else Path(local_state["paths"]["source_worktree"]) + changed = compare_snapshot(source_repo, local_state["source_snapshot"]) + if changed: + raise PlanAnvilError("Source worktree changed before commit", code="SOURCE_CHANGED", details=changed) + + transition_state( + state_path, + expected_revision=state["revision"], + new_status="PLAN_COMMITTED", + phase="COMMIT_PLANNING_ARTIFACTS", + next_action_type="WRITE_FINAL_REPORT", + next_action_target="final/REPORT.md", + hash_paths=[ + run / "PLAN.md", + run / "traceability.json", + run / "reports/validation/summary.json", + run / "reports/plan-review/blind-review.md", + run / "reports/plan-review/blind-review.json", + run / "reports/plan-review/comparison.json", + ], + ) + + run_rel = repo_relative(repo, run) + git(repo, "add", "--", ".gitignore", ".pursue/SYSTEM_PROFILE.md", run_rel) + staged = _staged_paths(repo) + forbidden = [ + ".pursue/SYSTEM_PROFILE.local.md", + f"{run_rel}/local-state.json", + f"{run_rel}/.generation-lock", + f"{run_rel}/.execution-lock", + ] + bad = [ + path for path in staged + if not _allowed(path, run_rel) or any(fnmatch.fnmatchcase(path, item) for item in forbidden) + ] + if bad: + raise PlanAnvilError("Staged paths violate the planning allowlist", code="STAGED_PATH_VIOLATION", details=bad) + if not staged: + raise PlanAnvilError("No planning artifacts are staged", code="NOTHING_TO_COMMIT") + + plan_id = manifest["plan_id"] + plan_commit = _commit(repo, message or f"Add PlanAnvil plan {plan_id}") + + comparison = load_json(run / "reports/plan-review/comparison.json") + report = f"""# PlanAnvil Final Report + +- Status: `PLAN_READY` +- Planning branch: `{manifest['repository']['planning_branch']}` +- Planning commit: `{plan_commit}` +- Plan: `{run_rel}/PLAN.md` +- Deterministic validation: `PASS` +- Blind review: `PASS` +- Comparison: `{comparison['result']}` + +## Assumptions and unknowns + +See `PLAN.md`. Any recorded non-critical unknown remains subject to its stated verification step. Critical unknowns are not permitted in a ready plan. + +## Next run + +Use the separate execution-run prompt in `PLAN.md`. Reconcile the manifest, canonical state, ignored local state, profiles, latest valid checkpoint, and Git state before executing only the next approved action. + +No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md. +""" + report_path = run / "final/REPORT.md" + atomic_write_text(report_path, report) + + current_state = load_json(state_path) + transition_state( + state_path, + expected_revision=current_state["revision"], + new_status="STOPPED", + phase="REPORT_AND_STOP", + next_action_type="NONE", + next_action_target=None, + hash_paths=[report_path], + ) + git(repo, "add", "--", repo_relative(repo, state_path), repo_relative(repo, report_path)) + staged_final = _staged_paths(repo) + bad_final = [path for path in staged_final if not _allowed(path, run_rel)] + if bad_final: + raise PlanAnvilError("Final staged paths violate allowlist", code="STAGED_PATH_VIOLATION", details=bad_final) + final_commit = _commit(repo, f"Finalize PlanAnvil plan {plan_id}") + + status = git(repo, "status", "--porcelain=v1", "--untracked-files=all").stdout + if status: + raise PlanAnvilError("Planning worktree is not clean after final commit", code="PLANNING_WORKTREE_DIRTY", details=status) + changed = compare_snapshot(source_repo, local_state["source_snapshot"]) + if changed: + raise PlanAnvilError("Source worktree changed during commit", code="SOURCE_CHANGED", details=changed) + + return { + "ok": True, + "result": "STOPPED", + "status": "PLAN_READY", + "planning_branch": manifest["repository"]["planning_branch"], + "plan_commit": plan_commit, + "final_commit": final_commit, + "plan": f"{run_rel}/PLAN.md", + "final_report": f"{run_rel}/final/REPORT.md", + "pushed": False, + "implementation_executed": False, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Validate and commit only approved PlanAnvil planning artifacts") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--source", type=Path) + parser.add_argument("--message") + args = parser.parse_args() + return emit(commit_plan(args.planning, args.run_root, source=args.source, message=args.message)) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/common.py b/.agents/skills/plan-anvil/scripts/common.py new file mode 100644 index 0000000..fbdcec4 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/common.py @@ -0,0 +1,431 @@ +from __future__ import annotations + +import argparse +import datetime as dt +import hashlib +import json +import os +import re +import secrets +import subprocess +import sys +import tempfile +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Iterable, Sequence +from urllib.parse import urlsplit, urlunsplit + +SCHEMA_VERSION = "1.1.0" +GENERATOR_VERSION = "0.1.0" +CONTRACT_VERSION = "2.1" + +PLAN_ID_RE = re.compile(r"^PG-\d{8}-\d{6}-[A-F0-9]{4}$") +RUN_ID_RE = re.compile( + r"^\d{8}T\d{6}Z_PG-\d{8}-\d{6}-[A-F0-9]{4}_[a-z0-9]+(?:-[a-z0-9]+)*$" +) +STAGE_ID_RE = re.compile(r"^STAGE-\d{2}[A-Z]?$") +HASH_RE = re.compile(r"^sha256:[0-9a-f]{64}$") +SHA_RE = re.compile(r"^[0-9a-f]{40,64}$") + +GENERATOR_STATES = [ + "NEW", + "SOURCE_PREFLIGHT_PASSED", + "GIT_READY", + "PLANNING_WORKTREE_READY", + "PROFILE_READY", + "INSTRUCTION_MAP_READY", + "ANALYSIS_READY", + "ARTIFACTS_GENERATED", + "DETERMINISTICALLY_VALID", + "BLIND_REVIEW_WRITTEN", + "COMPARISON_VALID", + "PLAN_COMMITTED", + "STOPPED", +] + +TERMINAL_PLAN_STATUSES = { + "PLAN_READY", + "BLOCKED_BY_CRITICAL_UNKNOWN", + "BLOCKED_BY_GIT_STATE", + "BLOCKED_BY_GIT_PERMISSIONS", + "BLOCKED_BY_INSTRUCTION_CONFLICT", + "BLOCKED_BY_RUNTIME_PREREQUISITE", + "PLAN_VALIDATION_FAILED", +} + +SECRET_PATTERNS = [ + ("private-key", re.compile(r"-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----")), + ("generic-token", re.compile(r"(?i)\b(?:api[_-]?key|access[_-]?token|secret|password)\b\s*[:=]\s*[\"']?[A-Za-z0-9_./+=-]{12,}")), + ("github-token", re.compile(r"\bgh[pousr]_[A-Za-z0-9]{20,}\b")), + ("aws-access-key", re.compile(r"\bAKIA[0-9A-Z]{16}\b")), +] + +ABSOLUTE_PATH_PATTERNS = [ + re.compile(r"(?]+"), + re.compile(r"(?i)(?]+"), + re.compile(r"\\\\[^\\\s]+\\[^\\\s]+"), + re.compile(r"(?]+"), +] + + +class PlanAnvilError(RuntimeError): + def __init__(self, message: str, *, code: str = "PLANANVIL_ERROR", details: Any = None): + super().__init__(message) + self.code = code + self.details = details + + +@dataclass(frozen=True) +class CommandResult: + args: tuple[str, ...] + returncode: int + stdout: str + stderr: str + + +def utc_now() -> str: + return dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z") + + +def timestamp_id() -> str: + return dt.datetime.now(dt.timezone.utc).strftime("%Y%m%dT%H%M%SZ") + + +def make_plan_id() -> str: + now = dt.datetime.now(dt.timezone.utc) + return f"PG-{now:%Y%m%d-%H%M%S}-{secrets.token_hex(2).upper()}" + + +def slugify(value: str, *, default: str = "plan", max_length: int = 48) -> str: + value = value.lower() + value = re.sub(r"[^a-z0-9]+", "-", value).strip("-") + value = re.sub(r"-{2,}", "-", value) + return (value[:max_length].rstrip("-") or default) + + +def make_run_id(plan_id: str, slug: str) -> str: + if not PLAN_ID_RE.fullmatch(plan_id): + raise PlanAnvilError(f"Invalid plan id: {plan_id}", code="INVALID_PLAN_ID") + return f"{timestamp_id()}_{plan_id}_{slugify(slug)}" + + +def sha256_bytes(data: bytes) -> str: + return "sha256:" + hashlib.sha256(data).hexdigest() + + +def sha256_text(text: str) -> str: + return sha256_bytes(text.encode("utf-8")) + + +def sha256_file(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as handle: + for chunk in iter(lambda: handle.read(1024 * 1024), b""): + digest.update(chunk) + return "sha256:" + digest.hexdigest() + + +def canonical_json_text(value: Any) -> str: + return json.dumps(value, indent=2, sort_keys=True, ensure_ascii=False) + "\n" + + +def atomic_write_text(path: Path, text: str, *, exclusive: bool = False) -> None: + path = path.resolve() + path.parent.mkdir(parents=True, exist_ok=True) + if exclusive and path.exists(): + raise PlanAnvilError(f"Refusing to overwrite immutable file: {path}", code="IMMUTABLE_EXISTS") + mode = "x" if exclusive else "w" + if exclusive: + with path.open(mode, encoding="utf-8", newline="\n") as handle: + handle.write(text) + handle.flush() + os.fsync(handle.fileno()) + return + fd, tmp_name = tempfile.mkstemp(prefix=f".{path.name}.", suffix=".tmp", dir=str(path.parent)) + tmp = Path(tmp_name) + try: + with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as handle: + handle.write(text) + handle.flush() + os.fsync(handle.fileno()) + os.replace(tmp, path) + try: + directory_fd = os.open(path.parent, os.O_RDONLY) + except (AttributeError, OSError): + directory_fd = None + if directory_fd is not None: + try: + os.fsync(directory_fd) + finally: + os.close(directory_fd) + finally: + if tmp.exists(): + tmp.unlink() + + +def atomic_write_json(path: Path, value: Any, *, exclusive: bool = False) -> None: + atomic_write_text(path, canonical_json_text(value), exclusive=exclusive) + + +def load_json(path: Path) -> Any: + try: + return json.loads(path.read_text(encoding="utf-8")) + except FileNotFoundError as exc: + raise PlanAnvilError(f"Missing JSON file: {path}", code="MISSING_FILE") from exc + except json.JSONDecodeError as exc: + raise PlanAnvilError( + f"Invalid JSON in {path}: line {exc.lineno}, column {exc.colno}", + code="INVALID_JSON", + ) from exc + + +def command( + args: Sequence[str], + *, + cwd: Path | None = None, + check: bool = True, + env: dict[str, str] | None = None, + input_text: str | None = None, + timeout: int = 120, +) -> CommandResult: + process = subprocess.run( + list(args), + cwd=str(cwd) if cwd else None, + env=env, + input=input_text, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + timeout=timeout, + shell=False, + ) + result = CommandResult(tuple(str(x) for x in args), process.returncode, process.stdout, process.stderr) + if check and process.returncode != 0: + raise PlanAnvilError( + f"Command failed ({process.returncode}): {' '.join(result.args)}", + code="COMMAND_FAILED", + details={"stdout": result.stdout, "stderr": result.stderr}, + ) + return result + + +def git( + repo: Path, + *args: str, + check: bool = True, + timeout: int = 120, + env: dict[str, str] | None = None, +) -> CommandResult: + return command(["git", "-C", str(repo), *args], check=check, timeout=timeout, env=env) + + +def discover_repo(path: Path) -> Path: + result = git(path, "rev-parse", "--show-toplevel", check=False) + if result.returncode != 0: + raise PlanAnvilError("Not inside a Git repository", code="NOT_A_GIT_REPOSITORY") + return Path(result.stdout.strip()).resolve() + + +def git_path(repo: Path, name: str) -> Path: + result = git(repo, "rev-parse", "--git-path", name) + raw = Path(result.stdout.strip()) + return raw.resolve() if raw.is_absolute() else (repo / raw).resolve() + + +def detect_git_operation(repo: Path) -> str | None: + checks = [ + ("MERGE", "MERGE_HEAD"), + ("CHERRY_PICK", "CHERRY_PICK_HEAD"), + ("REVERT", "REVERT_HEAD"), + ("BISECT", "BISECT_LOG"), + ("REBASE", "rebase-merge"), + ("REBASE", "rebase-apply"), + ] + for label, name in checks: + if git_path(repo, name).exists(): + return label + return None + + +def source_snapshot(repo: Path) -> dict[str, Any]: + repo = discover_repo(repo) + head = git(repo, "rev-parse", "HEAD").stdout.strip() + branch_result = git(repo, "symbolic-ref", "--quiet", "--short", "HEAD", check=False) + branch = branch_result.stdout.strip() if branch_result.returncode == 0 else None + status = git(repo, "status", "--porcelain=v1", "-z", "--untracked-files=all").stdout.encode("utf-8", "surrogateescape") + index = git(repo, "ls-files", "--stage", "-z").stdout.encode("utf-8", "surrogateescape") + return { + "head": head, + "branch": branch, + "status_hash": sha256_bytes(status), + "index_hash": sha256_bytes(index), + } + + +def compare_snapshot(repo: Path, expected: dict[str, Any]) -> list[str]: + current = source_snapshot(repo) + return [key for key in ("head", "branch", "status_hash", "index_hash") if current.get(key) != expected.get(key)] + + + + +def path_is_within(root: Path, candidate: Path) -> bool: + try: + candidate.resolve().relative_to(root.resolve()) + return True + except (OSError, ValueError): + return False + + +def git_worktree_paths(repo: Path) -> list[Path]: + repo = discover_repo(repo) + result = git(repo, "worktree", "list", "--porcelain", check=False) + if result.returncode != 0: + raise PlanAnvilError("Could not list Git worktrees", code="GIT_WORKTREE_UNSUPPORTED", details=result.stderr) + paths = [ + Path(line.removeprefix("worktree ")).resolve() + for line in result.stdout.splitlines() + if line.startswith("worktree ") + ] + return paths or [repo] + + +def require_external_path(repo: Path, candidate: Path, *, code: str) -> Path: + resolved = candidate.resolve() + for worktree in git_worktree_paths(repo): + if path_is_within(worktree, resolved): + raise PlanAnvilError( + f"Path must be outside every repository worktree: {resolved}", + code=code, + details={"worktree": str(worktree), "candidate": str(resolved)}, + ) + return resolved + +def repository_fingerprint(repo: Path) -> str: + repo = discover_repo(repo) + remote = git(repo, "config", "--get", "remote.origin.url", check=False).stdout.strip() + if remote: + identity = sanitize_remote_identity(remote) + else: + roots = git(repo, "rev-list", "--max-parents=0", "--all", check=False).stdout.splitlines() + identity = "roots:" + ",".join(sorted(roots)) + return sha256_text(identity) + + +def sanitize_remote_identity(remote: str) -> str: + remote = remote.strip() + scp_match = re.match(r"^(?:[^@]+@)?([^:]+):(.+)$", remote) + if scp_match and "://" not in remote: + host, path = scp_match.groups() + return f"{host.lower()}/{path.removesuffix('.git')}" + parts = urlsplit(remote) + if parts.scheme and parts.netloc: + host = parts.hostname or parts.netloc + port = f":{parts.port}" if parts.port else "" + path = parts.path.removesuffix(".git") + return urlunsplit((parts.scheme.lower(), host.lower() + port, path, "", "")) + return remote.removesuffix(".git") + + +def ensure_inside(root: Path, candidate: Path, *, allow_root: bool = True) -> Path: + root = root.resolve() + candidate = candidate.resolve(strict=False) + try: + relative = candidate.relative_to(root) + except ValueError as exc: + raise PlanAnvilError(f"Path escapes allowed root: {candidate}", code="PATH_ESCAPE") from exc + if not allow_root and relative == Path("."): + raise PlanAnvilError("Root path is not an allowed target", code="PATH_ESCAPE") + if ".git" in relative.parts: + raise PlanAnvilError(f"Direct .git write is forbidden: {candidate}", code="GIT_PATH_FORBIDDEN") + return candidate + + +def repo_relative(root: Path, path: Path) -> str: + return ensure_inside(root, path).relative_to(root.resolve()).as_posix() or "." + + +def append_ignore_rules(repo: Path, rules: Iterable[str]) -> bool: + repo = discover_repo(repo) + ignore = repo / ".gitignore" + existing = ignore.read_text(encoding="utf-8") if ignore.exists() else "" + lines = existing.splitlines() + missing = [rule for rule in rules if rule not in lines] + if not missing: + return False + block = "\n".join(["", "# PlanAnvil local state", *missing, ""]) + atomic_write_text(ignore, existing.rstrip("\n") + block) + return True + + +def is_ignored(repo: Path, path: Path) -> bool: + relative = repo_relative(repo, path) + return git(repo, "check-ignore", "-q", "--", relative, check=False).returncode == 0 + + +def is_tracked(repo: Path, path: Path) -> bool: + relative = repo_relative(repo, path) + return git(repo, "ls-files", "--error-unmatch", "--", relative, check=False).returncode == 0 + + +def list_untracked(repo: Path) -> list[str]: + result = git(repo, "ls-files", "--others", "--exclude-standard", "-z") + return [item for item in result.stdout.split("\0") if item] + + +def privacy_findings(path: Path, text: str) -> list[dict[str, str]]: + findings: list[dict[str, str]] = [] + for name, pattern in SECRET_PATTERNS: + if pattern.search(text): + findings.append({"path": path.as_posix(), "kind": name}) + for pattern in ABSOLUTE_PATH_PATTERNS: + match = pattern.search(text) + if match: + findings.append({"path": path.as_posix(), "kind": "absolute-path", "sample": match.group(0)[:120]}) + return findings + + +def scan_privacy(root: Path, paths: Iterable[Path]) -> list[dict[str, str]]: + findings: list[dict[str, str]] = [] + for path in paths: + if not path.is_file(): + continue + try: + text = path.read_text(encoding="utf-8") + except UnicodeDecodeError: + continue + rel = Path(repo_relative(root, path)) + findings.extend(privacy_findings(rel, text)) + return findings + + +def emit(payload: dict[str, Any], *, exit_code: int = 0) -> int: + sys.stdout.write(canonical_json_text(payload)) + return exit_code + + +def fail_payload(exc: Exception) -> dict[str, Any]: + if isinstance(exc, PlanAnvilError): + return {"ok": False, "error": exc.code, "message": str(exc), "details": exc.details} + return {"ok": False, "error": exc.__class__.__name__, "message": str(exc)} + + +def cli_main(function) -> None: + try: + code = function() + except Exception as exc: # top-level machine-readable failure boundary + emit(fail_payload(exc), exit_code=1) + raise SystemExit(1) + raise SystemExit(code if isinstance(code, int) else 0) + + +def add_source_argument(parser: argparse.ArgumentParser) -> None: + parser.add_argument("--source", type=Path, default=Path.cwd(), help="Source repository or path inside it") + + +def canonical_file_is_valid(path: Path) -> bool: + try: + value = load_json(path) + except PlanAnvilError: + return False + return path.read_text(encoding="utf-8") == canonical_json_text(value) diff --git a/.agents/skills/plan-anvil/scripts/compare_review.py b/.agents/skills/plan-anvil/scripts/compare_review.py new file mode 100644 index 0000000..b06a1c3 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/compare_review.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_json, + cli_main, + discover_repo, + emit, + load_json, + repo_relative, + sha256_file, + utc_now, +) +from schema_validator import assert_valid_file +from transition_state import transition_state + + +def compare_review(planning: Path, run_root: Path) -> dict[str, Any]: + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + state = load_json(run / "state.json") + if state.get("status") != "BLIND_REVIEW_WRITTEN": + raise PlanAnvilError( + f"Comparison requires BLIND_REVIEW_WRITTEN, found {state.get('status')}", + code="INVALID_STATE_FOR_COMPARISON", + ) + + review_md = run / "reports/plan-review/blind-review.md" + review_json = run / "reports/plan-review/blind-review.json" + sidecar = load_json(review_json) + summary_path = run / "reports/validation/summary.json" + summary = load_json(summary_path) if summary_path.is_file() else {} + + reasons: list[str] = [] + if sha256_file(review_md) != sidecar.get("markdown_hash"): + reasons.append("Blind-review Markdown hash does not match its immutable sidecar.") + if sidecar.get("result") != "PASS": + reasons.append(f"Blind review result is {sidecar.get('result')}.") + if summary.get("result") != "PASS": + reasons.append("Deterministic validation is missing or failed.") + high_findings = [ + item for item in sidecar.get("findings", []) + if item.get("severity") in {"HIGH", "CRITICAL"} + ] + if high_findings: + reasons.append("Blind review contains high or critical findings.") + + result = "PASS" if not reasons else "FAIL" + comparison = { + "schema_version": "1.1.0", + "created_at": utc_now(), + "result": result, + "blind_review_hash": sha256_file(review_md), + "blind_review_sidecar_hash": sha256_file(review_json), + "deterministic_validation": "PASS" if summary.get("result") == "PASS" else ("FAIL" if summary else "MISSING"), + "reasons": reasons, + } + target = run / "reports/plan-review/comparison.json" + atomic_write_json(target, comparison, exclusive=True) + schema = Path(__file__).resolve().parent.parent / "schemas/comparison.schema.json" + assert_valid_file(target, schema) + + if result == "PASS": + transition_state( + run / "state.json", + expected_revision=state["revision"], + new_status="COMPARISON_VALID", + phase="COMMIT_PLANNING_ARTIFACTS", + next_action_type="COMMIT_PLAN", + next_action_target=repo_relative(repo, run), + hash_paths=[target], + ) + else: + transition_state( + run / "state.json", + expected_revision=state["revision"], + new_status="FAILED", + phase="REPORT_AND_STOP", + next_action_type="NONE", + next_action_target=None, + blocker="PLAN_VALIDATION_FAILED", + hash_paths=[target], + ) + return { + "ok": result == "PASS", + "result": result, + "comparison": repo_relative(repo, target), + "reasons": reasons, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Compare immutable blind review with deterministic PlanAnvil validation") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + args = parser.parse_args() + payload = compare_review(args.planning, args.run_root) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/create_planning_worktree.py b/.agents/skills/plan-anvil/scripts/create_planning_worktree.py new file mode 100644 index 0000000..5007c0f --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/create_planning_worktree.py @@ -0,0 +1,140 @@ +from __future__ import annotations + +import argparse +import tempfile +from pathlib import Path +from typing import Any + +from common import ( + PLAN_ID_RE, + PlanAnvilError, + cli_main, + compare_snapshot, + discover_repo, + emit, + git, + load_json, + make_run_id, + repo_relative, + require_external_path, + slugify, + source_snapshot, +) + + +def default_destination(source_repo: Path, plan_id: str, slug: str) -> Path: + source_repo = source_repo.resolve() + parent = source_repo.parent / f".{source_repo.name}-plananvil-worktrees" + return parent / f"{plan_id}-{slug}" + + +def create_planning_worktree( + source: Path, + *, + plan_id: str, + slug: str, + capability_report: dict[str, Any], + destination: Path | None = None, +) -> dict[str, Any]: + if not PLAN_ID_RE.fullmatch(plan_id): + raise PlanAnvilError(f"Invalid plan id: {plan_id}", code="INVALID_PLAN_ID") + slug = slugify(slug) + if capability_report.get("result") != "GIT_READY" or not capability_report.get("ok"): + raise PlanAnvilError("A successful complete Git capability report is required", code="GIT_NOT_READY") + + repo = discover_repo(source) + expected_root = Path(capability_report["repository_root"]).resolve() + if repo != expected_root: + raise PlanAnvilError("Capability report belongs to a different repository", code="CAPABILITY_REPOSITORY_MISMATCH") + + snapshot = capability_report.get("source_snapshot") + changed = compare_snapshot(repo, snapshot) + if changed: + raise PlanAnvilError( + f"Source changed after Git capability verification: {', '.join(changed)}", + code="SOURCE_CHANGED", + details=changed, + ) + + base_sha = snapshot["head"] + base_branch = capability_report.get("base_branch") or snapshot.get("branch") + if not base_branch: + raise PlanAnvilError("Base branch is unresolved", code="GIT_BASE_AMBIGUOUS") + + branch = f"pursue/plan/{plan_id}/{slug}" + existing = git(repo, "show-ref", "--verify", f"refs/heads/{branch}", check=False) + if existing.returncode == 0: + raise PlanAnvilError(f"Planning branch already exists: {branch}", code="PLANNING_BRANCH_EXISTS") + + dest = require_external_path( + repo, + destination or default_destination(repo, plan_id, slug), + code="PLANNING_WORKTREE_INSIDE_WORKTREE", + ) + if dest.exists(): + raise PlanAnvilError(f"Planning worktree path already exists: {dest}", code="PLANNING_WORKTREE_EXISTS") + dest.parent.mkdir(parents=True, exist_ok=True) + + add = git(repo, "worktree", "add", "-b", branch, str(dest), base_sha, check=False, timeout=180) + if add.returncode != 0: + raise PlanAnvilError( + "Could not create planning branch and linked worktree", + code="PLANNING_WORKTREE_CREATE_FAILED", + details=add.stderr or add.stdout, + ) + + try: + head = git(dest, "rev-parse", "HEAD").stdout.strip() + current_branch = git(dest, "symbolic-ref", "--short", "HEAD").stdout.strip() + if head != base_sha or current_branch != branch: + raise PlanAnvilError("Planning worktree identity verification failed", code="PLANNING_WORKTREE_MISMATCH") + + changed = compare_snapshot(repo, snapshot) + if changed: + raise PlanAnvilError( + f"Source changed while creating planning worktree: {', '.join(changed)}", + code="SOURCE_CHANGED", + details=changed, + ) + except Exception: + git(repo, "worktree", "remove", "--force", str(dest), check=False, timeout=180) + git(repo, "branch", "-D", branch, check=False) + raise + + run_id = make_run_id(plan_id, slug) + return { + "ok": True, + "result": "PLANNING_WORKTREE_READY", + "plan_id": plan_id, + "run_id": run_id, + "slug": slug, + "source_repository": str(repo), + "planning_worktree": str(dest), + "planning_branch": branch, + "base_branch": base_branch, + "base_sha": base_sha, + "source_snapshot": snapshot, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Create the isolated PlanAnvil planning branch and worktree") + parser.add_argument("--source", type=Path, default=Path.cwd()) + parser.add_argument("--plan-id", required=True) + parser.add_argument("--slug", required=True) + parser.add_argument("--capability-report", type=Path, required=True) + parser.add_argument("--destination", type=Path) + args = parser.parse_args() + report = load_json(args.capability_report) + payload = create_planning_worktree( + args.source, + plan_id=args.plan_id, + slug=args.slug, + capability_report=report, + destination=args.destination, + ) + return emit(payload) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/map_instructions.py b/.agents/skills/plan-anvil/scripts/map_instructions.py new file mode 100644 index 0000000..2a58f67 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/map_instructions.py @@ -0,0 +1,267 @@ +from __future__ import annotations + +import argparse +import os +import re +import tomllib +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + SCHEMA_VERSION, + atomic_write_json, + cli_main, + discover_repo, + emit, + ensure_inside, + load_json, + repo_relative, + sha256_bytes, + utc_now, +) +from schema_validator import assert_valid_file +from transition_state import transition_state + + +SAFETY_TERMS = re.compile( + r"(?i)\b(?:must not|never|forbidden|secret|credential|production|deploy|destructive|irreversible|security|privacy|legal|permission|protected branch|data loss)\b" +) + + +def _load_codex_instruction_config(repo: Path) -> tuple[list[str], int]: + fallback: list[str] = [] + max_bytes = 32768 + candidates: list[Path] = [] + codex_home = Path(os.environ.get("CODEX_HOME", Path.home() / ".codex")) + candidates.append(codex_home / "config.toml") + candidates.append(repo / ".codex/config.toml") + for path in candidates: + if not path.is_file(): + continue + try: + data = tomllib.loads(path.read_text(encoding="utf-8")) + except (OSError, tomllib.TOMLDecodeError): + continue + names = data.get("project_doc_fallback_filenames") + if isinstance(names, list) and all(isinstance(item, str) and item for item in names): + fallback = list(dict.fromkeys(names)) + value = data.get("project_doc_max_bytes") + if isinstance(value, int) and value > 0: + max_bytes = value + return fallback, max_bytes + + +def _scope_directories(repo: Path, affected: str) -> list[Path]: + raw = Path(affected) + candidate = raw if raw.is_absolute() else repo / raw + candidate = ensure_inside(repo, candidate) + target_dir = candidate if candidate.is_dir() else candidate.parent + dirs: list[Path] = [] + current = target_dir + while True: + dirs.append(current) + if current == repo: + break + current = current.parent + dirs.reverse() + return dirs + + +def _selected_instruction(directory: Path, fallback: list[str]) -> Path | None: + for name in ["AGENTS.override.md", "AGENTS.md", *fallback]: + path = directory / name + if path.is_file() and path.stat().st_size > 0: + return path + return None + + +def map_instructions( + planning: Path, + *, + affected_paths: list[str], + output: Path, + fallback_filenames: list[str] | None = None, + automatic_byte_limit: int | None = None, + conflicts_file: Path | None = None, +) -> dict[str, Any]: + repo = discover_repo(planning) + if not affected_paths: + affected_paths = ["."] + configured_fallback, configured_limit = _load_codex_instruction_config(repo) + fallback = list(dict.fromkeys(fallback_filenames if fallback_filenames is not None else configured_fallback)) + byte_limit = automatic_byte_limit or configured_limit + + normalized_affected: list[str] = [] + selections: dict[str, dict[str, Any]] = {} + order: list[str] = [] + + for affected in affected_paths: + candidate = Path(affected) + absolute = candidate if candidate.is_absolute() else repo / candidate + absolute = ensure_inside(repo, absolute) + relative = repo_relative(repo, absolute) + normalized_affected.append(relative) + for precedence, directory in enumerate(_scope_directories(repo, relative)): + selected = _selected_instruction(directory, fallback) + if selected is None: + continue + key = selected.resolve().as_posix() + if key not in selections: + data = selected.read_bytes() + try: + text = data.decode("utf-8") + except UnicodeDecodeError as exc: + raise PlanAnvilError( + f"Instruction file is not UTF-8: {repo_relative(repo, selected)}", + code="INSTRUCTION_NOT_UTF8", + ) from exc + safety_rules = [] + for number, line in enumerate(text.splitlines(), start=1): + if SAFETY_TERMS.search(line): + safety_rules.append(f"L{number} {sha256_bytes(line.encode('utf-8'))}") + selections[key] = { + "path": repo_relative(repo, selected), + "sha256": sha256_bytes(data), + "bytes": len(data), + "full_read": True, + "scope": repo_relative(repo, directory), + "precedence": precedence, + "affected_paths": [], + "truncation_risk": False, + "safety_critical_rules": safety_rules, + } + order.append(key) + entry = selections[key] + entry["precedence"] = max(entry["precedence"], precedence) + if relative not in entry["affected_paths"]: + entry["affected_paths"].append(relative) + + cumulative = 0 + files: list[dict[str, Any]] = [] + for key in order: + entry = selections[key] + cumulative += entry["bytes"] + entry["truncation_risk"] = cumulative > byte_limit + entry["affected_paths"].sort() + files.append(entry) + + conflicts: list[dict[str, Any]] = [] + if conflicts_file is not None: + raw_conflicts = load_json(conflicts_file) + if not isinstance(raw_conflicts, list): + raise PlanAnvilError("Instruction conflicts file must contain an array", code="INVALID_INSTRUCTION_CONFLICTS") + known_paths = {entry["path"] for entry in files} + for item in raw_conflicts: + if not isinstance(item, dict): + raise PlanAnvilError("Instruction conflict must be an object", code="INVALID_INSTRUCTION_CONFLICTS") + paths = item.get("paths") + critical = item.get("critical") + resolution = item.get("resolution") + if ( + not isinstance(paths, list) + or len(paths) < 2 + or any(not isinstance(path, str) or path not in known_paths for path in paths) + or not isinstance(critical, bool) + or (resolution is not None and not isinstance(resolution, str)) + or isinstance(resolution, str) and not resolution.strip() + ): + raise PlanAnvilError("Invalid instruction conflict entry", code="INVALID_INSTRUCTION_CONFLICTS", details=item) + conflicts.append({"paths": sorted(set(paths)), "critical": critical, "resolution": resolution.strip() if isinstance(resolution, str) else None}) + + payload = { + "schema_version": SCHEMA_VERSION, + "generated_at": utc_now(), + "affected_paths": sorted(set(normalized_affected)), + "fallback_filenames": fallback, + "automatic_byte_limit": byte_limit, + "files": files, + "conflicts": conflicts, + } + + output = output if output.is_absolute() else repo / output + output = ensure_inside(repo, output) + run_root = output.parent.parent if output.parent.name == "evidence" else None + scaffolded = bool(run_root and (run_root / "state.json").is_file() and (run_root / "compliance.json").is_file()) + if scaffolded: + state = load_json(run_root / "state.json") + if state.get("status") != "PROFILE_READY": + raise PlanAnvilError( + f"Instruction mapping requires PROFILE_READY, found {state.get('status')}", + code="INVALID_STATE_FOR_INSTRUCTION_MAP", + ) + atomic_write_json(output, payload, exclusive=scaffolded) + schema = Path(__file__).resolve().parent.parent / "schemas/instruction-map.schema.json" + assert_valid_file(output, schema) + + # When the map belongs to a scaffolded run, advance canonical state and + # record the capability without relying on conversation state. + if scaffolded: + compliance_path = run_root / "compliance.json" + compliance = load_json(compliance_path) + for capability in compliance.get("capabilities", []): + if capability.get("id") == "CAP-INSTRUCTION-MAP": + capability["status"] = "VERIFIED" + capability["evidence"] = [repo_relative(repo, output)] + compliance["verified_at"] = utc_now() + atomic_write_json(compliance_path, compliance) + state_path = run_root / "state.json" + unresolved_critical = [item for item in conflicts if item["critical"] and item["resolution"] is None] + if unresolved_critical: + transition_state( + state_path, + expected_revision=state["revision"], + new_status="BLOCKED", + phase="REPORT_AND_STOP", + next_action_type="NONE", + next_action_target=None, + blocker="BLOCKED_BY_INSTRUCTION_CONFLICT", + hash_paths=[output], + ) + else: + transition_state( + state_path, + expected_revision=state["revision"], + new_status="INSTRUCTION_MAP_READY", + phase="ANALYZE_GOAL", + next_action_type="ANALYZE_GOAL", + next_action_target="evidence/analysis.json", + hash_paths=[output], + ) + + blocked = any(item["critical"] and item["resolution"] is None for item in conflicts) + return { + "ok": not blocked, + "result": "BLOCKED_BY_INSTRUCTION_CONFLICT" if blocked else "INSTRUCTION_MAP_READY", + "output": repo_relative(repo, output), + "files": len(files), + "truncation_risk": any(item["truncation_risk"] for item in files), + "conflicts": conflicts, + "blocked": blocked, + "fallback_filenames": fallback, + "automatic_byte_limit": byte_limit, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Map complete applicable Codex project instruction files") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--affected-path", action="append", dest="affected_paths", default=[]) + parser.add_argument("--fallback-name", action="append", dest="fallback_names") + parser.add_argument("--automatic-byte-limit", type=int) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--conflicts-file", type=Path) + args = parser.parse_args() + payload = map_instructions( + args.planning, + affected_paths=args.affected_paths, + output=args.output, + fallback_filenames=args.fallback_names, + automatic_byte_limit=args.automatic_byte_limit, + conflicts_file=args.conflicts_file, + ) + return emit(payload, exit_code=2 if payload.get("blocked") else 0) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/plan_anvil.py b/.agents/skills/plan-anvil/scripts/plan_anvil.py new file mode 100644 index 0000000..d0c131e --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/plan_anvil.py @@ -0,0 +1,150 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import cli_main, emit, load_json, make_plan_id, make_run_id, slugify +from create_planning_worktree import create_planning_worktree +from preflight import preflight +from profile_repository import profile_repository +from scaffold_run import scaffold_run +from test_git_capabilities import probe_git_capabilities +from validate_all import validate_all + + +def start( + source: Path, + goal: str, + destination: Path | None = None, + *, + codex_version: str = "unknown", + model: str = "unknown", + permission_mode: str = "unknown", + project_trust: str = "UNKNOWN", + hook_mode: str = "HOOKS_UNAVAILABLE", +) -> dict[str, Any]: + goal = goal.strip() + slug = slugify(goal) + plan_id = make_plan_id() + probe_run_id = make_run_id(plan_id, slug) + + source_check = preflight(source) + if not source_check["ok"]: + return source_check + + capability = probe_git_capabilities(source, probe_run_id) + if not capability["ok"]: + return capability + + worktree = create_planning_worktree( + source, + plan_id=plan_id, + slug=slug, + capability_report=capability, + destination=destination, + ) + planning = Path(worktree["planning_worktree"]) + profile = profile_repository(planning, source) + scaffold = scaffold_run( + planning, + source, + plan_id=plan_id, + run_id=worktree["run_id"], + slug=slug, + goal=goal, + base_branch=worktree["base_branch"], + base_sha=worktree["base_sha"], + capability_report=capability, + codex_version=codex_version, + model=model, + permission_mode=permission_mode, + project_trust=project_trust, + hook_mode=hook_mode, + ) + return { + "ok": True, + "result": "PROFILE_READY", + "plan_id": plan_id, + "run_id": worktree["run_id"], + "planning_branch": worktree["planning_branch"], + "planning_worktree": worktree["planning_worktree"], + "run_root": scaffold["run_root"], + "plan": scaffold["plan"], + "next_action": { + "type": "MAP_INSTRUCTIONS", + "instruction": "Determine affected paths, run map_instructions.py for all of them, then analyze the goal and replace every plan placeholder.", + }, + "implementation_executed": False, + } + + +def status(planning: Path, run_root: Path) -> dict[str, Any]: + run = run_root if run_root.is_absolute() else planning / run_root + return { + "ok": True, + "manifest": load_json(run / "manifest.json"), + "state": load_json(run / "state.json"), + "compliance": load_json(run / "compliance.json"), + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="PlanAnvil deterministic controller") + sub = parser.add_subparsers(dest="command", required=True) + + start_parser = sub.add_parser("start", help="Preflight, probe Git, isolate planning worktree, profile, and scaffold") + start_parser.add_argument("--source", type=Path, default=Path.cwd()) + start_goal = start_parser.add_mutually_exclusive_group(required=True) + start_goal.add_argument("--goal") + start_goal.add_argument("--goal-file", type=Path) + start_parser.add_argument("--destination", type=Path) + start_parser.add_argument("--codex-version", default="unknown") + start_parser.add_argument("--model", default="unknown") + start_parser.add_argument("--permission-mode", default="unknown") + start_parser.add_argument("--project-trust", choices=["TRUSTED", "UNTRUSTED", "UNKNOWN"], default="UNKNOWN") + start_parser.add_argument( + "--hook-mode", + choices=["HOOKS_TRUSTED", "HOOKS_DISABLED", "HOOKS_UNTRUSTED", "HOOKS_UNAVAILABLE"], + default="HOOKS_UNAVAILABLE", + ) + + validate_parser = sub.add_parser("validate", help="Run deterministic validation") + validate_parser.add_argument("--planning", type=Path, default=Path.cwd()) + validate_parser.add_argument("--run-root", type=Path, required=True) + validate_parser.add_argument("--source", type=Path) + validate_parser.add_argument("--phase", choices=["pre-review", "final"], default="pre-review") + validate_parser.add_argument("--no-advance-state", action="store_true") + + status_parser = sub.add_parser("status", help="Read canonical run status") + status_parser.add_argument("--planning", type=Path, default=Path.cwd()) + status_parser.add_argument("--run-root", type=Path, required=True) + + args = parser.parse_args() + if args.command == "start": + goal = args.goal if args.goal is not None else args.goal_file.read_text(encoding="utf-8") + payload = start( + args.source, + goal, + args.destination, + codex_version=args.codex_version, + model=args.model, + permission_mode=args.permission_mode, + project_trust=args.project_trust, + hook_mode=args.hook_mode, + ) + return emit(payload, exit_code=0 if payload.get("ok") else 2) + if args.command == "validate": + payload = validate_all( + args.planning, + args.run_root, + source=args.source, + phase=args.phase, + advance_state=not args.no_advance_state, + ) + return emit(payload, exit_code=0 if payload.get("ok") else 2) + return emit(status(args.planning, args.run_root)) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/preflight.py b/.agents/skills/plan-anvil/scripts/preflight.py new file mode 100644 index 0000000..218b07b --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/preflight.py @@ -0,0 +1,112 @@ +from __future__ import annotations + +import argparse +import shutil +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + add_source_argument, + cli_main, + detect_git_operation, + discover_repo, + emit, + git, + source_snapshot, +) + + +def resolve_base(repo: Path) -> tuple[str | None, str | None]: + attached = git(repo, "symbolic-ref", "--quiet", "--short", "HEAD", check=False) + if attached.returncode == 0: + branch = attached.stdout.strip() + return branch, None + candidates = [ + line.strip() + for line in git(repo, "for-each-ref", "--format=%(refname:short)", "--contains=HEAD", "refs/heads").stdout.splitlines() + if line.strip() + ] + if len(candidates) == 1: + return candidates[0], None + return None, "GIT_BASE_AMBIGUOUS" + + +def plan_status_for(result: str) -> str | None: + if result == "SOURCE_PREFLIGHT_PASSED": + return None + if result in {"GIT_DIRTY", "GIT_OPERATION_IN_PROGRESS", "GIT_BASE_AMBIGUOUS"}: + return "BLOCKED_BY_GIT_STATE" + if result in {"GIT_READ_ONLY", "GIT_WRITE_RESTRICTED"}: + return "BLOCKED_BY_GIT_PERMISSIONS" + return "BLOCKED_BY_RUNTIME_PREREQUISITE" + + +def preflight(source: Path) -> dict[str, Any]: + if shutil.which("git") is None: + result = "GIT_UNAVAILABLE" + return {"ok": False, "result": result, "plan_status": plan_status_for(result)} + + try: + repo = discover_repo(source) + except PlanAnvilError: + result = "NOT_A_GIT_REPOSITORY" + return {"ok": False, "result": result, "plan_status": plan_status_for(result)} + + head_result = git(repo, "rev-parse", "--verify", "HEAD", check=False) + if head_result.returncode != 0: + result = "GIT_BASE_AMBIGUOUS" + return { + "ok": False, + "result": result, + "plan_status": plan_status_for(result), + "repository_root": str(repo), + "diagnostic": head_result.stderr.strip(), + } + + status_raw = git(repo, "status", "--porcelain=v1", "-z", "--untracked-files=all").stdout + conflicts = [ + item for item in git(repo, "diff", "--name-only", "--diff-filter=U", "-z").stdout.split("\0") if item + ] + operation = detect_git_operation(repo) + base_branch, base_error = resolve_base(repo) + worktrees = git(repo, "worktree", "list", "--porcelain", check=False) + + if status_raw or conflicts: + result = "GIT_DIRTY" + elif operation: + result = "GIT_OPERATION_IN_PROGRESS" + elif base_error: + result = base_error + elif worktrees.returncode != 0: + result = "GIT_WORKTREE_UNSUPPORTED" + else: + result = "SOURCE_PREFLIGHT_PASSED" + + snapshot = source_snapshot(repo) + return { + "ok": result == "SOURCE_PREFLIGHT_PASSED", + "result": result, + "plan_status": plan_status_for(result), + "repository_root": str(repo), + "head": snapshot["head"], + "branch": snapshot["branch"], + "base_branch": base_branch, + "clean": not bool(status_raw), + "conflicts": conflicts, + "operation": operation, + "worktrees": worktrees.stdout if worktrees.returncode == 0 else None, + "source_snapshot": snapshot, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Read-only PlanAnvil source preflight") + add_source_argument(parser) + args = parser.parse_args() + payload = preflight(args.source) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/prepare_review_bundle.py b/.agents/skills/plan-anvil/scripts/prepare_review_bundle.py new file mode 100644 index 0000000..b7eff5f --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/prepare_review_bundle.py @@ -0,0 +1,127 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_json, + atomic_write_text, + cli_main, + discover_repo, + emit, + load_json, + repo_relative, + sha256_file, + utc_now, +) + + +def review_candidates(repo: Path, run: Path) -> list[Path]: + return [ + repo / ".pursue/SYSTEM_PROFILE.md", + run / "evidence/original-goal.md", + run / "evidence/git-capability.json", + run / "evidence/lifecycle.json", + run / "evidence/instruction-map.json", + run / "evidence/analysis.md", + run / "evidence/analysis.json", + run / "PLAN.md", + run / "traceability.json", + run / "reports/validation/summary.json", + *sorted((run / "stages").glob("STAGE-*.md")), + *sorted((run / "risks").glob("RISK-*.json")), + ] + + +def review_file_entries(repo: Path, run: Path) -> list[dict[str, str]]: + candidates = review_candidates(repo, run) + missing = [repo_relative(repo, path) for path in candidates if not path.is_file()] + if missing: + raise PlanAnvilError("Review bundle inputs are missing", code="REVIEW_INPUT_MISSING", details=missing) + return [ + { + "path": repo_relative(repo, path), + "sha256": sha256_file(path), + "role": ( + "goal" if path.name == "original-goal.md" + else "git-capability" if path.name == "git-capability.json" + else "lifecycle" if path.name == "lifecycle.json" + else "profile" if path.name == "SYSTEM_PROFILE.md" + else "instruction-map" if path.name == "instruction-map.json" + else "analysis" if path.name in {"analysis.md", "analysis.json"} + else "plan" if path.name == "PLAN.md" + else "traceability" if path.name == "traceability.json" + else "deterministic-validation" if path.name == "summary.json" + else "stage" if path.parent.name == "stages" + else "risk" + ), + } + for path in candidates + ] + +def prepare_review_bundle(planning: Path, run_root: Path) -> dict[str, Any]: + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + state = load_json(run / "state.json") + if state.get("status") != "DETERMINISTICALLY_VALID": + raise PlanAnvilError( + f"Blind review requires DETERMINISTICALLY_VALID, found {state.get('status')}", + code="INVALID_STATE_FOR_REVIEW", + ) + + summary = load_json(run / "reports/validation/summary.json") + if summary.get("result") != "PASS": + raise PlanAnvilError("Deterministic validation did not pass", code="VALIDATION_NOT_PASSED") + + files = review_file_entries(repo, run) + bundle = { + "schema_version": "1.1.0", + "created_at": utc_now(), + "purpose": "BLIND_PLAN_REVIEW", + "excludes": ["planner reasoning", "self-review", "conversation transcript", "local-state.json", "SYSTEM_PROFILE.local.md"], + "files": files, + } + bundle_path = run / "reports/plan-review/review-bundle.json" + atomic_write_json(bundle_path, bundle, exclusive=True) + + prompt = """# Blind Plan Review Brief + +Review only the files listed in `review-bundle.json`. Do not request or use planner reasoning, self-review, conversation history, local-state.json, or the local profile. + +Assess: + +- goal coverage and definition of done; +- unsupported assumptions and critical unknowns; +- instruction compliance; +- stage atomicity and stable identifiers; +- requirement, criterion, risk, control, test, and evidence traceability; +- test strategy and independent verification; +- Git/worktree ownership and approval gates; +- stateful migration, live-switch, rollback, and recovery safety; +- generator/executor separation; +- placeholders, contradictions, and unverifiable commands. + +Return a Markdown report using the blind-review template and a structured findings JSON array. Use `PASS` only when no high or critical defect blocks readiness. Do not modify any plan artifact. +""" + atomic_write_text(run / "reports/plan-review/review-prompt.md", prompt, exclusive=True) + return { + "ok": True, + "result": "REVIEW_BUNDLE_READY", + "bundle": repo_relative(repo, bundle_path), + "prompt": repo_relative(repo, run / "reports/plan-review/review-prompt.md"), + "files": len(files), + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Create the immutable-input PlanAnvil blind-review bundle") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + args = parser.parse_args() + return emit(prepare_review_bundle(args.planning, args.run_root)) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/profile_repository.py b/.agents/skills/plan-anvil/scripts/profile_repository.py new file mode 100644 index 0000000..1c11243 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/profile_repository.py @@ -0,0 +1,283 @@ +from __future__ import annotations + +import argparse +import json +from collections import Counter +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + append_ignore_rules, + atomic_write_text, + cli_main, + discover_repo, + emit, + git, + repository_fingerprint, + sha256_file, + utc_now, +) + +EXTENSION_NAMES = { + ".py": "Python", + ".php": "PHP", + ".js": "JavaScript", + ".mjs": "JavaScript", + ".cjs": "JavaScript", + ".ts": "TypeScript", + ".tsx": "TypeScript/TSX", + ".jsx": "JavaScript/JSX", + ".java": "Java", + ".go": "Go", + ".rs": "Rust", + ".rb": "Ruby", + ".cs": "C#", + ".cpp": "C++", + ".c": "C", + ".h": "C/C++ header", + ".swift": "Swift", + ".kt": "Kotlin", + ".sql": "SQL", + ".sh": "Shell", + ".ps1": "PowerShell", + ".svg": "SVG", +} + +MANIFEST_HINTS = { + "pyproject.toml": ("Python", "python -m unittest discover"), + "requirements.txt": ("Python", "python -m unittest discover"), + "package.json": ("Node.js", None), + "composer.json": ("PHP", "composer test"), + "go.mod": ("Go", "go test ./..."), + "Cargo.toml": ("Rust", "cargo test"), + "pom.xml": ("Java/Maven", "mvn test"), + "build.gradle": ("Java/Gradle", "./gradlew test"), + "build.gradle.kts": ("Kotlin/Gradle", "./gradlew test"), + "Gemfile": ("Ruby", "bundle exec rake test"), +} + +FRESHNESS_NAMES = { + "AGENTS.md", "AGENTS.override.md", "package.json", "package-lock.json", "pnpm-lock.yaml", + "yarn.lock", "composer.json", "composer.lock", "pyproject.toml", "requirements.txt", + "poetry.lock", "uv.lock", "go.mod", "go.sum", "Cargo.toml", "Cargo.lock", "pom.xml", + "build.gradle", "build.gradle.kts", "Gemfile", "Gemfile.lock", "Dockerfile", + "docker-compose.yml", "docker-compose.yaml", "Makefile", "Taskfile.yml", "Taskfile.yaml", + "phpunit.xml", "phpunit.xml.dist", "pytest.ini", "tox.ini", "mypy.ini", "ruff.toml", +} +FRESHNESS_PARTS = { + ".github", ".gitlab", ".codex", "migrations", "migration", "deploy", "deployment", + "helm", "k8s", "kubernetes", "terraform", "ansible", "ci", "scripts", +} + + +def _freshness_files(repo: Path, files: list[Path]) -> list[Path]: + selected: list[Path] = [] + for path in files: + rel = path.relative_to(repo) + lower_parts = {part.lower() for part in rel.parts} + if ( + path.name in FRESHNESS_NAMES + or path.name.startswith("AGENTS.") + or bool(lower_parts & FRESHNESS_PARTS) + or any(token in path.name.lower() for token in ("test", "build", "deploy", "migration", "schema")) + ): + selected.append(path) + return sorted(set(selected), key=lambda item: item.relative_to(repo).as_posix())[:250] + + +def _tracked_files(repo: Path) -> list[Path]: + raw = git(repo, "ls-files", "-z").stdout + return [repo / item for item in raw.split("\0") if item] + + +def _json_scripts(path: Path) -> list[str]: + try: + data = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError): + return [] + scripts = data.get("scripts") + if not isinstance(scripts, dict): + return [] + return [f"{name}: {value}" for name, value in sorted(scripts.items()) if isinstance(value, str)] + + +def profile_repository(planning: Path, source: Path) -> dict[str, Any]: + repo = discover_repo(planning) + source_repo = discover_repo(source) + branch = git(repo, "symbolic-ref", "--quiet", "--short", "HEAD", check=False).stdout.strip() + if not branch.startswith("pursue/plan/"): + raise PlanAnvilError("Repository is not on a PlanAnvil planning branch", code="NOT_PLANNING_WORKTREE") + + head = git(repo, "rev-parse", "HEAD").stdout.strip() + files = _tracked_files(repo) + extension_counts = Counter(path.suffix.lower() for path in files if path.suffix) + languages = [ + (EXTENSION_NAMES[ext], count) + for ext, count in extension_counts.most_common() + if ext in EXTENSION_NAMES + ] + manifests: list[str] = [] + command_lines: list[str] = [] + runtimes: list[str] = [] + for filename, (runtime, default_command) in MANIFEST_HINTS.items(): + path = repo / filename + if path.exists(): + manifests.append(filename) + runtimes.append(runtime) + if default_command: + command_lines.append(f"- `{default_command}` — inferred from `{filename}`; verify before execution") + if filename in {"package.json", "composer.json"}: + for script in _json_scripts(path): + command_lines.append(f"- `{script}` — declared in `{filename}`") + + top_level = sorted({path.relative_to(repo).parts[0] for path in files if path.relative_to(repo).parts}) + ci = sorted( + path.relative_to(repo).as_posix() + for path in files + if path.relative_to(repo).as_posix().startswith((".github/workflows/", ".gitlab-ci", "azure-pipelines")) + ) + freshness_files = _freshness_files(repo, files) + freshness_lines = [ + f"- `{path.relative_to(repo).as_posix()}`: `{sha256_file(path)}`" + for path in freshness_files + if path.is_file() + ] + + structure = "\n".join(f"- `{item}`" for item in top_level[:80]) or "- No tracked files detected." + language_text = "\n".join(f"- {name}: {count} tracked files" for name, count in languages[:20]) or "- UNKNOWN" + runtime_text = "\n".join(f"- {name}" for name in sorted(set(runtimes))) or "- UNKNOWN" + commands = "\n".join(command_lines) or "- UNKNOWN — derive from repository instructions and manifests before planning acceptance." + ci_text = "\n".join(f"- `{item}`" for item in ci) or "- No tracked CI definition detected." + generated = utc_now() + fingerprint = repository_fingerprint(repo) + + profile = f"""# PlanAnvil Repository Profile + +- Profile status: `VALID_WITH_UNKNOWNS` +- Generated at: `{generated}` +- Repository fingerprint: `{fingerprint}` +- Evidence base SHA: `{head}` + +## Repository structure and architecture + +Tracked top-level entries: + +{structure} + +Architecture is not inferred beyond repository evidence. The plan must identify concrete components and flows for the requested goal. + +## Languages, runtimes, and dependency managers + +Languages: + +{language_text} + +Runtime/dependency indicators: + +{runtime_text} + +Tracked manifests: {", ".join(f"`{item}`" for item in manifests) if manifests else "none detected"}. + +## Build, test, lint, and static-analysis commands + +{commands} + +Commands marked inferred require confirmation from project instructions or a non-mutating discovery step before use. + +## Git conventions and quality gates + +- Current planning branch: `{branch}` +- Evidence SHA: `{head}` +- Source worktree must remain unchanged. +- Product changes are forbidden in this planning worktree. +- Commit signing and repository hooks must remain enabled according to repository policy. +- CI definitions: + +{ci_text} + +## Project instruction map + +Pending explicit instruction mapping. The run-specific instruction map is authoritative. + +## Deployment, state, and rollback rules + +- Deployment behavior: `UNKNOWN` +- Push-trigger implications: stored only in the ignored local profile when discovered. +- Stateful changes require recovery points, compatibility, resumability, integrity checks, observation, and separate contraction. +- Live switching and irreversible operations require explicit user approval. + +## Risk and activation policy + +- LOW: isolated behavior with focused evidence. +- MEDIUM: cross-component or public behavior with bounded rollback. +- HIGH: stateful, destructive, security-sensitive, permission-sensitive, or live-system work. +- Critical unknowns block readiness. + +## Evidence and freshness + +- Profile facts are `VERIFIED`, `INFERRED`, or `UNKNOWN`. +- Freshness anchor: tracked repository state at `{head}`. +- Revalidate when any hashed instruction, dependency, build/test, deployment, migration, or PlanAnvil configuration file changes. +- Hashed evidence files: + +{chr(10).join(freshness_lines) if freshness_lines else "- No freshness-sensitive tracked file detected."} +""" + local_profile = f"""# PlanAnvil Local Profile + +This ignored file contains non-secret machine-specific locators. Never commit it. + +- Source worktree: `{source_repo.resolve()}` +- Planning worktree: `{repo.resolve()}` +- Generated at: `{generated}` + +## Local commands and services + +- UNKNOWN — discover only when required by the plan. +- Do not copy credentials, `.env` values, tokens, keys, cookies, or certificates here. + +## Health checks, switching, and rollback + +- UNKNOWN — a critical live-operation plan must resolve these before readiness. + +## Permission and push-trigger implications + +- Git capability probe: required before planning isolation. +- Push-trigger implications: UNKNOWN. PlanAnvil does not push by default. +""" + + pursue = repo / ".pursue" + pursue.mkdir(exist_ok=True) + atomic_write_text(pursue / "SYSTEM_PROFILE.md", profile) + atomic_write_text(pursue / "SYSTEM_PROFILE.local.md", local_profile) + ignore_changed = append_ignore_rules( + repo, + [ + ".pursue/SYSTEM_PROFILE.local.md", + ".pursue/runs/*/local-state.json", + ".pursue/runs/*/.generation-lock", + ".pursue/runs/*/.execution-lock", + ], + ) + return { + "ok": True, + "result": "PROFILE_READY", + "repository_profile": ".pursue/SYSTEM_PROFILE.md", + "local_profile": ".pursue/SYSTEM_PROFILE.local.md", + "profile_status": "VALID_WITH_UNKNOWNS", + "ignore_rules_changed": ignore_changed, + "fingerprint": fingerprint, + "evidence_sha": head, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Create PlanAnvil repository and local profiles") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--source", type=Path, required=True) + args = parser.parse_args() + return emit(profile_repository(args.planning, args.source)) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/record_analysis.py b/.agents/skills/plan-anvil/scripts/record_analysis.py new file mode 100644 index 0000000..5e6a2a6 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/record_analysis.py @@ -0,0 +1,198 @@ +from __future__ import annotations + +import argparse +import re +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + SCHEMA_VERSION, + atomic_write_json, + atomic_write_text, + canonical_json_text, + cli_main, + discover_repo, + emit, + ensure_inside, + load_json, + privacy_findings, + repo_relative, + sha256_file, + sha256_text, + utc_now, +) +from schema_validator import assert_valid_file, validate +from transition_state import transition_state + + +CLASSIFICATIONS = { + "ISOLATED", "CROSS_COMPONENT", "STATEFUL", "PUBLIC_API", + "SECURITY", "LIVE_OPERATION", "DOCUMENTATION", +} +RISKS = {"LOW", "MEDIUM", "HIGH"} +CONFIDENCE = {"VERIFIED", "USER_CONFIRMED", "INFERRED"} + + +def _relative_existing(repo: Path, value: str, *, code: str) -> str: + candidate = ensure_inside(repo, repo / value) + if not candidate.exists(): + raise PlanAnvilError(f"Evidence path does not exist: {value}", code=code) + return repo_relative(repo, candidate) + + +def record_analysis( + planning: Path, + run_root: Path, + *, + analysis_markdown: Path, + analysis_data: Path, +) -> dict[str, Any]: + repo = discover_repo(planning) + run = ensure_inside(repo, run_root if run_root.is_absolute() else repo / run_root) + state_path = run / "state.json" + state = load_json(state_path) + if state.get("status") != "INSTRUCTION_MAP_READY": + raise PlanAnvilError( + f"Analysis requires INSTRUCTION_MAP_READY, found {state.get('status')}", + code="INVALID_STATE_FOR_ANALYSIS", + ) + + markdown = analysis_markdown.read_text(encoding="utf-8").rstrip() + "\n" + if not markdown.strip(): + raise PlanAnvilError("Analysis Markdown is empty", code="EMPTY_ANALYSIS") + if re.search(r"\{\{[^}]+\}\}|\b(?:TODO|TBD)\b", markdown, re.IGNORECASE): + raise PlanAnvilError("Analysis contains placeholders", code="ANALYSIS_PLACEHOLDER") + findings = privacy_findings(Path("evidence/analysis.md"), markdown) + if findings: + raise PlanAnvilError("Analysis contains private or secret data", code="ANALYSIS_PRIVACY", details=findings) + + raw = load_json(analysis_data) + if not isinstance(raw, dict): + raise PlanAnvilError("Analysis data must be a JSON object", code="INVALID_ANALYSIS_DATA") + allowed = {"classification", "risk", "affected_paths", "evidence", "assumptions", "unknowns"} + unexpected = sorted(set(raw) - allowed) + if unexpected: + raise PlanAnvilError("Analysis data has unexpected fields", code="INVALID_ANALYSIS_DATA", details=unexpected) + if raw.get("classification") not in CLASSIFICATIONS or raw.get("risk") not in RISKS: + raise PlanAnvilError("Invalid analysis classification or risk", code="INVALID_ANALYSIS_DATA") + + instruction_map = load_json(run / "evidence/instruction-map.json") + mapped_paths = set(instruction_map.get("affected_paths", [])) + affected = [] + for value in raw.get("affected_paths", []): + if not isinstance(value, str): + raise PlanAnvilError("Affected paths must be strings", code="INVALID_ANALYSIS_DATA") + rel = repo_relative(repo, ensure_inside(repo, repo / value)) + if rel not in mapped_paths: + raise PlanAnvilError( + f"Affected path is not covered by the instruction map: {rel}", + code="UNMAPPED_AFFECTED_PATH", + ) + affected.append(rel) + if not affected: + raise PlanAnvilError("At least one affected path is required", code="INVALID_ANALYSIS_DATA") + + evidence = [_relative_existing(repo, item, code="ANALYSIS_EVIDENCE_MISSING") for item in raw.get("evidence", [])] + assumptions = raw.get("assumptions", []) + unknowns = raw.get("unknowns", []) + if not isinstance(assumptions, list) or not isinstance(unknowns, list): + raise PlanAnvilError("Assumptions and unknowns must be arrays", code="INVALID_ANALYSIS_DATA") + for item in assumptions: + if set(item) != {"text", "confidence", "evidence"} if isinstance(item, dict) else True: + raise PlanAnvilError("Invalid assumption fields", code="INVALID_ANALYSIS_DATA", details=item) + if item.get("confidence") not in CONFIDENCE or not str(item.get("text", "")).strip(): + raise PlanAnvilError("Invalid assumption", code="INVALID_ANALYSIS_DATA", details=item) + item_evidence = item.get("evidence", []) + if not isinstance(item_evidence, list): + raise PlanAnvilError("Assumption evidence must be an array", code="INVALID_ANALYSIS_DATA") + item["evidence"] = [_relative_existing(repo, value, code="ANALYSIS_EVIDENCE_MISSING") for value in item_evidence] + for item in unknowns: + if set(item) != {"text", "critical", "verification"} if isinstance(item, dict) else True: + raise PlanAnvilError("Invalid unknown fields", code="INVALID_ANALYSIS_DATA", details=item) + if ( + not str(item.get("text", "")).strip() + or not isinstance(item.get("critical"), bool) + or not str(item.get("verification", "")).strip() + ): + raise PlanAnvilError("Invalid unknown", code="INVALID_ANALYSIS_DATA", details=item) + + target_md = run / "evidence/analysis.md" + target_json = run / "evidence/analysis.json" + payload = { + "schema_version": SCHEMA_VERSION, + "created_at": utc_now(), + "goal_hash": sha256_file(run / "evidence/original-goal.md"), + "markdown_hash": sha256_text(markdown), + "classification": raw["classification"], + "risk": raw["risk"], + "affected_paths": sorted(set(affected)), + "evidence": sorted(set(evidence)), + "assumptions": assumptions, + "unknowns": unknowns, + } + schema_path = Path(__file__).resolve().parent.parent / "schemas/analysis.schema.json" + schema_errors = validate(payload, load_json(schema_path)) + if schema_errors: + raise PlanAnvilError("Analysis schema validation failed", code="SCHEMA_VALIDATION_FAILED", details=schema_errors) + json_findings = privacy_findings(Path("evidence/analysis.json"), canonical_json_text(payload)) + if json_findings: + raise PlanAnvilError("Analysis data contains private or secret data", code="ANALYSIS_PRIVACY", details=json_findings) + atomic_write_text(target_md, markdown, exclusive=True) + atomic_write_json(target_json, payload, exclusive=True) + assert_valid_file(target_json, schema_path) + + critical = [item for item in unknowns if item["critical"]] + if critical: + transition_state( + state_path, + expected_revision=state["revision"], + new_status="BLOCKED", + phase="REPORT_AND_STOP", + next_action_type="NONE", + next_action_target=None, + blocker="BLOCKED_BY_CRITICAL_UNKNOWN", + hash_paths=[target_md, target_json], + ) + return { + "ok": False, + "result": "BLOCKED_BY_CRITICAL_UNKNOWN", + "analysis": repo_relative(repo, target_json), + "unknowns": critical, + } + + transition_state( + state_path, + expected_revision=state["revision"], + new_status="ANALYSIS_READY", + phase="GENERATE_ARTIFACTS", + next_action_type="AUTHOR_PLAN", + next_action_target="PLAN.md", + hash_paths=[target_md, target_json], + ) + return { + "ok": True, + "result": "ANALYSIS_READY", + "analysis": repo_relative(repo, target_json), + "markdown": repo_relative(repo, target_md), + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Record deterministic PlanAnvil goal analysis") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--analysis-markdown", type=Path, required=True) + parser.add_argument("--analysis-data", type=Path, required=True) + args = parser.parse_args() + payload = record_analysis( + args.planning, + args.run_root, + analysis_markdown=args.analysis_markdown, + analysis_data=args.analysis_data, + ) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/record_blind_review.py b/.agents/skills/plan-anvil/scripts/record_blind_review.py new file mode 100644 index 0000000..9bad752 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/record_blind_review.py @@ -0,0 +1,151 @@ +from __future__ import annotations + +import argparse +import re +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_json, + atomic_write_text, + canonical_json_text, + cli_main, + discover_repo, + emit, + load_json, + repo_relative, + privacy_findings, + sha256_file, + sha256_text, + utc_now, +) +from prepare_review_bundle import review_file_entries +from schema_validator import assert_valid_file, validate +from transition_state import transition_state + + +def record_blind_review( + planning: Path, + run_root: Path, + *, + review_markdown: Path, + result: str, + findings_file: Path | None = None, +) -> dict[str, Any]: + if result not in {"PASS", "FAIL", "BLOCKED"}: + raise PlanAnvilError(f"Invalid review result: {result}", code="INVALID_REVIEW_RESULT") + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + state = load_json(run / "state.json") + if state.get("status") != "DETERMINISTICALLY_VALID": + raise PlanAnvilError( + f"Blind review recording requires DETERMINISTICALLY_VALID, found {state.get('status')}", + code="INVALID_STATE_FOR_REVIEW", + ) + + bundle_path = run / "reports/plan-review/review-bundle.json" + bundle = load_json(bundle_path) + expected_files = review_file_entries(repo, run) + if bundle.get("purpose") != "BLIND_PLAN_REVIEW" or bundle.get("files") != expected_files: + raise PlanAnvilError( + "Blind-review bundle membership or hashes changed after deterministic validation", + code="REVIEW_BUNDLE_CHANGED", + ) + for item in expected_files: + path = repo / item["path"] + if not path.is_file() or sha256_file(path) != item["sha256"]: + raise PlanAnvilError( + f"Review input changed or is missing: {item['path']}", + code="REVIEW_INPUT_CHANGED", + ) + + markdown = review_markdown.read_text(encoding="utf-8").rstrip() + "\n" + if not markdown.strip(): + raise PlanAnvilError("Blind review Markdown is empty", code="EMPTY_REVIEW") + if re.search(r"\{\{[^}]+\}\}|\b(?:TODO|TBD)\b", markdown, re.IGNORECASE): + raise PlanAnvilError("Blind review contains placeholders", code="REVIEW_PLACEHOLDER") + + review_privacy = privacy_findings(Path("reports/plan-review/blind-review.md"), markdown) + if review_privacy: + raise PlanAnvilError("Blind review contains private or secret data", code="REVIEW_PRIVACY", details=review_privacy) + + findings: list[dict[str, Any]] = [] + if findings_file: + raw = load_json(findings_file) + if not isinstance(raw, list): + raise PlanAnvilError("Findings file must contain a JSON array", code="INVALID_FINDINGS") + findings = raw + + target_md = run / "reports/plan-review/blind-review.md" + target_json = run / "reports/plan-review/blind-review.json" + sidecar = { + "schema_version": "1.1.0", + "report_type": "BLIND_PLAN_REVIEW", + "created_at": utc_now(), + "inputs": {item["path"]: item["sha256"] for item in expected_files}, + "result": result, + "findings": findings, + "markdown_hash": sha256_text(markdown), + } + schema = Path(__file__).resolve().parent.parent / "schemas/review.schema.json" + schema_errors = validate(sidecar, load_json(schema)) + if schema_errors: + raise PlanAnvilError("Blind review schema validation failed", code="SCHEMA_VALIDATION_FAILED", details=schema_errors) + sidecar_privacy = privacy_findings(Path("reports/plan-review/blind-review.json"), canonical_json_text(sidecar)) + if sidecar_privacy: + raise PlanAnvilError("Blind review sidecar contains private or secret data", code="REVIEW_PRIVACY", details=sidecar_privacy) + atomic_write_text(target_md, markdown, exclusive=True) + atomic_write_json(target_json, sidecar, exclusive=True) + assert_valid_file(target_json, schema) + + compliance_path = run / "compliance.json" + compliance = load_json(compliance_path) + for capability in compliance.get("capabilities", []): + if capability.get("id") == "CAP-BLIND-REVIEW": + capability["status"] = "VERIFIED" if result == "PASS" else "FAILED" + capability["evidence"] = [ + repo_relative(repo, target_md), + repo_relative(repo, target_json), + ] + compliance["verified_at"] = utc_now() + atomic_write_json(compliance_path, compliance) + + transition_state( + run / "state.json", + expected_revision=state["revision"], + new_status="BLIND_REVIEW_WRITTEN", + phase="COMPARISON_AND_FINAL_VALIDATION", + next_action_type="COMPARE_REVIEW", + next_action_target="reports/plan-review/comparison.json", + hash_paths=[target_md, target_json], + ) + return { + "ok": True, + "result": "BLIND_REVIEW_WRITTEN", + "review_result": result, + "markdown": repo_relative(repo, target_md), + "sidecar": repo_relative(repo, target_json), + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Record one immutable PlanAnvil blind review") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--review-markdown", type=Path, required=True) + parser.add_argument("--result", choices=["PASS", "FAIL", "BLOCKED"], required=True) + parser.add_argument("--findings-file", type=Path) + args = parser.parse_args() + payload = record_blind_review( + args.planning, + args.run_root, + review_markdown=args.review_markdown, + result=args.result, + findings_file=args.findings_file, + ) + return emit(payload) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/scaffold_run.py b/.agents/skills/plan-anvil/scripts/scaffold_run.py new file mode 100644 index 0000000..5f3f21b --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/scaffold_run.py @@ -0,0 +1,385 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import ( + CONTRACT_VERSION, + GENERATOR_VERSION, + PLAN_ID_RE, + RUN_ID_RE, + SCHEMA_VERSION, + PlanAnvilError, + append_ignore_rules, + atomic_write_json, + atomic_write_text, + canonical_json_text, + cli_main, + discover_repo, + emit, + git, + is_ignored, + is_tracked, + load_json, + repository_fingerprint, + sha256_file, + sha256_text, + source_snapshot, + utc_now, +) +from schema_validator import assert_valid_file + + +DIRECTORIES = [ + "stages", + "checkpoints", + "reports/validation", + "reports/plan-review", + "risks", + "evidence", + "diffs", + "logs", + "incidents", + "final", +] + + +def _template(name: str) -> str: + path = Path(__file__).resolve().parent.parent / "templates" / name + return path.read_text(encoding="utf-8") + + +REQUIRED_GIT_STEPS = [ + "create_temporary_ref", + "verify_temporary_ref", + "delete_temporary_ref", + "create_probe_branch", + "create_probe_worktree", + "checkout_probe_worktree", + "create_probe_file", + "update_probe_index", + "create_probe_commit", + "verify_probe_clean", +] + + +def _git_evidence( + capability_report: dict[str, Any] | None, + *, + source_repo: Path, + source_state: dict[str, Any], + base_branch: str, + base_sha: str, + verified_at: str, +) -> dict[str, Any]: + if not isinstance(capability_report, dict): + raise PlanAnvilError("A complete Git capability report is required", code="CAPABILITY_REPORT_REQUIRED") + if capability_report.get("ok") is not True or capability_report.get("result") != "GIT_READY": + raise PlanAnvilError("Git capability report is not GIT_READY", code="GIT_NOT_READY") + report_root = capability_report.get("repository_root") + if not isinstance(report_root, str) or Path(report_root).resolve() != source_repo.resolve(): + raise PlanAnvilError("Git capability report belongs to a different repository", code="CAPABILITY_REPOSITORY_MISMATCH") + report_snapshot = capability_report.get("source_snapshot") + if not isinstance(report_snapshot, dict) or report_snapshot != source_state or report_snapshot.get("head") != base_sha: + raise PlanAnvilError("Git capability evidence is stale", code="CAPABILITY_REPORT_STALE") + if capability_report.get("base_branch") != base_branch: + raise PlanAnvilError("Git capability base branch differs from the planning base", code="CAPABILITY_BASE_MISMATCH") + if capability_report.get("source_snapshot_changed") not in ([], None): + raise PlanAnvilError("Git capability probe changed the source worktree", code="CAPABILITY_SOURCE_CHANGED") + cleanup_errors = capability_report.get("cleanup_errors") + if cleanup_errors != []: + raise PlanAnvilError("Git capability cleanup was not verified", code="CAPABILITY_CLEANUP_FAILED", details=cleanup_errors) + steps = capability_report.get("steps") + if not isinstance(steps, list): + raise PlanAnvilError("Git capability steps are missing", code="CAPABILITY_REPORT_INCOMPLETE") + step_results = {item.get("step"): item.get("ok") for item in steps if isinstance(item, dict)} + missing = [step for step in REQUIRED_GIT_STEPS if step_results.get(step) is not True] + if missing: + raise PlanAnvilError("Git capability report did not pass every required operation", code="CAPABILITY_REPORT_INCOMPLETE", details=missing) + return { + "schema_version": SCHEMA_VERSION, + "verified_at": verified_at, + "result": "GIT_READY", + "base_branch": base_branch, + "base_sha": base_sha, + "source_snapshot": source_state, + "steps": [{"id": step, "result": "PASS"} for step in REQUIRED_GIT_STEPS], + "cleanup": {"result": "PASS", "errors": []}, + } + + +def scaffold_run( + planning: Path, + source: Path, + *, + plan_id: str, + run_id: str, + slug: str, + goal: str, + base_branch: str, + base_sha: str, + capability_report: dict[str, Any] | None = None, + codex_version: str = "unknown", + model: str = "unknown", + permission_mode: str = "unknown", + project_trust: str = "UNKNOWN", + hook_mode: str = "HOOKS_UNAVAILABLE", +) -> dict[str, Any]: + if not PLAN_ID_RE.fullmatch(plan_id): + raise PlanAnvilError(f"Invalid plan id: {plan_id}", code="INVALID_PLAN_ID") + if not RUN_ID_RE.fullmatch(run_id): + raise PlanAnvilError(f"Invalid run id: {run_id}", code="INVALID_RUN_ID") + if not goal.strip(): + raise PlanAnvilError("Goal must not be empty", code="EMPTY_GOAL") + if project_trust not in {"TRUSTED", "UNTRUSTED", "UNKNOWN"}: + raise PlanAnvilError(f"Invalid project trust: {project_trust}", code="INVALID_RUNTIME_METADATA") + if hook_mode not in {"HOOKS_TRUSTED", "HOOKS_DISABLED", "HOOKS_UNTRUSTED", "HOOKS_UNAVAILABLE"}: + raise PlanAnvilError(f"Invalid hook mode: {hook_mode}", code="INVALID_RUNTIME_METADATA") + + repo = discover_repo(planning) + source_repo = discover_repo(source) + branch = git(repo, "symbolic-ref", "--quiet", "--short", "HEAD", check=False).stdout.strip() + expected_branch = f"pursue/plan/{plan_id}/{slug}" + if branch != expected_branch: + raise PlanAnvilError( + f"Expected planning branch {expected_branch}, got {branch or 'detached HEAD'}", + code="PLANNING_BRANCH_MISMATCH", + ) + head = git(repo, "rev-parse", "HEAD").stdout.strip() + if head != base_sha: + raise PlanAnvilError("Planning worktree no longer points at the verified base SHA", code="BASE_SHA_MISMATCH") + + profile = repo / ".pursue/SYSTEM_PROFILE.md" + local_profile = repo / ".pursue/SYSTEM_PROFILE.local.md" + if not profile.is_file() or not local_profile.is_file(): + raise PlanAnvilError("Profiles must exist before scaffolding a run", code="PROFILE_MISSING") + + source_state = source_snapshot(source_repo) + if source_state["head"] != base_sha: + raise PlanAnvilError("Source HEAD differs from the verified base SHA", code="SOURCE_CHANGED") + created_at = utc_now() + git_evidence = _git_evidence( + capability_report, + source_repo=source_repo, + source_state=source_state, + base_branch=base_branch, + base_sha=base_sha, + verified_at=created_at, + ) + + run_rel = Path(".pursue/runs") / run_id + run_root = repo / run_rel + if run_root.exists(): + raise PlanAnvilError(f"Run already exists: {run_rel.as_posix()}", code="RUN_EXISTS") + for directory in DIRECTORIES: + (run_root / directory).mkdir(parents=True, exist_ok=True) + + manifest = { + "schema_version": SCHEMA_VERSION, + "plan_id": plan_id, + "run_id": run_id, + "created_at": created_at, + "generator_version": GENERATOR_VERSION, + "repository": { + "fingerprint": repository_fingerprint(repo), + "base_branch": base_branch, + "base_sha": base_sha, + "planning_branch": branch, + }, + "paths": { + "run_root": run_rel.as_posix(), + "plan": "PLAN.md", + "state": "state.json", + "compliance": "compliance.json", + "traceability": "traceability.json", + "repository_profile": ".pursue/SYSTEM_PROFILE.md", + "local_state": "local-state.json", + }, + "contract_versions": { + "implementation_spec": CONTRACT_VERSION, + "plan_contract": "1.0.0", + "artifact_schema": SCHEMA_VERSION, + }, + } + state = { + "schema_version": SCHEMA_VERSION, + "revision": 4, + "updated_at": created_at, + "mode": "PLAN_GENERATION", + "status": "PROFILE_READY", + "current_stage": None, + "current_phase": "DISCOVER_INSTRUCTIONS", + "next_action": {"type": "MAP_INSTRUCTIONS", "target": "evidence/instruction-map.json"}, + "last_checkpoint": None, + "open_blockers": [], + "artifact_hashes": {}, + } + compliance = { + "schema_version": SCHEMA_VERSION, + "verified_at": created_at, + "codex": { + "version": codex_version or "unknown", + "model": model or "unknown", + "permission_mode": permission_mode or "unknown", + "project_trust": project_trust, + "hook_mode": hook_mode, + }, + "capabilities": [ + {"id": "CAP-SKILL-DISCOVERY", "status": "DOCUMENTED", "required": True, "evidence": []}, + {"id": "CAP-EXPLICIT-ACTIVATION", "status": "DOCUMENTED", "required": True, "evidence": []}, + {"id": "CAP-GIT-PROBE", "status": "VERIFIED", "required": True, "evidence": [(run_rel / "evidence/git-capability.json").as_posix()]}, + {"id": "CAP-INSTRUCTION-MAP", "status": "UNKNOWN", "required": True, "evidence": []}, + {"id": "CAP-BLIND-REVIEW", "status": "UNKNOWN", "required": True, "evidence": []}, + ], + "unsupported": [ + "Generator execution of implementation stages", + "Automatic base-branch push or merge", + "Hooks as the sole enforcement boundary", + ], + "warnings": [ + warning + for warning in [ + "Codex version is unknown." if not codex_version or codex_version == "unknown" else None, + "Model slug is unknown." if not model or model == "unknown" else None, + "Permission mode is unknown." if not permission_mode or permission_mode == "unknown" else None, + "Project trust is unknown." if project_trust == "UNKNOWN" else None, + "Hooks are not verified active; deterministic postconditions remain mandatory." if hook_mode != "HOOKS_TRUSTED" else None, + ] + if warning + ], + } + traceability = { + "schema_version": SCHEMA_VERSION, + "requirements": [], + "criteria": [], + "controls": [], + "gaps": [], + } + + lifecycle = { + "schema_version": SCHEMA_VERSION, + "recorded_at": created_at, + "events": [ + {"sequence": 1, "state": "SOURCE_PREFLIGHT_PASSED", "result": "PASS", "evidence": [(run_rel / "evidence/git-capability.json").as_posix()]}, + {"sequence": 2, "state": "GIT_READY", "result": "PASS", "evidence": [(run_rel / "evidence/git-capability.json").as_posix()]}, + {"sequence": 3, "state": "PLANNING_WORKTREE_READY", "result": "PASS", "evidence": [(run_rel / "manifest.json").as_posix()]}, + {"sequence": 4, "state": "PROFILE_READY", "result": "PASS", "evidence": [".pursue/SYSTEM_PROFILE.md"]}, + ], + } + state["artifact_hashes"] = { + "evidence/git-capability.json": sha256_text(canonical_json_text(git_evidence)), + "evidence/lifecycle.json": sha256_text(canonical_json_text(lifecycle)), + ".pursue/SYSTEM_PROFILE.md": sha256_file(profile), + } + local_state = { + "schema_version": SCHEMA_VERSION, + "run_id": run_id, + "updated_at": created_at, + "paths": { + "source_worktree": str(source_repo.resolve()), + "planning_worktree": str(repo.resolve()), + "local_profile": str(local_profile.resolve()), + }, + "hashes": {"local_profile": sha256_file(local_profile)}, + "source_snapshot": source_state, + } + + atomic_write_json(run_root / "manifest.json", manifest) + atomic_write_json(run_root / "evidence/git-capability.json", git_evidence) + atomic_write_json(run_root / "evidence/lifecycle.json", lifecycle) + atomic_write_json(run_root / "state.json", state) + atomic_write_json(run_root / "compliance.json", compliance) + atomic_write_json(run_root / "traceability.json", traceability) + atomic_write_json(run_root / "local-state.json", local_state) + atomic_write_text(run_root / "evidence/original-goal.md", "# Original goal\n\n" + goal.strip() + "\n") + + plan = _template("PLAN.md") + replacements = { + "{{TITLE}}": slug.replace("-", " ").title(), + "{{PLAN_ID}}": plan_id, + "{{RUN_ID}}": run_id, + "{{BASE_BRANCH}}": base_branch, + "{{BASE_SHA}}": base_sha, + "{{PLANNING_BRANCH}}": branch, + "{{GOAL}}": goal.strip(), + "{{STATUS}}": "DRAFT", + "{{NEXT_ACTION}}": "Complete repository analysis and author the plan.", + } + for key, value in replacements.items(): + plan = plan.replace(key, value) + atomic_write_text(run_root / "PLAN.md", plan) + + append_ignore_rules( + repo, + [ + ".pursue/SYSTEM_PROFILE.local.md", + ".pursue/runs/*/local-state.json", + ".pursue/runs/*/.generation-lock", + ".pursue/runs/*/.execution-lock", + ], + ) + if not is_ignored(repo, run_root / "local-state.json") or is_tracked(repo, run_root / "local-state.json"): + raise PlanAnvilError("local-state.json is not safely ignored and untracked", code="LOCAL_STATE_NOT_IGNORED") + + schema_root = Path(__file__).resolve().parent.parent / "schemas" + for filename in ["manifest", "state", "compliance", "traceability", "local-state"]: + assert_valid_file(run_root / f"{filename}.json", schema_root / f"{filename}.schema.json") + assert_valid_file(run_root / "evidence/git-capability.json", schema_root / "git-capability.schema.json") + assert_valid_file(run_root / "evidence/lifecycle.json", schema_root / "lifecycle.schema.json") + + return { + "ok": True, + "result": "RUN_SCAFFOLDED", + "run_root": run_rel.as_posix(), + "plan": (run_rel / "PLAN.md").as_posix(), + "state": state["status"], + "next_action": state["next_action"], + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Scaffold a durable PlanAnvil run") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--source", type=Path, required=True) + parser.add_argument("--plan-id", required=True) + parser.add_argument("--run-id", required=True) + parser.add_argument("--slug", required=True) + goal_group = parser.add_mutually_exclusive_group(required=True) + goal_group.add_argument("--goal") + goal_group.add_argument("--goal-file", type=Path) + parser.add_argument("--base-branch", required=True) + parser.add_argument("--base-sha", required=True) + parser.add_argument("--capability-report", type=Path, required=True) + parser.add_argument("--codex-version", default="unknown") + parser.add_argument("--model", default="unknown") + parser.add_argument("--permission-mode", default="unknown") + parser.add_argument("--project-trust", choices=["TRUSTED", "UNTRUSTED", "UNKNOWN"], default="UNKNOWN") + parser.add_argument( + "--hook-mode", + choices=["HOOKS_TRUSTED", "HOOKS_DISABLED", "HOOKS_UNTRUSTED", "HOOKS_UNAVAILABLE"], + default="HOOKS_UNAVAILABLE", + ) + args = parser.parse_args() + goal = args.goal if args.goal is not None else args.goal_file.read_text(encoding="utf-8") + payload = scaffold_run( + args.planning, + args.source, + plan_id=args.plan_id, + run_id=args.run_id, + slug=args.slug, + goal=goal, + base_branch=args.base_branch, + base_sha=args.base_sha, + capability_report=load_json(args.capability_report), + codex_version=args.codex_version, + model=args.model, + permission_mode=args.permission_mode, + project_trust=args.project_trust, + hook_mode=args.hook_mode, + ) + return emit(payload) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/schema_validator.py b/.agents/skills/plan-anvil/scripts/schema_validator.py new file mode 100644 index 0000000..80c9217 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/schema_validator.py @@ -0,0 +1,152 @@ +from __future__ import annotations + +import datetime as dt +import json +import re +from pathlib import Path +from typing import Any + +from common import PlanAnvilError, load_json + + +class SchemaValidationError(PlanAnvilError): + def __init__(self, errors: list[str]): + super().__init__("Schema validation failed", code="SCHEMA_VALIDATION_FAILED", details=errors) + self.errors = errors + + +def _resolve_ref(root_schema: dict[str, Any], ref: str) -> dict[str, Any]: + if not ref.startswith("#/"): + raise PlanAnvilError(f"Only local schema refs are supported: {ref}", code="UNSUPPORTED_SCHEMA_REF") + node: Any = root_schema + for part in ref[2:].split("/"): + part = part.replace("~1", "/").replace("~0", "~") + node = node[part] + if not isinstance(node, dict): + raise PlanAnvilError(f"Schema ref is not an object: {ref}", code="INVALID_SCHEMA_REF") + return node + + +def _type_matches(value: Any, expected: str) -> bool: + if expected == "null": + return value is None + if expected == "object": + return isinstance(value, dict) + if expected == "array": + return isinstance(value, list) + if expected == "string": + return isinstance(value, str) + if expected == "integer": + return isinstance(value, int) and not isinstance(value, bool) + if expected == "number": + return isinstance(value, (int, float)) and not isinstance(value, bool) + if expected == "boolean": + return isinstance(value, bool) + return True + + +def _is_datetime(value: str) -> bool: + if not value.endswith("Z"): + return False + try: + dt.datetime.fromisoformat(value[:-1] + "+00:00") + return True + except ValueError: + return False + + +def validate(instance: Any, schema: dict[str, Any], *, root_schema: dict[str, Any] | None = None, path: str = "$") -> list[str]: + root_schema = root_schema or schema + errors: list[str] = [] + + if "$ref" in schema: + return validate(instance, _resolve_ref(root_schema, schema["$ref"]), root_schema=root_schema, path=path) + + if "allOf" in schema: + for item in schema["allOf"]: + errors.extend(validate(instance, item, root_schema=root_schema, path=path)) + if "anyOf" in schema: + if not any(not validate(instance, item, root_schema=root_schema, path=path) for item in schema["anyOf"]): + errors.append(f"{path}: does not match anyOf") + if "oneOf" in schema: + matched = sum(not validate(instance, item, root_schema=root_schema, path=path) for item in schema["oneOf"]) + if matched != 1: + errors.append(f"{path}: matches {matched} oneOf branches") + if "not" in schema and not validate(instance, schema["not"], root_schema=root_schema, path=path): + errors.append(f"{path}: matches forbidden schema") + + if "const" in schema and instance != schema["const"]: + errors.append(f"{path}: expected constant {schema['const']!r}") + if "enum" in schema and instance not in schema["enum"]: + errors.append(f"{path}: {instance!r} not in enum") + + expected_type = schema.get("type") + if expected_type: + expected_types = [expected_type] if isinstance(expected_type, str) else expected_type + if not any(_type_matches(instance, item) for item in expected_types): + errors.append(f"{path}: expected type {expected_types}, got {type(instance).__name__}") + return errors + + if isinstance(instance, dict): + required = schema.get("required", []) + for key in required: + if key not in instance: + errors.append(f"{path}: missing required property {key!r}") + properties = schema.get("properties", {}) + additional = schema.get("additionalProperties", True) + for key, value in instance.items(): + child = f"{path}.{key}" + if key in properties: + errors.extend(validate(value, properties[key], root_schema=root_schema, path=child)) + elif additional is False: + errors.append(f"{path}: unexpected property {key!r}") + elif isinstance(additional, dict): + errors.extend(validate(value, additional, root_schema=root_schema, path=child)) + if "minProperties" in schema and len(instance) < schema["minProperties"]: + errors.append(f"{path}: fewer than {schema['minProperties']} properties") + if "maxProperties" in schema and len(instance) > schema["maxProperties"]: + errors.append(f"{path}: more than {schema['maxProperties']} properties") + + if isinstance(instance, list): + if "minItems" in schema and len(instance) < schema["minItems"]: + errors.append(f"{path}: fewer than {schema['minItems']} items") + if "maxItems" in schema and len(instance) > schema["maxItems"]: + errors.append(f"{path}: more than {schema['maxItems']} items") + if schema.get("uniqueItems"): + serialized = [json.dumps(x, sort_keys=True, ensure_ascii=False) for x in instance] + if len(serialized) != len(set(serialized)): + errors.append(f"{path}: array items are not unique") + item_schema = schema.get("items") + if isinstance(item_schema, dict): + for index, value in enumerate(instance): + errors.extend(validate(value, item_schema, root_schema=root_schema, path=f"{path}[{index}]")) + + if isinstance(instance, str): + if "minLength" in schema and len(instance) < schema["minLength"]: + errors.append(f"{path}: string shorter than {schema['minLength']}") + if "maxLength" in schema and len(instance) > schema["maxLength"]: + errors.append(f"{path}: string longer than {schema['maxLength']}") + if "pattern" in schema and re.search(schema["pattern"], instance) is None: + errors.append(f"{path}: string does not match {schema['pattern']!r}") + if schema.get("format") == "date-time" and not _is_datetime(instance): + errors.append(f"{path}: invalid RFC 3339 UTC timestamp") + + if isinstance(instance, (int, float)) and not isinstance(instance, bool): + if "minimum" in schema and instance < schema["minimum"]: + errors.append(f"{path}: value below minimum {schema['minimum']}") + if "maximum" in schema and instance > schema["maximum"]: + errors.append(f"{path}: value above maximum {schema['maximum']}") + + return errors + + +def validate_file(instance_path: Path, schema_path: Path) -> list[str]: + instance = load_json(instance_path) + schema = load_json(schema_path) + return validate(instance, schema) + + +def assert_valid_file(instance_path: Path, schema_path: Path) -> None: + errors = validate_file(instance_path, schema_path) + if errors: + raise SchemaValidationError(errors) diff --git a/.agents/skills/plan-anvil/scripts/seal_artifacts.py b/.agents/skills/plan-anvil/scripts/seal_artifacts.py new file mode 100644 index 0000000..e0c3cc0 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/seal_artifacts.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import PlanAnvilError, cli_main, discover_repo, emit, ensure_inside, load_json +from transition_state import transition_state +from validate_artifacts import validate_artifacts +from validate_plan import validate_plan + + +def seal_artifacts(planning: Path, run_root: Path) -> dict[str, Any]: + repo = discover_repo(planning) + run = ensure_inside(repo, run_root if run_root.is_absolute() else repo / run_root) + state = load_json(run / "state.json") + if state.get("status") != "ANALYSIS_READY": + raise PlanAnvilError( + f"Artifact sealing requires ANALYSIS_READY, found {state.get('status')}", + code="INVALID_STATE_FOR_ARTIFACT_SEAL", + ) + plan_result = validate_plan(repo, run, write_report=False) + artifact_result = validate_artifacts(repo, run, phase="pre-review", write_report=False) + findings = [] + if not plan_result.get("ok"): + findings.append({"validator": "validate_plan", "findings": plan_result.get("findings", [])}) + if not artifact_result.get("ok"): + findings.append({"validator": "validate_artifacts", "findings": artifact_result.get("findings", [])}) + if findings: + raise PlanAnvilError("Plan artifacts are incomplete or invalid", code="ARTIFACT_SEAL_FAILED", details=findings) + + plan_status = plan_result.get("plan_status") + if plan_status != "PLAN_READY": + raise PlanAnvilError( + f"Only PLAN_READY artifacts can be sealed, found {plan_status}", + code="PLAN_NOT_READY_TO_SEAL", + ) + hash_paths = [run / "PLAN.md", run / "traceability.json", run / "evidence/analysis.json"] + hash_paths.extend(sorted((run / "stages").glob("STAGE-*.md"))) + hash_paths.extend(sorted((run / "risks").glob("RISK-*.json"))) + transition_state( + run / "state.json", + expected_revision=state["revision"], + new_status="ARTIFACTS_GENERATED", + phase="DETERMINISTIC_VALIDATION", + next_action_type="RUN_VALIDATOR", + next_action_target="reports/validation/summary.json", + hash_paths=hash_paths, + ) + return {"ok": True, "result": "ARTIFACTS_GENERATED", "artifacts": len(hash_paths)} + + +def main() -> int: + parser = argparse.ArgumentParser(description="Seal authored PlanAnvil artifacts before deterministic validation") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + args = parser.parse_args() + return emit(seal_artifacts(args.planning, args.run_root)) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/test_git_capabilities.py b/.agents/skills/plan-anvil/scripts/test_git_capabilities.py new file mode 100644 index 0000000..eeaaf5e --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/test_git_capabilities.py @@ -0,0 +1,220 @@ +from __future__ import annotations + +import argparse +import os +import re +import shutil +import tempfile +from pathlib import Path +from typing import Any + +from common import PlanAnvilError, add_source_argument, cli_main, compare_snapshot, emit, git, require_external_path, source_snapshot +from preflight import plan_status_for, preflight + + +class _ProbeAbort(Exception): + pass + + +def _classify_failure(stderr: str, *, operation: str, repo: Path) -> str: + text = stderr.lower() + if any(token in text for token in ["author identity unknown", "unable to auto-detect email", "please tell me who you are"]): + return "GIT_IDENTITY_MISSING" + if any(token in text for token in ["gpg failed to sign", "signing failed", "failed to sign", "ssh signing"]): + return "GIT_SIGNING_BLOCKED" + if any(token in text for token in ["permission denied", "operation not permitted", "read-only file system", "cannot lock ref"]): + return "GIT_WRITE_RESTRICTED" + if operation == "worktree": + return "GIT_WORKTREE_UNSUPPORTED" + if operation == "commit": + hooks_dir = Path(git(repo, "rev-parse", "--git-path", "hooks").stdout.strip()) + if not hooks_dir.is_absolute(): + hooks_dir = repo / hooks_dir + relevant = ["pre-commit", "prepare-commit-msg", "commit-msg", "post-commit"] + if any((hooks_dir / name).exists() for name in relevant): + return "GIT_HOOK_BLOCKED" + return "GIT_WRITE_RESTRICTED" + return "GIT_WRITE_RESTRICTED" + + +def _run(repo: Path, operation: str, *args: str, cwd: Path | None = None) -> tuple[bool, str, str | None]: + target = cwd or repo + result = git(target, *args, check=False) + if result.returncode == 0: + return True, result.stdout, None + return False, result.stderr or result.stdout, _classify_failure(result.stderr + result.stdout, operation=operation, repo=repo) + + +def probe_git_capabilities(source: Path, run_id: str, temp_parent: Path | None = None) -> dict[str, Any]: + initial = preflight(source) + if not initial["ok"]: + return initial + + repo = Path(initial["repository_root"]) + before = source_snapshot(repo) + safe_run = re.sub(r"[^A-Za-z0-9._-]+", "-", run_id).strip("-")[:80] + if not safe_run: + raise PlanAnvilError("Run id is empty after normalization", code="INVALID_RUN_ID") + + ref_name = f"refs/plananvil/probes/{safe_run}" + branch_name = f"plananvil/probe/{safe_run}" + parent = require_external_path( + repo, + temp_parent or Path(tempfile.gettempdir()) / "plananvil-probes", + code="PROBE_TEMP_INSIDE_WORKTREE", + ) + parent.mkdir(parents=True, exist_ok=True) + probe_path = parent / safe_run + if probe_path.exists(): + raise PlanAnvilError(f"Probe path already exists: {probe_path}", code="PROBE_PATH_EXISTS") + + steps: list[dict[str, Any]] = [] + created_ref = False + created_branch = False + created_worktree = False + primary_result = "GIT_READY" + cleanup_errors: list[str] = [] + + def record(name: str, ok: bool, detail: str = "") -> None: + steps.append({"step": name, "ok": ok, "detail": detail.strip()[:2000]}) + + try: + ok, detail, failure = _run(repo, "ref", "update-ref", ref_name, before["head"]) + record("create_temporary_ref", ok, detail) + if not ok: + primary_result = failure or "GIT_WRITE_RESTRICTED" + raise _ProbeAbort + created_ref = True + + verify = git(repo, "rev-parse", ref_name, check=False) + ok = verify.returncode == 0 and verify.stdout.strip() == before["head"] + record("verify_temporary_ref", ok, verify.stderr or verify.stdout) + if not ok: + primary_result = "GIT_WRITE_RESTRICTED" + raise _ProbeAbort + + delete_ref = git(repo, "update-ref", "-d", ref_name, check=False) + ok = delete_ref.returncode == 0 + record("delete_temporary_ref", ok, delete_ref.stderr) + if not ok: + primary_result = "GIT_WRITE_RESTRICTED" + raise _ProbeAbort + created_ref = False + + branch = git(repo, "branch", branch_name, before["head"], check=False) + ok = branch.returncode == 0 + record("create_probe_branch", ok, branch.stderr) + if not ok: + primary_result = _classify_failure(branch.stderr, operation="branch", repo=repo) + raise _ProbeAbort + created_branch = True + + worktree = git(repo, "worktree", "add", "--no-checkout", str(probe_path), branch_name, check=False, timeout=180) + ok = worktree.returncode == 0 + record("create_probe_worktree", ok, worktree.stderr or worktree.stdout) + if not ok: + primary_result = _classify_failure(worktree.stderr, operation="worktree", repo=repo) + raise _ProbeAbort + created_worktree = True + + checkout = git(probe_path, "checkout", "--detach", branch_name, check=False) + ok = checkout.returncode == 0 + record("checkout_probe_worktree", ok, checkout.stderr or checkout.stdout) + if not ok: + primary_result = "GIT_WORKTREE_UNSUPPORTED" + raise _ProbeAbort + + probe_file = probe_path / f".plananvil-probe-{safe_run}" + probe_file.write_text("PlanAnvil Git capability probe\n", encoding="utf-8", newline="\n") + record("create_probe_file", probe_file.exists()) + + add = git(probe_path, "add", "--", probe_file.name, check=False) + ok = add.returncode == 0 + record("update_probe_index", ok, add.stderr) + if not ok: + primary_result = _classify_failure(add.stderr, operation="index", repo=repo) + raise _ProbeAbort + + commit = git( + probe_path, + "commit", + "-m", + f"PlanAnvil capability probe {safe_run}", + check=False, + timeout=180, + ) + ok = commit.returncode == 0 + record("create_probe_commit", ok, commit.stderr or commit.stdout) + if not ok: + primary_result = _classify_failure(commit.stderr + commit.stdout, operation="commit", repo=repo) + raise _ProbeAbort + + clean = git(probe_path, "status", "--porcelain=v1", check=False) + ok = clean.returncode == 0 and clean.stdout == "" + record("verify_probe_clean", ok, clean.stderr or clean.stdout) + if not ok: + primary_result = "GIT_WRITE_RESTRICTED" + raise _ProbeAbort + + except _ProbeAbort: + pass + finally: + if created_ref: + result = git(repo, "update-ref", "-d", ref_name, check=False) + if result.returncode != 0: + cleanup_errors.append(f"temporary ref: {result.stderr.strip()}") + if created_worktree: + result = git(repo, "worktree", "remove", "--force", str(probe_path), check=False, timeout=180) + if result.returncode != 0: + cleanup_errors.append(f"worktree: {result.stderr.strip()}") + else: + created_worktree = False + if probe_path.exists() and not created_worktree: + try: + probe_path.rmdir() + except OSError: + cleanup_errors.append(f"probe directory remains: {probe_path}") + if created_branch: + result = git(repo, "branch", "-D", branch_name, check=False) + if result.returncode != 0: + cleanup_errors.append(f"branch: {result.stderr.strip()}") + + return _finish(repo, before, primary_result, steps, cleanup_errors) + + +def _finish( + repo: Path, + before: dict[str, Any], + result: str, + steps: list[dict[str, Any]], + cleanup_errors: list[str], +) -> dict[str, Any]: + changed = compare_snapshot(repo, before) + if cleanup_errors or changed: + result = "GIT_WRITE_RESTRICTED" + refreshed = preflight(repo) + return { + "ok": result == "GIT_READY", + "result": result, + "plan_status": None if result == "GIT_READY" else plan_status_for(result), + "repository_root": str(repo), + "base_branch": refreshed.get("base_branch"), + "source_snapshot": before, + "source_snapshot_changed": changed, + "cleanup_errors": cleanup_errors, + "steps": steps, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Run the complete reversible PlanAnvil Git capability probe") + add_source_argument(parser) + parser.add_argument("--run-id", required=True) + parser.add_argument("--temp-parent", type=Path) + args = parser.parse_args() + payload = probe_git_capabilities(args.source, args.run_id, args.temp_parent) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/transition_state.py b/.agents/skills/plan-anvil/scripts/transition_state.py new file mode 100644 index 0000000..84869b6 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/transition_state.py @@ -0,0 +1,116 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import ( + GENERATOR_STATES, + PlanAnvilError, + atomic_write_json, + cli_main, + emit, + load_json, + sha256_file, + utc_now, +) +from schema_validator import assert_valid_file + + +ALLOWED = { + "NEW": {"SOURCE_PREFLIGHT_PASSED"}, + "SOURCE_PREFLIGHT_PASSED": {"GIT_READY"}, + "GIT_READY": {"PLANNING_WORKTREE_READY"}, + "PLANNING_WORKTREE_READY": {"PROFILE_READY"}, + "PROFILE_READY": {"INSTRUCTION_MAP_READY"}, + "INSTRUCTION_MAP_READY": {"ANALYSIS_READY"}, + "ANALYSIS_READY": {"ARTIFACTS_GENERATED"}, + "ARTIFACTS_GENERATED": {"DETERMINISTICALLY_VALID"}, + "DETERMINISTICALLY_VALID": {"BLIND_REVIEW_WRITTEN"}, + "BLIND_REVIEW_WRITTEN": {"COMPARISON_VALID"}, + "COMPARISON_VALID": {"PLAN_COMMITTED"}, + "PLAN_COMMITTED": {"STOPPED"}, +} + + +def transition_state( + state_path: Path, + *, + expected_revision: int, + new_status: str, + phase: str | None, + next_action_type: str, + next_action_target: str | None, + blocker: str | None = None, + hash_paths: list[Path] | None = None, +) -> dict[str, Any]: + state = load_json(state_path) + if state.get("revision") != expected_revision: + raise PlanAnvilError( + f"Stale state revision: expected {expected_revision}, found {state.get('revision')}", + code="STALE_STATE_REVISION", + ) + current = state.get("status") + allowed = ALLOWED.get(current, set()) + if new_status not in allowed and new_status not in {"BLOCKED", "FAILED"}: + raise PlanAnvilError(f"Invalid transition {current} → {new_status}", code="INVALID_STATE_TRANSITION") + if current in {"STOPPED", "BLOCKED", "FAILED"}: + raise PlanAnvilError(f"Terminal state cannot transition: {current}", code="TERMINAL_STATE") + + blockers = list(state.get("open_blockers", [])) + if blocker and blocker not in blockers: + blockers.append(blocker) + artifact_hashes = dict(state.get("artifact_hashes", {})) + for path in hash_paths or []: + if not path.is_file(): + raise PlanAnvilError(f"Cannot hash missing artifact: {path}", code="MISSING_ARTIFACT") + try: + key = path.resolve().relative_to(state_path.parent.resolve()).as_posix() + except ValueError: + key = path.name + artifact_hashes[key] = sha256_file(path) + + replacement = { + **state, + "revision": expected_revision + 1, + "updated_at": utc_now(), + "status": new_status, + "current_phase": phase, + "next_action": {"type": next_action_type, "target": next_action_target}, + "open_blockers": blockers, + "artifact_hashes": artifact_hashes, + } + if new_status in {"STOPPED", "BLOCKED", "FAILED"} and next_action_type != "NONE": + raise PlanAnvilError("Terminal state must use next_action.type = NONE", code="INVALID_TERMINAL_ACTION") + atomic_write_json(state_path, replacement) + schema = Path(__file__).resolve().parent.parent / "schemas/state.schema.json" + assert_valid_file(state_path, schema) + return replacement + + +def main() -> int: + parser = argparse.ArgumentParser(description="Atomically advance PlanAnvil canonical state") + parser.add_argument("--state", type=Path, required=True) + parser.add_argument("--expected-revision", type=int, required=True) + parser.add_argument("--status", required=True) + parser.add_argument("--phase") + parser.add_argument("--next-action", required=True) + parser.add_argument("--target") + parser.add_argument("--blocker") + parser.add_argument("--hash-path", type=Path, action="append", default=[]) + args = parser.parse_args() + state = transition_state( + args.state, + expected_revision=args.expected_revision, + new_status=args.status, + phase=args.phase, + next_action_type=args.next_action, + next_action_target=args.target, + blocker=args.blocker, + hash_paths=args.hash_path, + ) + return emit({"ok": True, "result": "STATE_UPDATED", "state": state}) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/validate_all.py b/.agents/skills/plan-anvil/scripts/validate_all.py new file mode 100644 index 0000000..8082984 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/validate_all.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import PlanAnvilError, atomic_write_json, cli_main, discover_repo, emit, load_json, utc_now +from transition_state import transition_state +from validate_artifacts import validate_artifacts +from validate_diff import validate_diff +from validate_plan import validate_plan +from validate_profile import validate_profile + + +def validate_all( + planning: Path, + run_root: Path, + *, + source: Path | None = None, + phase: str = "pre-review", + advance_state: bool = True, +) -> dict[str, Any]: + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + + results = { + "profile": validate_profile(repo), + "artifacts": validate_artifacts(repo, run, phase=phase, write_report=True), + "plan": validate_plan(repo, run, write_report=True), + "diff": validate_diff(repo, run, source=source, write_report=True), + } + findings = [ + {"validator": name, "findings": result.get("findings", [])} + for name, result in results.items() + if not result.get("ok") + ] + payload = { + "schema_version": "1.1.0", + "generated_at": utc_now(), + "validator": "validate_all", + "phase": phase, + "result": "PASS" if not findings else "FAIL", + "validators": {name: result.get("result") for name, result in results.items()}, + "findings": findings, + } + atomic_write_json(run / "reports/validation/summary.json", payload) + + if not findings and advance_state and phase == "pre-review": + state_path = run / "state.json" + state = load_json(state_path) + if state["status"] != "ARTIFACTS_GENERATED": + raise PlanAnvilError( + f"Deterministic validation requires ARTIFACTS_GENERATED, found {state['status']}", + code="INVALID_STATE_FOR_VALIDATION", + ) + transition_state( + state_path, + expected_revision=state["revision"], + new_status="DETERMINISTICALLY_VALID", + phase="BLIND_PLAN_REVIEW", + next_action_type="PREPARE_REVIEW_BUNDLE", + next_action_target="reports/plan-review/review-bundle.json", + hash_paths=[run / "PLAN.md", run / "traceability.json", run / "reports/validation/summary.json"], + ) + + return {"ok": not findings, **payload} + + +def main() -> int: + parser = argparse.ArgumentParser(description="Run all PlanAnvil deterministic validators") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--source", type=Path) + parser.add_argument("--phase", choices=["pre-review", "final"], default="pre-review") + parser.add_argument("--no-advance-state", action="store_true") + args = parser.parse_args() + payload = validate_all( + args.planning, + args.run_root, + source=args.source, + phase=args.phase, + advance_state=not args.no_advance_state, + ) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/validate_artifacts.py b/.agents/skills/plan-anvil/scripts/validate_artifacts.py new file mode 100644 index 0000000..e75be4b --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/validate_artifacts.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_json, + canonical_file_is_valid, + cli_main, + discover_repo, + emit, + is_ignored, + is_tracked, + load_json, + repo_relative, + scan_privacy, + sha256_file, + utc_now, +) +from schema_validator import validate_file + + +SCHEMA_FILES = { + "manifest.json": "manifest.schema.json", + "state.json": "state.schema.json", + "compliance.json": "compliance.schema.json", + "traceability.json": "traceability.schema.json", + "local-state.json": "local-state.schema.json", + "evidence/git-capability.json": "git-capability.schema.json", + "evidence/lifecycle.json": "lifecycle.schema.json", +} + + +def _resolve_run_root(repo: Path, run_root: Path) -> Path: + candidate = run_root if run_root.is_absolute() else repo / run_root + candidate = candidate.resolve() + try: + candidate.relative_to(repo) + except ValueError as exc: + raise PlanAnvilError("Run root escapes planning repository", code="PATH_ESCAPE") from exc + return candidate + + +def validate_artifacts(planning: Path, run_root: Path, *, phase: str = "pre-review", write_report: bool = True) -> dict[str, Any]: + repo = discover_repo(planning) + run = _resolve_run_root(repo, run_root) + schemas = Path(__file__).resolve().parent.parent / "schemas" + findings: list[dict[str, Any]] = [] + validated: list[str] = [] + + for filename, schema_name in SCHEMA_FILES.items(): + path = run / filename + if not path.is_file(): + findings.append({"kind": "missing", "path": repo_relative(repo, path)}) + continue + errors = validate_file(path, schemas / schema_name) + if errors: + findings.append({"kind": "schema", "path": repo_relative(repo, path), "errors": errors}) + elif not canonical_file_is_valid(path): + findings.append({"kind": "non-canonical-json", "path": repo_relative(repo, path)}) + else: + validated.append(repo_relative(repo, path)) + + manifest = load_json(run / "manifest.json") if (run / "manifest.json").is_file() else {} + state = load_json(run / "state.json") if (run / "state.json").is_file() else {} + compliance = load_json(run / "compliance.json") if (run / "compliance.json").is_file() else {} + traceability = load_json(run / "traceability.json") if (run / "traceability.json").is_file() else {} + + if manifest: + if manifest.get("run_id") != run.name: + findings.append({"kind": "run-id-mismatch", "expected": run.name, "actual": manifest.get("run_id")}) + expected_root = repo_relative(repo, run) + if manifest.get("paths", {}).get("run_root") != expected_root: + findings.append({"kind": "run-root-mismatch", "expected": expected_root, "actual": manifest.get("paths", {}).get("run_root")}) + + git_evidence = load_json(run / "evidence/git-capability.json") if (run / "evidence/git-capability.json").is_file() else {} + if git_evidence and manifest: + if git_evidence.get("base_sha") != manifest.get("repository", {}).get("base_sha"): + findings.append({"kind": "git-evidence-base-sha-mismatch"}) + if git_evidence.get("base_branch") != manifest.get("repository", {}).get("base_branch"): + findings.append({"kind": "git-evidence-base-branch-mismatch"}) + required_steps = { + "create_temporary_ref", "verify_temporary_ref", "delete_temporary_ref", + "create_probe_branch", "create_probe_worktree", "checkout_probe_worktree", + "create_probe_file", "update_probe_index", "create_probe_commit", "verify_probe_clean", + } + actual_steps = {item.get("id") for item in git_evidence.get("steps", []) if item.get("result") == "PASS"} + if actual_steps != required_steps: + findings.append({"kind": "git-evidence-step-mismatch", "missing": sorted(required_steps - actual_steps), "extra": sorted(actual_steps - required_steps)}) + + lifecycle = load_json(run / "evidence/lifecycle.json") if (run / "evidence/lifecycle.json").is_file() else {} + expected_bootstrap = ["SOURCE_PREFLIGHT_PASSED", "GIT_READY", "PLANNING_WORKTREE_READY", "PROFILE_READY"] + if lifecycle: + states = [item.get("state") for item in lifecycle.get("events", [])] + sequences = [item.get("sequence") for item in lifecycle.get("events", [])] + if states != expected_bootstrap or sequences != [1, 2, 3, 4]: + findings.append({"kind": "bootstrap-lifecycle-order", "states": states, "sequences": sequences}) + for event in lifecycle.get("events", []): + for relative in event.get("evidence", []): + path = repo / relative + try: + path.resolve().relative_to(repo.resolve()) + except ValueError: + findings.append({"kind": "lifecycle-evidence-path-escape", "path": relative}) + continue + if not path.is_file(): + findings.append({"kind": "lifecycle-evidence-missing", "path": relative}) + + local_state = run / "local-state.json" + local_profile = repo / ".pursue/SYSTEM_PROFILE.local.md" + for path in [local_state, local_profile]: + if path.exists() and not is_ignored(repo, path): + findings.append({"kind": "not-ignored", "path": repo_relative(repo, path)}) + if path.exists() and is_tracked(repo, path): + findings.append({"kind": "tracked-local-state", "path": repo_relative(repo, path)}) + + json_candidates = [ + path for path in run.rglob("*.json") + if path.name != "local-state.json" and not any(part.startswith(".") for part in path.relative_to(run).parts) + ] + schema_by_location: list[tuple[Path, Path]] = [] + schema_by_location += [(path, schemas / "risk.schema.json") for path in (run / "risks").glob("RISK-*.json")] + schema_by_location += [(path, schemas / "checkpoint.schema.json") for path in (run / "checkpoints").glob("CHECKPOINT-*.json")] + analysis = run / "evidence/analysis.json" + if analysis.exists(): + schema_by_location.append((analysis, schemas / "analysis.schema.json")) + review_sidecar = run / "reports/plan-review/blind-review.json" + comparison = run / "reports/plan-review/comparison.json" + if review_sidecar.exists(): + schema_by_location.append((review_sidecar, schemas / "review.schema.json")) + if comparison.exists(): + schema_by_location.append((comparison, schemas / "comparison.schema.json")) + + for path, schema in schema_by_location: + errors = validate_file(path, schema) + if errors: + findings.append({"kind": "schema", "path": repo_relative(repo, path), "errors": errors}) + if not canonical_file_is_valid(path): + findings.append({"kind": "non-canonical-json", "path": repo_relative(repo, path)}) + validated.append(repo_relative(repo, path)) + + for path in json_candidates: + if not canonical_file_is_valid(path): + findings.append({"kind": "non-canonical-json", "path": repo_relative(repo, path)}) + + committed_candidates = [ + repo / ".pursue/SYSTEM_PROFILE.md", + *[ + path for path in run.rglob("*") + if path.is_file() and path.name != "local-state.json" and not path.name.startswith(".") + ], + ] + findings.extend(scan_privacy(repo, committed_candidates)) + + referenced_risks = { + risk_id + for criterion in traceability.get("criteria", []) + for risk_id in criterion.get("risks", []) + } + available_risks = { + load_json(path).get("id") + for path in (run / "risks").glob("RISK-*.json") + if path.is_file() + } + for risk_id in sorted(referenced_risks - available_risks): + findings.append({"kind": "missing-risk-file", "risk": risk_id}) + + for capability in compliance.get("capabilities", []): + if not capability.get("required"): + continue + status = capability.get("status") + if status in {"FAILED", "BLOCKED"}: + findings.append({"kind": "required-capability-failed", "capability": capability.get("id"), "status": status}) + if phase == "final" and status == "UNKNOWN": + findings.append({"kind": "required-capability-unknown", "capability": capability.get("id")}) + + if phase == "final": + if not review_sidecar.is_file() or not (run / "reports/plan-review/blind-review.md").is_file(): + findings.append({"kind": "missing-blind-review"}) + if not comparison.is_file(): + findings.append({"kind": "missing-comparison"}) + elif load_json(comparison).get("result") != "PASS": + findings.append({"kind": "comparison-not-pass"}) + + for rel, expected_hash in state.get("artifact_hashes", {}).items(): + candidates = [run / rel, run / Path(rel).name, repo / rel] + existing = next((path for path in candidates if path.is_file()), None) + if existing is None: + findings.append({"kind": "hashed-artifact-missing", "path": rel}) + elif sha256_file(existing) != expected_hash: + findings.append({"kind": "hashed-artifact-stale", "path": rel}) + + payload = { + "schema_version": "1.1.0", + "generated_at": utc_now(), + "validator": "validate_artifacts", + "phase": phase, + "result": "PASS" if not findings else "FAIL", + "findings": findings, + "validated": sorted(set(validated)), + } + if write_report: + atomic_write_json(run / "reports/validation/artifacts.json", payload) + return {"ok": not findings, **payload} + + +def main() -> int: + parser = argparse.ArgumentParser(description="Validate PlanAnvil canonical artifacts, schemas, privacy, and ignored local state") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--phase", choices=["pre-review", "final"], default="pre-review") + parser.add_argument("--no-write-report", action="store_true") + args = parser.parse_args() + payload = validate_artifacts(args.planning, args.run_root, phase=args.phase, write_report=not args.no_write_report) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/validate_diff.py b/.agents/skills/plan-anvil/scripts/validate_diff.py new file mode 100644 index 0000000..84d5d4a --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/validate_diff.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import argparse +import fnmatch +from pathlib import Path +from typing import Any + +from common import ( + PlanAnvilError, + atomic_write_json, + cli_main, + compare_snapshot, + discover_repo, + emit, + ensure_inside, + git, + list_untracked, + load_json, + repo_relative, + scan_privacy, + utc_now, +) + + +def _changed_paths(repo: Path, base_sha: str) -> list[str]: + result = git(repo, "diff", "--name-only", "-z", base_sha, "--") + paths = [item for item in result.stdout.split("\0") if item] + paths.extend(list_untracked(repo)) + return sorted(set(paths)) + + +def _matches(path: str, allowed: list[str]) -> bool: + return any(fnmatch.fnmatchcase(path, pattern) for pattern in allowed) + + +def validate_diff( + planning: Path, + run_root: Path, + *, + source: Path | None = None, + extra_allowed: list[str] | None = None, + write_report: bool = True, +) -> dict[str, Any]: + repo = discover_repo(planning) + run = (run_root if run_root.is_absolute() else repo / run_root).resolve() + manifest = load_json(run / "manifest.json") + local_state = load_json(run / "local-state.json") + base_sha = manifest["repository"]["base_sha"] + run_rel = repo_relative(repo, run) + + allowed = [ + ".gitignore", + ".pursue/SYSTEM_PROFILE.md", + f"{run_rel}/**", + ] + allowed.extend(extra_allowed or []) + forbidden = [ + ".pursue/SYSTEM_PROFILE.local.md", + f"{run_rel}/local-state.json", + f"{run_rel}/.generation-lock", + f"{run_rel}/.execution-lock", + ] + + findings: list[dict[str, Any]] = [] + changed = _changed_paths(repo, base_sha) + committed_candidates: list[Path] = [] + + for rel in changed: + if rel in forbidden or _matches(rel, forbidden): + findings.append({"kind": "forbidden-local-artifact", "path": rel}) + continue + if not _matches(rel, allowed): + findings.append({"kind": "path-outside-planning-allowlist", "path": rel}) + continue + path = repo / rel + ensure_inside(repo, path) + if path.is_symlink(): + try: + path.resolve().relative_to(repo) + except ValueError: + findings.append({"kind": "symlink-escape", "path": rel}) + if path.is_file(): + committed_candidates.append(path) + + source_repo = discover_repo(source) if source else Path(local_state["paths"]["source_worktree"]) + changed_snapshot = compare_snapshot(source_repo, local_state["source_snapshot"]) + if changed_snapshot: + findings.append({"kind": "source-worktree-changed", "fields": changed_snapshot}) + + findings.extend(scan_privacy(repo, committed_candidates)) + + payload = { + "schema_version": "1.1.0", + "generated_at": utc_now(), + "validator": "validate_diff", + "result": "PASS" if not findings else "FAIL", + "base_sha": base_sha, + "allowed": allowed, + "changed_paths": changed, + "findings": findings, + } + if write_report: + atomic_write_json(run / "reports/validation/diff.json", payload) + return {"ok": not findings, **payload} + + +def main() -> int: + parser = argparse.ArgumentParser(description="Validate PlanAnvil planning-branch ownership and source immutability") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--source", type=Path) + parser.add_argument("--allow", action="append", default=[]) + parser.add_argument("--no-write-report", action="store_true") + args = parser.parse_args() + payload = validate_diff( + args.planning, + args.run_root, + source=args.source, + extra_allowed=args.allow, + write_report=not args.no_write_report, + ) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/validate_plan.py b/.agents/skills/plan-anvil/scripts/validate_plan.py new file mode 100644 index 0000000..018c5e6 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/validate_plan.py @@ -0,0 +1,445 @@ +from __future__ import annotations + +import argparse +import ast +import re +from collections import Counter +from pathlib import Path, PurePosixPath +from typing import Any + +from common import ( + STAGE_ID_RE, + TERMINAL_PLAN_STATUSES, + PlanAnvilError, + atomic_write_json, + cli_main, + discover_repo, + emit, + ensure_inside, + load_json, + repo_relative, + utc_now, +) + +REQUIRED_PLAN_HEADINGS = [ + "## Identity", + "## Original goal", + "## Outcome and definition of done", + "## Generator stop boundary", + "## Separate execution-run prompt", + "## Scope", + "## Exclusions", + "## Assumptions, unknowns, and evidence", + "## Applicable instructions", + "## System and change analysis", + "## Dependencies and classification", + "## Stable stage index", + "## Traceability", + "## Testing and independent verification", + "## Git, integration, and control-root rules", + "## Production verification, switching, and approvals", + "## Rollback and recovery", + "## Resume and reconciliation", + "## Status and next action", + "## Final report requirements", +] + +REQUIRED_STAGE_HEADINGS = [ + "## Outcome", + "## Scope", + "## Exclusions", + "## Affected paths or discovery procedure", + "## Applicable instructions", + "## Dependencies and conflicts", + "## Acceptance criteria", + "## Risks and controls", + "## Evidence cycle", + "## Modifier and verifier roles", + "## Commit and checkpoint", + "## Rollback", +] + +REQUIRED_STAGE_METADATA = [ + "outcome", + "classification", + "requirements", + "criteria", + "risks", + "dependencies", + "applicable_instructions", + "allowed_write_paths", +] + +PLACEHOLDER_RE = re.compile(r"\{\{[^}]+\}\}|\b(?:TODO|TBD)\b|\[REPLACE(?: ME)?\]", re.IGNORECASE) +BOUNDARY_VIOLATIONS = [ + re.compile(r"(?is)after (?:creating|generating|validating) (?:the )?plan.{0,120}(?:implement|start jim|execute stage)"), + re.compile(r"(?i)continue (?:directly )?into implementation"), + re.compile(r"(?i)immediately start jim"), + re.compile(r"(?i)in this (?:same )?run.{0,80}(?:implement|execute|modify product)"), +] +HASH_RE = re.compile(r"^sha256:[0-9a-f]{64}$") +WINDOWS_ABSOLUTE_RE = re.compile(r"^[A-Za-z]:[\\/]") + + +def _frontmatter(path: Path) -> dict[str, Any]: + text = path.read_text(encoding="utf-8") + if not text.startswith("---\n"): + raise PlanAnvilError(f"Missing stage frontmatter: {path.name}", code="STAGE_FRONTMATTER_MISSING") + end = text.find("\n---\n", 4) + if end < 0: + raise PlanAnvilError(f"Unclosed stage frontmatter: {path.name}", code="STAGE_FRONTMATTER_INVALID") + data: dict[str, Any] = {} + for line in text[4:end].splitlines(): + if not line.strip() or line.lstrip().startswith("#"): + continue + if ":" not in line: + raise PlanAnvilError(f"Invalid stage frontmatter line in {path.name}: {line}", code="STAGE_FRONTMATTER_INVALID") + key, raw = line.split(":", 1) + key = key.strip() + if not key or key in data: + raise PlanAnvilError(f"Duplicate or empty stage metadata key in {path.name}: {key}", code="STAGE_FRONTMATTER_INVALID") + raw = raw.strip() + if not raw: + data[key] = None + continue + try: + data[key] = ast.literal_eval(raw) + except (SyntaxError, ValueError): + data[key] = raw.strip("\"'") + return data + + +def _section(text: str, heading: str) -> str: + start = text.find(heading) + if start < 0: + return "" + body_start = start + len(heading) + next_heading = re.search(r"(?m)^##\s+", text[body_start:]) + end = body_start + next_heading.start() if next_heading else len(text) + return text[body_start:end].strip() + + +def _duplicates(values: list[Any]) -> list[Any]: + return sorted(value for value, count in Counter(values).items() if value is not None and count > 1) + + +def _safe_relative_glob(value: Any) -> bool: + if not isinstance(value, str) or not value.strip() or "\x00" in value: + return False + normalized = value.replace("\\", "/") + if normalized.startswith("/") or WINDOWS_ABSOLUTE_RE.match(value) or normalized.startswith("//"): + return False + parts = PurePosixPath(normalized).parts + return ".." not in parts and ".git" not in parts + + +def _dependency_cycles(stages: dict[str, dict[str, Any]]) -> list[list[str]]: + cycles: list[list[str]] = [] + visiting: list[str] = [] + visited: set[str] = set() + + def visit(stage_id: str) -> None: + if stage_id in visiting: + index = visiting.index(stage_id) + cycle = visiting[index:] + [stage_id] + if cycle not in cycles: + cycles.append(cycle) + return + if stage_id in visited: + return + visiting.append(stage_id) + for dependency in stages.get(stage_id, {}).get("dependencies") or []: + if dependency in stages: + visit(dependency) + visiting.pop() + visited.add(stage_id) + + for stage_id in stages: + visit(stage_id) + return cycles + + +def _load_risks(run: Path, findings: list[dict[str, Any]]) -> dict[str, dict[str, Any]]: + risks: dict[str, dict[str, Any]] = {} + for path in sorted((run / "risks").glob("RISK-*.json")): + try: + risk = load_json(path) + except PlanAnvilError as exc: + findings.append({"kind": exc.code, "path": f"risks/{path.name}", "message": str(exc)}) + continue + risk_id = risk.get("id") + if not isinstance(risk_id, str): + findings.append({"kind": "risk-id-missing", "path": f"risks/{path.name}"}) + continue + if path.stem != risk_id: + findings.append({"kind": "risk-filename-mismatch", "path": f"risks/{path.name}", "risk": risk_id}) + if risk_id in risks: + findings.append({"kind": "duplicate-risk-id", "risk": risk_id}) + risks[risk_id] = risk + return risks + + +def validate_plan(planning: Path, run_root: Path, *, write_report: bool = True) -> dict[str, Any]: + repo = discover_repo(planning) + run = ensure_inside(repo, run_root if run_root.is_absolute() else repo / run_root) + plan_path = run / "PLAN.md" + findings: list[dict[str, Any]] = [] + plan_status: str | None = None + manifest = load_json(run / "manifest.json") if (run / "manifest.json").is_file() else {} + instruction_map = load_json(run / "evidence/instruction-map.json") if (run / "evidence/instruction-map.json").is_file() else None + instruction_hashes = { + item.get("path"): item.get("sha256") + for item in (instruction_map or {}).get("files", []) + if isinstance(item, dict) + } + + if not plan_path.is_file(): + findings.append({"kind": "missing", "path": repo_relative(repo, plan_path)}) + plan_text = "" + else: + plan_text = plan_path.read_text(encoding="utf-8") + for heading in REQUIRED_PLAN_HEADINGS: + if heading not in plan_text: + findings.append({"kind": "missing-heading", "path": "PLAN.md", "heading": heading}) + for match in PLACEHOLDER_RE.finditer(plan_text): + findings.append({"kind": "placeholder", "path": "PLAN.md", "value": match.group(0)}) + for pattern in BOUNDARY_VIOLATIONS: + if pattern.search(plan_text): + findings.append({"kind": "generator-executor-boundary-violation", "path": "PLAN.md"}) + break + required_stop = "No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md." + if required_stop not in plan_text: + findings.append({"kind": "missing-hard-stop-statement", "path": "PLAN.md"}) + + if manifest: + expected_identity = { + "Plan ID": manifest.get("plan_id"), + "Run ID": manifest.get("run_id"), + "Base branch": manifest.get("repository", {}).get("base_branch"), + "Base SHA": manifest.get("repository", {}).get("base_sha"), + "Planning branch": manifest.get("repository", {}).get("planning_branch"), + } + for label, value in expected_identity.items(): + if value is not None and f"- {label}: `{value}`" not in plan_text: + findings.append({"kind": "plan-identity-mismatch", "field": label, "expected": value}) + + statuses = re.findall(r"(?m)^- Status:\s*`([^`]+)`\s*$", plan_text) + if len(statuses) != 1: + findings.append({"kind": "plan-status-count", "count": len(statuses)}) + plan_status = None + else: + plan_status = statuses[0] + if plan_status not in TERMINAL_PLAN_STATUSES: + findings.append({"kind": "invalid-plan-status", "status": plan_status}) + next_actions = [item.strip() for item in re.findall(r"(?m)^- Next action:\s*`([^`]+)`\s*$", plan_text)] + if len(next_actions) != 1 or not next_actions[0]: + findings.append({"kind": "plan-next-action-count", "count": len(next_actions)}) + + trace = load_json(run / "traceability.json") if (run / "traceability.json").is_file() else { + "requirements": [], "criteria": [], "controls": [], "gaps": [] + } + stage_paths = sorted((run / "stages").glob("STAGE-*.md")) + stages: dict[str, dict[str, Any]] = {} + + for path in stage_paths: + text = path.read_text(encoding="utf-8") + try: + metadata = _frontmatter(path) + except PlanAnvilError as exc: + findings.append({"kind": exc.code, "path": path.name, "message": str(exc)}) + continue + stage_id = metadata.get("stage_id") + if not isinstance(stage_id, str) or not STAGE_ID_RE.fullmatch(stage_id): + findings.append({"kind": "invalid-stage-id", "path": path.name, "value": stage_id}) + continue + if path.stem != stage_id: + findings.append({"kind": "stage-filename-mismatch", "path": path.name, "stage_id": stage_id}) + if stage_id in stages: + findings.append({"kind": "duplicate-stage-id", "stage_id": stage_id}) + stages[stage_id] = metadata + if metadata.get("schema_version") != "1.1.0": + findings.append({"kind": "stage-schema-version", "path": path.name}) + for key in REQUIRED_STAGE_METADATA: + if key not in metadata: + findings.append({"kind": "stage-metadata-missing", "path": path.name, "field": key}) + if not isinstance(metadata.get("outcome"), str) or not metadata.get("outcome", "").strip(): + findings.append({"kind": "stage-outcome-invalid", "stage": stage_id}) + if not isinstance(metadata.get("classification"), str) or not metadata.get("classification", "").strip(): + findings.append({"kind": "stage-classification-invalid", "stage": stage_id}) + for field in ["requirements", "criteria", "risks", "dependencies", "applicable_instructions", "allowed_write_paths"]: + if field in metadata and not isinstance(metadata[field], list): + findings.append({"kind": "stage-metadata-type", "stage": stage_id, "field": field, "expected": "list"}) + for allowed_path in metadata.get("allowed_write_paths") or []: + if not _safe_relative_glob(allowed_path): + findings.append({"kind": "unsafe-stage-write-path", "stage": stage_id, "path": allowed_path}) + instruction_refs = metadata.get("applicable_instructions") or [] + if instruction_hashes and not instruction_refs: + findings.append({"kind": "stage-without-applicable-instructions", "stage": stage_id}) + for reference in instruction_refs: + if not isinstance(reference, dict) or set(reference) != {"path", "sha256"}: + findings.append({"kind": "invalid-stage-instruction-reference", "stage": stage_id, "reference": reference}) + continue + ref_path = reference.get("path") + ref_hash = reference.get("sha256") + if not _safe_relative_glob(ref_path) or not isinstance(ref_hash, str) or not HASH_RE.fullmatch(ref_hash): + findings.append({"kind": "invalid-stage-instruction-reference", "stage": stage_id, "reference": reference}) + elif instruction_hashes.get(ref_path) != ref_hash: + findings.append({"kind": "stale-or-unmapped-instruction-reference", "stage": stage_id, "path": ref_path}) + for heading in REQUIRED_STAGE_HEADINGS: + if heading not in text: + findings.append({"kind": "missing-heading", "path": path.name, "heading": heading}) + for match in PLACEHOLDER_RE.finditer(text): + findings.append({"kind": "placeholder", "path": path.name, "value": match.group(0)}) + evidence = _section(text, "## Evidence cycle").upper() + for marker in ["GREEN", "RED", "IMPLEMENT", "INDEPENDENT"]: + if marker not in evidence: + findings.append({"kind": "stage-evidence-cycle-incomplete", "stage": stage_id, "missing": marker}) + if not _section(text, "## Rollback"): + findings.append({"kind": "stage-rollback-empty", "stage": stage_id}) + commit_section = _section(text, "## Commit and checkpoint").lower() + if "commit" not in commit_section or "checkpoint" not in commit_section: + findings.append({"kind": "stage-commit-checkpoint-incomplete", "stage": stage_id}) + + ready = plan_status == "PLAN_READY" + if ready and not stages: + findings.append({"kind": "ready-plan-without-stages"}) + + requirements = trace.get("requirements", []) + criteria = trace.get("criteria", []) + controls = trace.get("controls", []) + requirement_ids_list = [item.get("id") for item in requirements] + criterion_ids_list = [item.get("id") for item in criteria] + control_ids_list = [item.get("id") for item in controls] + for duplicate in _duplicates(requirement_ids_list): + findings.append({"kind": "duplicate-requirement-id", "id": duplicate}) + for duplicate in _duplicates(criterion_ids_list): + findings.append({"kind": "duplicate-criterion-id", "id": duplicate}) + for duplicate in _duplicates(control_ids_list): + findings.append({"kind": "duplicate-control-id", "id": duplicate}) + requirement_ids = set(requirement_ids_list) + criterion_ids = set(criterion_ids_list) + control_ids = set(control_ids_list) + criteria_by_stage: dict[str, set[str]] = {} + requirements_by_stage: dict[str, set[str]] = {} + + for requirement in requirements: + req_id = requirement.get("id") + for stage_id in requirement.get("stages", []): + requirements_by_stage.setdefault(stage_id, set()).add(req_id) + if stage_id not in stages: + findings.append({"kind": "traceability-missing-stage", "requirement": req_id, "stage": stage_id}) + for criterion in requirement.get("criteria", []): + if criterion not in criterion_ids: + findings.append({"kind": "traceability-missing-criterion", "requirement": req_id, "criterion": criterion}) + + referenced_risks: set[str] = set() + referenced_controls: set[str] = set() + for criterion in criteria: + criterion_id = criterion.get("id") + stage_id = criterion.get("stage") + criteria_by_stage.setdefault(stage_id, set()).add(criterion_id) + if stage_id not in stages: + findings.append({"kind": "criterion-stage-missing", "criterion": criterion_id, "stage": stage_id}) + if not criterion.get("controls"): + findings.append({"kind": "criterion-without-control", "criterion": criterion_id}) + if not criterion.get("evidence_type"): + findings.append({"kind": "criterion-without-evidence", "criterion": criterion_id}) + for control in criterion.get("controls", []): + referenced_controls.add(control) + if control not in control_ids: + findings.append({"kind": "criterion-control-missing", "criterion": criterion_id, "control": control}) + referenced_risks.update(criterion.get("risks", [])) + + for stage_id, metadata in stages.items(): + stage_requirements = set(metadata.get("requirements") or []) + stage_criteria = set(metadata.get("criteria") or []) + stage_risks = set(metadata.get("risks") or []) + if ready and not stage_requirements: + findings.append({"kind": "stage-without-requirement", "stage": stage_id}) + if ready and not stage_criteria: + findings.append({"kind": "stage-without-criterion", "stage": stage_id}) + for dependency in metadata.get("dependencies") or []: + if dependency == stage_id or dependency not in stages: + findings.append({"kind": "invalid-stage-dependency", "stage": stage_id, "dependency": dependency}) + for requirement in stage_requirements: + if requirement not in requirement_ids: + findings.append({"kind": "stage-requirement-missing", "stage": stage_id, "requirement": requirement}) + for criterion in stage_criteria: + if criterion not in criterion_ids: + findings.append({"kind": "stage-criterion-missing", "stage": stage_id, "criterion": criterion}) + if stage_requirements != requirements_by_stage.get(stage_id, set()): + findings.append({"kind": "stage-requirement-link-mismatch", "stage": stage_id}) + if stage_criteria != criteria_by_stage.get(stage_id, set()): + findings.append({"kind": "stage-criterion-link-mismatch", "stage": stage_id}) + criterion_risks = { + risk + for criterion in criteria + if criterion.get("stage") == stage_id + for risk in criterion.get("risks", []) + } + if stage_risks != criterion_risks: + findings.append({"kind": "stage-risk-link-mismatch", "stage": stage_id}) + + for cycle in _dependency_cycles(stages): + findings.append({"kind": "stage-dependency-cycle", "cycle": cycle}) + + risks = _load_risks(run, findings) + for risk_id in sorted(referenced_risks - set(risks)): + findings.append({"kind": "missing-risk-file", "risk": risk_id}) + for risk_id, risk in risks.items(): + stage_id = risk.get("stage") + if stage_id not in stages: + findings.append({"kind": "risk-stage-missing", "risk": risk_id, "stage": stage_id}) + if risk_id not in referenced_risks: + findings.append({"kind": "unreferenced-risk", "risk": risk_id}) + for criterion in risk.get("criteria", []): + if criterion not in criterion_ids: + findings.append({"kind": "risk-criterion-missing", "risk": risk_id, "criterion": criterion}) + for control in [*risk.get("controls", []), *risk.get("detection", [])]: + referenced_controls.add(control) + if control not in control_ids: + findings.append({"kind": "risk-control-missing", "risk": risk_id, "control": control}) + if not str(risk.get("mitigation", "")).strip() or not str(risk.get("rollback", "")).strip(): + findings.append({"kind": "risk-response-incomplete", "risk": risk_id}) + + for control in sorted(control_ids - referenced_controls): + findings.append({"kind": "control-without-behavior", "control": control}) + for gap in trace.get("gaps", []): + if gap.get("critical"): + findings.append({"kind": "critical-traceability-gap", "gap": gap}) + + if ready and not requirements: + findings.append({"kind": "ready-plan-without-requirements"}) + if ready and not criteria: + findings.append({"kind": "ready-plan-without-criteria"}) + + payload = { + "schema_version": "1.1.0", + "generated_at": utc_now(), + "validator": "validate_plan", + "result": "PASS" if not findings else "FAIL", + "findings": findings, + "plan_status": plan_status, + "stage_ids": sorted(stages), + "requirement_count": len(requirement_ids), + "criterion_count": len(criterion_ids), + "control_count": len(control_ids), + "risk_count": len(risks), + } + if write_report: + atomic_write_json(run / "reports/validation/plan.json", payload) + return {"ok": not findings, **payload} + + +def main() -> int: + parser = argparse.ArgumentParser(description="Validate PlanAnvil PLAN.md, stages, identifiers, and traceability") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + parser.add_argument("--run-root", type=Path, required=True) + parser.add_argument("--no-write-report", action="store_true") + args = parser.parse_args() + payload = validate_plan(args.planning, args.run_root, write_report=not args.no_write_report) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/scripts/validate_profile.py b/.agents/skills/plan-anvil/scripts/validate_profile.py new file mode 100644 index 0000000..8f38205 --- /dev/null +++ b/.agents/skills/plan-anvil/scripts/validate_profile.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import argparse +import re +from pathlib import Path +from typing import Any + +from common import cli_main, discover_repo, emit, is_ignored, is_tracked, privacy_findings, sha256_file + + +REQUIRED_REPOSITORY_HEADINGS = [ + "# PlanAnvil Repository Profile", + "## Repository structure and architecture", + "## Languages, runtimes, and dependency managers", + "## Build, test, lint, and static-analysis commands", + "## Git conventions and quality gates", + "## Project instruction map", + "## Deployment, state, and rollback rules", + "## Risk and activation policy", + "## Evidence and freshness", +] + +REQUIRED_LOCAL_HEADINGS = [ + "# PlanAnvil Local Profile", + "## Local commands and services", + "## Health checks, switching, and rollback", + "## Permission and push-trigger implications", +] + + +def validate_profile(planning: Path) -> dict[str, Any]: + repo = discover_repo(planning) + profile = repo / ".pursue/SYSTEM_PROFILE.md" + local = repo / ".pursue/SYSTEM_PROFILE.local.md" + findings: list[dict[str, Any]] = [] + + if not profile.is_file(): + findings.append({"kind": "missing", "path": ".pursue/SYSTEM_PROFILE.md"}) + if not local.is_file(): + findings.append({"kind": "missing", "path": ".pursue/SYSTEM_PROFILE.local.md"}) + + if profile.is_file(): + text = profile.read_text(encoding="utf-8") + for heading in REQUIRED_REPOSITORY_HEADINGS: + if heading not in text: + findings.append({"kind": "missing-heading", "path": ".pursue/SYSTEM_PROFILE.md", "heading": heading}) + status_match = re.search(r"(?m)^- Profile status: `([^`]+)`$", text) + if not status_match or status_match.group(1) not in {"VALID", "VALID_WITH_UNKNOWNS", "PARTIALLY_STALE", "STALE", "UNVERIFIABLE"}: + findings.append({"kind": "invalid-profile-status", "path": ".pursue/SYSTEM_PROFILE.md"}) + elif status_match.group(1) in {"STALE", "UNVERIFIABLE"}: + findings.append({"kind": "blocking-profile-status", "path": ".pursue/SYSTEM_PROFILE.md", "status": status_match.group(1)}) + hash_entries = re.findall(r"(?m)^- `([^`]+)`: `(sha256:[0-9a-f]{64})`$", text) + for relative, expected in hash_entries: + candidate = repo / relative + try: + candidate.resolve().relative_to(repo.resolve()) + except ValueError: + findings.append({"kind": "profile-evidence-path-escape", "path": relative}) + continue + if not candidate.is_file(): + findings.append({"kind": "profile-evidence-missing", "path": relative}) + elif sha256_file(candidate) != expected: + findings.append({"kind": "profile-evidence-stale", "path": relative}) + for item in privacy_findings(Path(".pursue/SYSTEM_PROFILE.md"), text): + findings.append(item) + + if local.is_file(): + text = local.read_text(encoding="utf-8") + for heading in REQUIRED_LOCAL_HEADINGS: + if heading not in text: + findings.append({"kind": "missing-heading", "path": ".pursue/SYSTEM_PROFILE.local.md", "heading": heading}) + secret_findings = [item for item in privacy_findings(Path(".pursue/SYSTEM_PROFILE.local.md"), text) if item["kind"] != "absolute-path"] + findings.extend(secret_findings) + if not is_ignored(repo, local): + findings.append({"kind": "not-ignored", "path": ".pursue/SYSTEM_PROFILE.local.md"}) + if is_tracked(repo, local): + findings.append({"kind": "tracked-local-state", "path": ".pursue/SYSTEM_PROFILE.local.md"}) + + return { + "ok": not findings, + "result": "PASS" if not findings else "FAIL", + "findings": findings, + } + + +def main() -> int: + parser = argparse.ArgumentParser(description="Validate PlanAnvil repository and local profiles") + parser.add_argument("--planning", type=Path, default=Path.cwd()) + args = parser.parse_args() + payload = validate_profile(args.planning) + return emit(payload, exit_code=0 if payload["ok"] else 2) + + +if __name__ == "__main__": + cli_main(main) diff --git a/.agents/skills/plan-anvil/templates/PLAN.md b/.agents/skills/plan-anvil/templates/PLAN.md new file mode 100644 index 0000000..00b1446 --- /dev/null +++ b/.agents/skills/plan-anvil/templates/PLAN.md @@ -0,0 +1,88 @@ +# Implementation Plan: {{TITLE}} + +## Identity + +- Plan ID: `{{PLAN_ID}}` +- Run ID: `{{RUN_ID}}` +- Contract: PlanAnvil 2.1 +- Artifact schema: 1.1.0 +- Base branch: `{{BASE_BRANCH}}` +- Base SHA: `{{BASE_SHA}}` +- Planning branch: `{{PLANNING_BRANCH}}` + +## Original goal + +{{GOAL}} + +## Outcome and definition of done + +{{OUTCOME_AND_DONE}} + +## Generator stop boundary + +PlanAnvil generated and validated this plan. It must not implement any stage, modify product code or tests, deploy, migrate, switch a live system, or integrate the base branch in this run. + +## Separate execution-run prompt + +Use this approved `PLAN.md` as the immutable execution contract in a separate Codex run. Reconcile `manifest.json`, `state.json`, `local-state.json`, the latest valid checkpoint, profiles, instruction map, and Git state before acting. Execute only the next approved action, preserve all gates and approvals, and stop on any mismatch. + +## Scope + +{{SCOPE}} + +## Exclusions + +{{EXCLUSIONS}} + +## Assumptions, unknowns, and evidence + +{{ASSUMPTIONS_UNKNOWNS_EVIDENCE}} + +## Applicable instructions + +{{INSTRUCTIONS}} + +## System and change analysis + +{{SYSTEM_ANALYSIS}} + +## Dependencies and classification + +{{DEPENDENCIES_AND_CLASSIFICATION}} + +## Stable stage index + +{{STAGE_INDEX}} + +## Traceability + +{{TRACEABILITY_SUMMARY}} + +## Testing and independent verification + +{{TESTING}} + +## Git, integration, and control-root rules + +{{GIT_AND_INTEGRATION}} + +## Production verification, switching, and approvals + +{{PRODUCTION_VERIFICATION}} + +## Rollback and recovery + +{{ROLLBACK_AND_RECOVERY}} + +## Resume and reconciliation + +{{RESUME}} + +## Status and next action + +- Status: `{{STATUS}}` +- Next action: `{{NEXT_ACTION}}` + +## Final report requirements + +{{FINAL_REPORT}} diff --git a/.agents/skills/plan-anvil/templates/STAGE.md b/.agents/skills/plan-anvil/templates/STAGE.md new file mode 100644 index 0000000..f6fd44d --- /dev/null +++ b/.agents/skills/plan-anvil/templates/STAGE.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "{{STAGE_ID}}" +outcome: "{{OUTCOME}}" +classification: "{{CLASSIFICATION}}" +requirements: [{{REQUIREMENTS}}] +criteria: [{{CRITERIA}}] +risks: [{{RISKS}}] +dependencies: [{{DEPENDENCIES}}] +applicable_instructions: [{{APPLICABLE_INSTRUCTIONS}}] +allowed_write_paths: [{{ALLOWED_WRITE_PATHS}}] +--- + +# {{STAGE_ID}} — {{TITLE}} + +## Outcome + +{{OUTCOME_DETAIL}} + +## Scope + +{{SCOPE}} + +## Exclusions + +{{EXCLUSIONS}} + +## Affected paths or discovery procedure + +{{PATHS}} + +## Applicable instructions + +{{INSTRUCTIONS}} + +## Dependencies and conflicts + +{{DEPENDENCIES_AND_CONFLICTS}} + +## Acceptance criteria + +{{ACCEPTANCE_CRITERIA}} + +## Risks and controls + +{{RISKS_AND_CONTROLS}} + +## Evidence cycle + +{{EVIDENCE_CYCLE}} + +## Modifier and verifier roles + +{{ROLES}} + +## Commit and checkpoint + +{{COMMIT_AND_CHECKPOINT}} + +## Rollback + +{{ROLLBACK}} diff --git a/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.local.md b/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.local.md new file mode 100644 index 0000000..03333ba --- /dev/null +++ b/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.local.md @@ -0,0 +1,19 @@ +# PlanAnvil Local Profile + +This ignored file contains non-secret machine-specific locators. Never commit it. + +- Planning worktree: `{{PLANNING_WORKTREE}}` +- Source worktree: `{{SOURCE_WORKTREE}}` +- Generated at: `{{GENERATED_AT}}` + +## Local commands and services + +{{LOCAL_COMMANDS}} + +## Health checks, switching, and rollback + +{{LOCAL_OPERATIONS}} + +## Permission and push-trigger implications + +{{PERMISSIONS}} diff --git a/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.md b/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.md new file mode 100644 index 0000000..b9898fd --- /dev/null +++ b/.agents/skills/plan-anvil/templates/SYSTEM_PROFILE.md @@ -0,0 +1,38 @@ +# PlanAnvil Repository Profile + +- Profile status: `{{STATUS}}` +- Generated at: `{{GENERATED_AT}}` +- Repository fingerprint: `{{FINGERPRINT}}` +- Evidence base SHA: `{{BASE_SHA}}` + +## Repository structure and architecture + +{{STRUCTURE}} + +## Languages, runtimes, and dependency managers + +{{RUNTIMES}} + +## Build, test, lint, and static-analysis commands + +{{COMMANDS}} + +## Git conventions and quality gates + +{{GIT_RULES}} + +## Project instruction map + +{{INSTRUCTION_MAP}} + +## Deployment, state, and rollback rules + +{{DEPLOYMENT}} + +## Risk and activation policy + +{{RISK_POLICY}} + +## Evidence and freshness + +{{EVIDENCE}} diff --git a/.agents/skills/plan-anvil/templates/analysis.md b/.agents/skills/plan-anvil/templates/analysis.md new file mode 100644 index 0000000..563a72d --- /dev/null +++ b/.agents/skills/plan-anvil/templates/analysis.md @@ -0,0 +1,29 @@ +# Goal analysis + +## Requested outcome + +{{OUTCOME}} + +## Repository evidence + +{{EVIDENCE}} + +## Change classification and risk + +{{CLASSIFICATION}} + +## Affected paths and boundaries + +{{AFFECTED_PATHS}} + +## Assumptions + +{{ASSUMPTIONS}} + +## Unknowns and verification + +{{UNKNOWNS}} + +## Recommended stage boundaries + +{{STAGES}} diff --git a/.agents/skills/plan-anvil/templates/blind-review.md b/.agents/skills/plan-anvil/templates/blind-review.md new file mode 100644 index 0000000..8ba710b --- /dev/null +++ b/.agents/skills/plan-anvil/templates/blind-review.md @@ -0,0 +1,29 @@ +# Blind Plan Review + +## Result + +`{{RESULT}}` + +## Scope reviewed + +{{SCOPE}} + +## Findings + +{{FINDINGS}} + +## Traceability and acceptance review + +{{TRACEABILITY}} + +## Testing, rollback, and approvals + +{{CONTROLS}} + +## Generator/executor boundary + +{{BOUNDARY}} + +## Conclusion + +{{CONCLUSION}} diff --git a/.agents/skills/plan-anvil/templates/final-report.md b/.agents/skills/plan-anvil/templates/final-report.md new file mode 100644 index 0000000..476d91d --- /dev/null +++ b/.agents/skills/plan-anvil/templates/final-report.md @@ -0,0 +1,19 @@ +# PlanAnvil Final Report + +- Status: `{{STATUS}}` +- Planning branch: `{{PLANNING_BRANCH}}` +- Planning commit: `{{COMMIT_SHA}}` +- Plan: `{{PLAN_PATH}}` +- Deterministic validation: `{{VALIDATION_RESULT}}` +- Blind review: `{{REVIEW_RESULT}}` +- Comparison: `{{COMPARISON_RESULT}}` + +## Assumptions and unknowns + +{{ASSUMPTIONS_AND_UNKNOWNS}} + +## Next run + +{{EXECUTION_PROMPT}} + +No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md. diff --git a/.agents/skills/plan-anvil/tests/_helpers.py b/.agents/skills/plan-anvil/tests/_helpers.py new file mode 100644 index 0000000..3e28455 --- /dev/null +++ b/.agents/skills/plan-anvil/tests/_helpers.py @@ -0,0 +1,391 @@ +from __future__ import annotations + +import json +import os +import shutil +import subprocess +import sys +import tempfile +from contextlib import contextmanager +from pathlib import Path +from typing import Any + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +if str(SCRIPTS) not in sys.path: + sys.path.insert(0, str(SCRIPTS)) + +from common import atomic_write_json, load_json, make_plan_id, slugify +from create_planning_worktree import create_planning_worktree +from profile_repository import profile_repository +from record_analysis import record_analysis +from scaffold_run import scaffold_run +from seal_artifacts import seal_artifacts +from test_git_capabilities import probe_git_capabilities +from transition_state import transition_state + + +def run(*args: str, cwd: Path, check: bool = True, env: dict[str, str] | None = None) -> subprocess.CompletedProcess[str]: + result = subprocess.run( + list(args), + cwd=cwd, + env=env, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=False, + ) + if check and result.returncode != 0: + raise AssertionError(f"command failed: {args}\nstdout={result.stdout}\nstderr={result.stderr}") + return result + + +def init_repo(path: Path, *, files: dict[str, str] | None = None, identity: bool = True) -> Path: + path.mkdir(parents=True) + run("git", "init", "-b", "main", cwd=path) + if identity: + run("git", "config", "user.name", "PlanAnvil Test", cwd=path) + run("git", "config", "user.email", "plananvil@example.invalid", cwd=path) + run("git", "config", "commit.gpgsign", "false", cwd=path) + defaults = { + "README.md": "# Fixture\n", + "AGENTS.md": "# Instructions\n\n- Run tests before committing.\n- Never expose secrets.\n", + "src/app.py": "def value():\n return 1\n", + "tests/test_app.py": "def test_value():\n assert True\n", + } + for rel, content in (files or defaults).items(): + target = path / rel + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(content, encoding="utf-8", newline="\n") + run("git", "add", ".", cwd=path) + run("git", "commit", "-m", "fixture", cwd=path) + return path + + +def cleanup_worktree(source: Path, planning: Path, branch: str) -> None: + if planning.exists(): + run("git", "worktree", "remove", "--force", str(planning), cwd=source, check=False) + run("git", "branch", "-D", branch, cwd=source, check=False) + + +def start_fixture(tmp: Path, goal: str = "Reject an empty display name") -> dict[str, Any]: + source = init_repo(tmp / "source") + plan_id = make_plan_id() + slug = slugify(goal) + probe = probe_git_capabilities(source, f"test-{plan_id}", tmp / "probes") + assert probe["ok"], probe + planning_info = create_planning_worktree( + source, + plan_id=plan_id, + slug=slug, + capability_report=probe, + destination=tmp / "planning", + ) + planning = Path(planning_info["planning_worktree"]) + profile_repository(planning, source) + scaffold = scaffold_run( + planning, + source, + plan_id=plan_id, + run_id=planning_info["run_id"], + slug=slug, + goal=goal, + base_branch=planning_info["base_branch"], + base_sha=planning_info["base_sha"], + capability_report=probe, + ) + return { + "source": source, + "planning": planning, + "branch": planning_info["planning_branch"], + "run_root": planning / scaffold["run_root"], + "plan_id": plan_id, + "run_id": planning_info["run_id"], + } + + +def author_valid_plan(context: dict[str, Any]) -> None: + run_root: Path = context["run_root"] + instruction_map = load_json(run_root / "evidence/instruction-map.json") + analysis_md = context["planning"].parent / f"{context['run_id']}-analysis.md" + analysis_json = context["planning"].parent / f"{context['run_id']}-analysis.json" + analysis_md.write_text( + """# Goal analysis + +## Requested outcome + +Reject empty display names without changing public API shape. + +## Repository evidence + +The repository contains one implementation module, focused tests, and applicable instructions. + +## Change classification and risk + +The change is isolated and low risk. + +## Affected paths and boundaries + +Only mapped implementation and test paths may change in the later execution run. + +## Assumptions + +Existing normalization behavior is preserved. + +## Unknowns and verification + +Whitespace behavior is verified during the expected-red stage and is not a critical unknown. + +## Recommended stage boundaries + +Use one behavior-changing stage with an independent verifier. +""", + encoding="utf-8", + newline="\n", + ) + atomic_write_json( + analysis_json, + { + "classification": "ISOLATED", + "risk": "LOW", + "affected_paths": instruction_map["affected_paths"], + "evidence": [ + ".pursue/SYSTEM_PROFILE.md", + f".pursue/runs/{context['run_id']}/evidence/original-goal.md", + f".pursue/runs/{context['run_id']}/evidence/instruction-map.json", + ], + "assumptions": [ + { + "text": "The existing validator and focused tests define the affected behavior.", + "confidence": "VERIFIED", + "evidence": ["src/app.py", "tests/test_app.py"], + } + ], + "unknowns": [ + { + "text": "Exact whitespace normalization is confirmed before implementation.", + "critical": False, + "verification": "Run the focused baseline and inspect current tests.", + } + ], + }, + ) + result = record_analysis( + context["planning"], + run_root, + analysis_markdown=analysis_md, + analysis_data=analysis_json, + ) + assert result["ok"], result + plan_id = context["plan_id"] + run_id = context["run_id"] + manifest = load_json(run_root / "manifest.json") + plan = f"""# Implementation Plan: Empty display name validation + +## Identity + +- Plan ID: `{plan_id}` +- Run ID: `{run_id}` +- Contract: PlanAnvil 2.1 +- Artifact schema: 1.1.0 +- Base branch: `{manifest['repository']['base_branch']}` +- Base SHA: `{manifest['repository']['base_sha']}` +- Planning branch: `{manifest['repository']['planning_branch']}` + +## Original goal + +Reject an empty display name. + +## Outcome and definition of done + +Empty and whitespace-only names follow the existing normalization policy, valid names remain accepted, and focused automated tests prove the behavior. + +## Generator stop boundary + +PlanAnvil generates and validates this contract only. It does not modify product code or tests and does not execute a stage. + +## Separate execution-run prompt + +In a separate Codex run, load this plan and canonical state, reconcile Git and the latest checkpoint, then execute only the next approved stage while preserving every gate. + +## Scope + +Validation behavior and focused regression tests. + +## Exclusions + +Public API renaming, UI copy changes, deployment, and data migration. + +## Assumptions, unknowns, and evidence + +The existing validator and unit-test paths are verified by repository inspection. Whitespace normalization is confirmed during the stage discovery step before changing behavior. + +## Applicable instructions + +Read and obey the hashed instruction map in `evidence/instruction-map.json`. + +## System and change analysis + +One validator controls the behavior. No persistent state, network boundary, or deployment flow changes. + +## Dependencies and classification + +Classification is LOW risk and behavior-changing. The stage depends on the existing green unit-test baseline. + +## Stable stage index + +- `STAGE-01` — reject empty display names while preserving valid input. + +## Traceability + +`REQ-01-01 → STAGE-01 → AC-01-01 → RISK-01-01 → CTRL-01-01 → automated test evidence`. + +## Testing and independent verification + +Run a green baseline, add an expected-red regression test, implement the minimum behavior, run the focused and full suites, then obtain independent read-only verification. + +## Git, integration, and control-root rules + +Use `pursue/{plan_id}/display-name` for task work and `pursue/integration/{plan_id}/display-name` only when integration is needed. Control artifacts remain in the planning worktree. One modifier acts at a time. + +## Production verification, switching, and approvals + +No live switch is required. Base-branch merge or push requires explicit user approval. + +## Rollback and recovery + +Revert the single coherent implementation commit if verification fails. Reconcile canonical state and Git before resuming. + +## Resume and reconciliation + +Read manifest, state, local state, profiles, instruction map, latest checkpoint, and Git state. Stop on any mismatch. + +## Status and next action + +- Status: `PLAN_READY` +- Next action: `Start a separate execution run for STAGE-01.` + +## Final report requirements + +Report tests, independent verification, commit, remaining risks, and approvals. No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md. +""" + (run_root / "PLAN.md").write_text(plan, encoding="utf-8", newline="\n") + + instruction = instruction_map["files"][0] + stage = f"""--- +schema_version: "1.1.0" +stage_id: "STAGE-01" +outcome: "Empty display names are rejected consistently." +classification: "BEHAVIOR" +requirements: ["REQ-01-01"] +criteria: ["AC-01-01"] +risks: ["RISK-01-01"] +dependencies: [] +applicable_instructions: [{{"path": {instruction["path"]!r}, "sha256": {instruction["sha256"]!r}}}] +allowed_write_paths: ["src/**", "tests/**"] +--- + +# STAGE-01 — Reject empty display names + +## Outcome + +The validator rejects empty input without regressing valid names. + +## Scope + +Validator behavior and focused tests. + +## Exclusions + +API renaming, UI copy, persistence, and deployment. + +## Affected paths or discovery procedure + +Confirm the current validator and its nearest tests before editing; write only within the approved paths. + +## Applicable instructions + +Read every instruction file recorded for the affected paths and verify its hash. + +## Dependencies and conflicts + +Requires a green baseline. Stop on instruction or behavior conflicts. + +## Acceptance criteria + +- `AC-01-01`: empty and whitespace-only names follow the verified normalization policy and valid names remain accepted. + +## Risks and controls + +- `RISK-01-01` is controlled by `CTRL-01-01`, focused regression tests, and the full suite. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +Jenny owns approved tests, one implementation agent owns approved production paths, and the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent implementation-and-test commit and `CHECKPOINT-01-VERIFIED`. + +## Rollback + +Revert the stage commit and restore the preceding valid checkpoint. +""" + (run_root / "stages/STAGE-01.md").write_text(stage, encoding="utf-8", newline="\n") + + traceability = { + "schema_version": "1.1.0", + "requirements": [ + { + "id": "REQ-01-01", + "text": "The validator rejects empty display names without rejecting valid names.", + "critical": True, + "stages": ["STAGE-01"], + "criteria": ["AC-01-01"], + } + ], + "criteria": [ + { + "id": "AC-01-01", + "stage": "STAGE-01", + "risks": ["RISK-01-01"], + "controls": ["CTRL-01-01"], + "evidence_type": "AUTOMATED_TEST", + "evidence": [], + } + ], + "controls": [ + { + "id": "CTRL-01-01", + "description": "Focused regression and full-suite verification.", + "verification": "Expected-red failure followed by focused and full green results.", + } + ], + "gaps": [], + } + atomic_write_json(run_root / "traceability.json", traceability) + + risk = { + "schema_version": "1.1.0", + "id": "RISK-01-01", + "stage": "STAGE-01", + "level": "LOW", + "description": "Normalization could reject valid names.", + "source": "Repository analysis", + "affected_components": ["validator"], + "probability": "LOW", + "impact": "MEDIUM", + "detection": ["CTRL-01-01"], + "criteria": ["AC-01-01"], + "controls": ["CTRL-01-01"], + "mitigation": "Preserve verified normalization and test valid examples.", + "rollback": "Revert the stage commit.", + "status": "OPEN", + } + atomic_write_json(run_root / "risks/RISK-01-01.json", risk) + + sealed = seal_artifacts(context["planning"], run_root) + assert sealed["ok"], sealed diff --git a/.agents/skills/plan-anvil/tests/test_analysis_and_review_integrity.py b/.agents/skills/plan-anvil/tests/test_analysis_and_review_integrity.py new file mode 100644 index 0000000..5b15f58 --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_analysis_and_review_integrity.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from _helpers import author_valid_plan, cleanup_worktree, start_fixture + +from common import PlanAnvilError, atomic_write_json, load_json +from compare_review import compare_review +from map_instructions import map_instructions +from prepare_review_bundle import prepare_review_bundle +from record_analysis import record_analysis +from record_blind_review import record_blind_review +from validate_all import validate_all + + +class AnalysisAndReviewIntegrityTests(unittest.TestCase): + def test_critical_unknown_blocks_before_plan_authoring(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + context = start_fixture(root, "Permanently remove all user data") + try: + map_instructions( + context["planning"], + affected_paths=["src/app.py"], + output=context["run_root"] / "evidence/instruction-map.json", + ) + markdown = root / "analysis.md" + markdown.write_text( + "# Goal analysis\n\nDeletion scope and retention policy are unknown.\n", + encoding="utf-8", + newline="\n", + ) + data = root / "analysis.json" + atomic_write_json( + data, + { + "classification": "STATEFUL", + "risk": "HIGH", + "affected_paths": ["src/app.py"], + "evidence": [f".pursue/runs/{context['run_id']}/evidence/original-goal.md"], + "assumptions": [], + "unknowns": [ + { + "text": "Authoritative data-retention scope is unknown.", + "critical": True, + "verification": "Obtain the retention policy and approval owner.", + } + ], + }, + ) + result = record_analysis( + context["planning"], context["run_root"], analysis_markdown=markdown, analysis_data=data + ) + self.assertFalse(result["ok"]) + self.assertEqual(result["result"], "BLOCKED_BY_CRITICAL_UNKNOWN") + state = load_json(context["run_root"] / "state.json") + self.assertEqual(state["status"], "BLOCKED") + self.assertIn("BLOCKED_BY_CRITICAL_UNKNOWN", state["open_blockers"]) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + def test_review_bundle_rejects_tampering_and_failed_review_stops(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + context = start_fixture(root) + try: + map_instructions( + context["planning"], + affected_paths=["src/app.py", "tests/test_app.py"], + output=context["run_root"] / "evidence/instruction-map.json", + ) + author_valid_plan(context) + validation = validate_all( + context["planning"], context["run_root"], source=context["source"], advance_state=True + ) + self.assertTrue(validation["ok"], validation) + prepare_review_bundle(context["planning"], context["run_root"]) + + plan = context["run_root"] / "PLAN.md" + original = plan.read_text(encoding="utf-8") + plan.write_text(original + "\nTampered after bundling.\n", encoding="utf-8", newline="\n") + review = root / "review.md" + review.write_text("# Blind Plan Review\n\n## Result\n\n`PASS`\n", encoding="utf-8") + with self.assertRaises(PlanAnvilError) as raised: + record_blind_review( + context["planning"], context["run_root"], review_markdown=review, result="PASS" + ) + self.assertEqual(raised.exception.code, "REVIEW_BUNDLE_CHANGED") + plan.write_text(original, encoding="utf-8", newline="\n") + + failed_review = root / "failed-review.md" + failed_review.write_text( + "# Blind Plan Review\n\n## Result\n\n`FAIL`\n\n## Findings\n\nRollback evidence is insufficient.\n", + encoding="utf-8", + newline="\n", + ) + findings = root / "findings.json" + atomic_write_json( + findings, + [{"id": "FINDING-01", "severity": "HIGH", "summary": "Rollback evidence is insufficient."}], + ) + record_blind_review( + context["planning"], + context["run_root"], + review_markdown=failed_review, + result="FAIL", + findings_file=findings, + ) + comparison = compare_review(context["planning"], context["run_root"]) + self.assertFalse(comparison["ok"]) + self.assertEqual(load_json(context["run_root"] / "state.json")["status"], "FAILED") + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_boundary_and_privacy.py b/.agents/skills/plan-anvil/tests/test_boundary_and_privacy.py new file mode 100644 index 0000000..82ca669 --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_boundary_and_privacy.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from _helpers import author_valid_plan, cleanup_worktree, start_fixture + +from map_instructions import map_instructions +from validate_plan import validate_plan + + +class BoundaryAndPrivacyTests(unittest.TestCase): + def test_generator_executor_boundary_violation_is_rejected(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + context = start_fixture(Path(tmp)) + try: + map_instructions( + context["planning"], + affected_paths=["src/app.py"], + output=context["run_root"] / "evidence/instruction-map.json", + ) + author_valid_plan(context) + plan = context["run_root"] / "PLAN.md" + plan.write_text( + plan.read_text(encoding="utf-8") + + "\nAfter generating the plan, immediately start Jim and implement STAGE-01.\n", + encoding="utf-8", + newline="\n", + ) + result = validate_plan(context["planning"], context["run_root"]) + self.assertFalse(result["ok"]) + self.assertTrue( + any(item["kind"] == "generator-executor-boundary-violation" for item in result["findings"]), + result, + ) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_common_and_schema.py b/.agents/skills/plan-anvil/tests/test_common_and_schema.py new file mode 100644 index 0000000..7be3b02 --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_common_and_schema.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +import json +import sys +import tempfile +import unittest +from pathlib import Path + +from _helpers import SCRIPTS + +from common import atomic_write_json, canonical_file_is_valid, privacy_findings, sha256_text +from schema_validator import validate_file + + +class CommonAndSchemaTests(unittest.TestCase): + def test_atomic_json_is_canonical(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "value.json" + atomic_write_json(path, {"b": 2, "a": 1}) + self.assertEqual(path.read_text(encoding="utf-8"), '{\n "a": 1,\n "b": 2\n}\n') + self.assertTrue(canonical_file_is_valid(path)) + + def test_privacy_finds_secret_and_absolute_path(self) -> None: + findings = privacy_findings(Path("x.md"), "password=abcdefghijklmnop\n/home/alice/repo\n") + kinds = {item["kind"] for item in findings} + self.assertIn("generic-token", kinds) + self.assertIn("absolute-path", kinds) + + def _valid_manifest(self) -> dict: + return { + "schema_version": "1.1.0", + "plan_id": "PG-20260712-143000-A1B2", + "run_id": "20260712T143000Z_PG-20260712-143000-A1B2_example", + "created_at": "2026-07-12T14:30:00Z", + "generator_version": "0.1.0", + "repository": { + "fingerprint": sha256_text("repo"), + "base_branch": "main", + "base_sha": "a" * 40, + "planning_branch": "pursue/plan/PG-20260712-143000-A1B2/example", + }, + "paths": { + "run_root": ".pursue/runs/20260712T143000Z_PG-20260712-143000-A1B2_example", + "plan": "PLAN.md", + "state": "state.json", + "compliance": "compliance.json", + "traceability": "traceability.json", + "repository_profile": ".pursue/SYSTEM_PROFILE.md", + "local_state": "local-state.json", + }, + "contract_versions": { + "implementation_spec": "2.1", + "plan_contract": "1.0.0", + "artifact_schema": "1.1.0", + }, + } + + def test_manifest_schema_rejects_absolute_path(self) -> None: + skill = SCRIPTS.parent + schema = skill / "schemas/manifest.schema.json" + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "manifest.json" + value = self._valid_manifest() + value["paths"]["run_root"] = "/tmp/run" + atomic_write_json(path, value) + errors = validate_file(path, schema) + self.assertTrue(any("forbidden" in item or "pattern" in item for item in errors), errors) + + def test_manifest_schema_rejects_relative_traversal(self) -> None: + schema = SCRIPTS.parent / "schemas/manifest.schema.json" + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "manifest.json" + value = self._valid_manifest() + value["paths"]["run_root"] = "../outside" + atomic_write_json(path, value) + errors = validate_file(path, schema) + self.assertTrue(any("forbidden" in item or "pattern" in item for item in errors), errors) + + def test_skill_metadata_requires_explicit_activation(self) -> None: + skill_root = SCRIPTS.parent + skill = (skill_root / "SKILL.md").read_text(encoding="utf-8") + metadata = (skill_root / "agents/openai.yaml").read_text(encoding="utf-8") + self.assertIn("Use only when explicitly invoked as $plan-anvil", skill) + self.assertIn("allow_implicit_invocation: false", metadata) + self.assertNotIn("implement the plan in this run", skill.lower()) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_hooks_and_edge_states.py b/.agents/skills/plan-anvil/tests/test_hooks_and_edge_states.py new file mode 100644 index 0000000..6b5a79c --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_hooks_and_edge_states.py @@ -0,0 +1,182 @@ +from __future__ import annotations + +import json +import subprocess +import tempfile +import unittest +from pathlib import Path + +from _helpers import init_repo, run +from common import PlanAnvilError, atomic_write_json +from preflight import preflight +from transition_state import transition_state + +ROOT = Path(__file__).resolve().parents[4] +HOOKS = ROOT / ".codex/hooks" + + +class HookAndEdgeStateTests(unittest.TestCase): + def _hook(self, script: str, repo: Path, event: dict) -> dict: + result = subprocess.run( + ["python3", str(HOOKS / script)], + cwd=repo, + input=json.dumps(event), + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + return json.loads(result.stdout) if result.stdout.strip() else {} + + def _active_repo(self, root: Path, *, mode: str = "PLAN_GENERATION", checkpoint=None) -> Path: + repo = init_repo(root / "repo") + state = { + "schema_version": "1.1.0", + "revision": 1, + "updated_at": "2026-07-12T12:00:00Z", + "mode": mode, + "status": "PROFILE_READY" if mode == "PLAN_GENERATION" else "EXECUTION_IN_PROGRESS", + "current_stage": None, + "current_phase": "DISCOVER_INSTRUCTIONS", + "next_action": {"type": "MAP_INSTRUCTIONS", "target": "evidence/instruction-map.json"}, + "last_checkpoint": checkpoint, + "open_blockers": [], + "artifact_hashes": {}, + } + path = repo / ".pursue/runs/run/state.json" + path.parent.mkdir(parents=True) + atomic_write_json(path, state) + return repo + + def test_hook_denies_destructive_git_and_product_patch(self) -> None: + with tempfile.TemporaryDirectory() as directory: + repo = self._active_repo(Path(directory)) + common = {"cwd": str(repo), "hook_event_name": "PreToolUse", "tool_name": "Bash"} + denied = self._hook( + "plan-anvil-guard.py", + repo, + {**common, "tool_input": {"command": "git reset --hard HEAD"}}, + ) + self.assertEqual(denied["hookSpecificOutput"]["permissionDecision"], "deny") + allowed = self._hook( + "plan-anvil-guard.py", + repo, + {**common, "tool_input": {"command": "git status --short"}}, + ) + self.assertEqual(allowed, {}) + + patch = "*** Begin Patch\n*** Update File: src/app.py\n@@\n-old\n+new\n*** End Patch\n" + denied_patch = self._hook( + "plan-anvil-guard.py", + repo, + { + "cwd": str(repo), + "hook_event_name": "PreToolUse", + "tool_name": "apply_patch", + "tool_input": {"command": patch}, + }, + ) + self.assertEqual(denied_patch["hookSpecificOutput"]["permissionDecision"], "deny") + denied_write = self._hook( + "plan-anvil-guard.py", + repo, + { + "cwd": str(repo), + "hook_event_name": "PreToolUse", + "tool_name": "Write", + "tool_input": {"file_path": "src/app.py", "content": "changed"}, + }, + ) + self.assertEqual(denied_write["hookSpecificOutput"]["permissionDecision"], "deny") + + def test_hook_allows_control_patch_and_compaction_requires_checkpoint(self) -> None: + with tempfile.TemporaryDirectory() as directory: + repo = self._active_repo(Path(directory)) + patch = "*** Begin Patch\n*** Update File: .pursue/runs/run/PLAN.md\n@@\n-old\n+new\n*** End Patch\n" + allowed = self._hook( + "plan-anvil-guard.py", + repo, + { + "cwd": str(repo), + "hook_event_name": "PreToolUse", + "tool_name": "apply_patch", + "tool_input": {"command": patch}, + }, + ) + self.assertEqual(allowed, {}) + allowed_write = self._hook( + "plan-anvil-guard.py", + repo, + { + "cwd": str(repo), + "hook_event_name": "PreToolUse", + "tool_name": "Write", + "tool_input": {"file_path": ".pursue/runs/run/PLAN.md", "content": "plan"}, + }, + ) + self.assertEqual(allowed_write, {}) + + with tempfile.TemporaryDirectory() as directory: + repo = self._active_repo(Path(directory), mode="PLAN_EXECUTION") + blocked = self._hook( + "plan-anvil-compaction.py", + repo, + {"cwd": str(repo), "hook_event_name": "PreCompact", "trigger": "auto"}, + ) + self.assertFalse(blocked["continue"]) + + def test_detached_head_with_multiple_containing_branches_is_ambiguous(self) -> None: + with tempfile.TemporaryDirectory() as directory: + repo = init_repo(Path(directory) / "repo") + run("git", "branch", "other", cwd=repo) + sha = run("git", "rev-parse", "HEAD", cwd=repo).stdout.strip() + run("git", "checkout", "--detach", sha, cwd=repo) + result = preflight(repo) + self.assertFalse(result["ok"]) + self.assertEqual(result["result"], "GIT_BASE_AMBIGUOUS") + self.assertEqual(result["plan_status"], "BLOCKED_BY_GIT_STATE") + + def test_state_revision_and_order_are_enforced(self) -> None: + with tempfile.TemporaryDirectory() as directory: + state_path = Path(directory) / "state.json" + atomic_write_json( + state_path, + { + "schema_version": "1.1.0", + "revision": 0, + "updated_at": "2026-07-12T12:00:00Z", + "mode": "PLAN_GENERATION", + "status": "PROFILE_READY", + "current_stage": None, + "current_phase": "DISCOVER_INSTRUCTIONS", + "next_action": {"type": "MAP_INSTRUCTIONS", "target": "evidence/instruction-map.json"}, + "last_checkpoint": None, + "open_blockers": [], + "artifact_hashes": {}, + }, + ) + with self.assertRaises(PlanAnvilError) as stale: + transition_state( + state_path, + expected_revision=1, + new_status="INSTRUCTION_MAP_READY", + phase="ANALYZE_GOAL", + next_action_type="ANALYZE_GOAL", + next_action_target="PLAN.md", + ) + self.assertEqual(stale.exception.code, "STALE_STATE_REVISION") + with self.assertRaises(PlanAnvilError) as skipped: + transition_state( + state_path, + expected_revision=0, + new_status="ARTIFACTS_GENERATED", + phase="DETERMINISTIC_VALIDATION", + next_action_type="RUN_VALIDATOR", + next_action_target="reports/validation/summary.json", + ) + self.assertEqual(skipped.exception.code, "INVALID_STATE_TRANSITION") + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_instruction_conflicts_and_examples.py b/.agents/skills/plan-anvil/tests/test_instruction_conflicts_and_examples.py new file mode 100644 index 0000000..ebcdc01 --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_instruction_conflicts_and_examples.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from _helpers import cleanup_worktree, start_fixture + +from common import atomic_write_json, load_json +from map_instructions import map_instructions +from schema_validator import validate_file + + +class InstructionConflictsAndExamplesTests(unittest.TestCase): + def test_unresolved_critical_instruction_conflict_blocks(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + context = start_fixture(root) + try: + nested = context["planning"] / "src/AGENTS.md" + nested.write_text("# Nested instructions\n\nNever change validation behavior.\n", encoding="utf-8") + # The file is planning evidence only for this test and is not committed. + conflicts = root / "conflicts.json" + atomic_write_json( + conflicts, + [ + { + "paths": ["AGENTS.md", "src/AGENTS.md"], + "critical": True, + "resolution": None, + } + ], + ) + result = map_instructions( + context["planning"], + affected_paths=["src/app.py"], + output=context["run_root"] / "evidence/instruction-map.json", + conflicts_file=conflicts, + ) + self.assertFalse(result["ok"]) + self.assertEqual(result["result"], "BLOCKED_BY_INSTRUCTION_CONFLICT") + state = load_json(context["run_root"] / "state.json") + self.assertEqual(state["status"], "BLOCKED") + self.assertIn("BLOCKED_BY_INSTRUCTION_CONFLICT", state["open_blockers"]) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + def test_golden_example_machine_artifacts_match_schemas(self) -> None: + repository = Path(__file__).resolve().parents[4] + schemas = repository / ".agents/skills/plan-anvil/schemas" + checks: list[tuple[Path, Path]] = [] + for name in ["small-change", "stateful-change", "blocked-plan"]: + run = repository / "examples" / name / "run" + checks.extend( + [ + (run / "manifest.json", schemas / "manifest.schema.json"), + (run / "state.json", schemas / "state.schema.json"), + (run / "compliance.json", schemas / "compliance.schema.json"), + (run / "traceability.json", schemas / "traceability.schema.json"), + (run / "evidence/analysis.json", schemas / "analysis.schema.json"), + (run / "evidence/git-capability.json", schemas / "git-capability.schema.json"), + (run / "evidence/lifecycle.json", schemas / "lifecycle.schema.json"), + ] + ) + checks.extend((path, schemas / "risk.schema.json") for path in (run / "risks").glob("RISK-*.json")) + if (run / "reports/plan-review/blind-review.json").exists(): + checks.append((run / "reports/plan-review/blind-review.json", schemas / "review.schema.json")) + checks.append((run / "reports/plan-review/comparison.json", schemas / "comparison.schema.json")) + failures = {str(path): validate_file(path, schema) for path, schema in checks if validate_file(path, schema)} + self.assertEqual(failures, {}) + restricted = repository / "examples/git-write-restricted" + self.assertFalse((restricted / "PLAN.md").exists()) + self.assertFalse((restricted / "SYSTEM_PROFILE.md").exists()) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_preflight_and_git.py b/.agents/skills/plan-anvil/tests/test_preflight_and_git.py new file mode 100644 index 0000000..2ce1ebb --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_preflight_and_git.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from _helpers import cleanup_worktree, init_repo, run + +from common import PlanAnvilError +from create_planning_worktree import create_planning_worktree +from preflight import preflight +from test_git_capabilities import probe_git_capabilities + + +class PreflightAndGitTests(unittest.TestCase): + def test_clean_and_dirty_preflight(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + repo = init_repo(Path(tmp) / "repo") + clean = preflight(repo) + self.assertTrue(clean["ok"], clean) + (repo / "untracked.txt").write_text("x", encoding="utf-8") + dirty = preflight(repo) + self.assertEqual(dirty["result"], "GIT_DIRTY") + self.assertEqual(dirty["plan_status"], "BLOCKED_BY_GIT_STATE") + + def test_complete_probe_preserves_source(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + repo = init_repo(root / "repo") + before = preflight(repo)["source_snapshot"] + result = probe_git_capabilities(repo, "probe-001", root / "external") + self.assertTrue(result["ok"], result) + self.assertEqual(result["result"], "GIT_READY") + self.assertEqual(preflight(repo)["source_snapshot"], before) + self.assertFalse((root / "external/probe-001").exists()) + + def test_planning_worktree_is_isolated(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + repo = init_repo(root / "repo") + capability = probe_git_capabilities(repo, "probe-002", root / "external") + plan_id = "PG-20260712-143000-A1B2" + info = create_planning_worktree( + repo, + plan_id=plan_id, + slug="example", + capability_report=capability, + destination=root / "planning", + ) + try: + self.assertEqual(run("git", "branch", "--show-current", cwd=repo).stdout.strip(), "main") + self.assertEqual( + run("git", "branch", "--show-current", cwd=Path(info["planning_worktree"])).stdout.strip(), + info["planning_branch"], + ) + self.assertEqual(run("git", "status", "--porcelain", cwd=repo).stdout, "") + finally: + cleanup_worktree(repo, Path(info["planning_worktree"]), info["planning_branch"]) + + def test_probe_and_planning_destinations_must_be_external(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + repo = init_repo(root / "repo") + with self.assertRaises(PlanAnvilError) as probe_error: + probe_git_capabilities(repo, "probe-inside", repo / ".probe") + self.assertEqual(probe_error.exception.code, "PROBE_TEMP_INSIDE_WORKTREE") + + capability = probe_git_capabilities(repo, "probe-external", root / "external") + with self.assertRaises(PlanAnvilError) as worktree_error: + create_planning_worktree( + repo, + plan_id="PG-20260712-143000-A1B2", + slug="inside", + capability_report=capability, + destination=repo / "planning", + ) + self.assertEqual(worktree_error.exception.code, "PLANNING_WORKTREE_INSIDE_WORKTREE") + + def test_probe_failure_cleans_resources_and_reports_hook_block(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + repo = init_repo(root / "repo") + hooks = Path(run("git", "rev-parse", "--git-path", "hooks", cwd=repo).stdout.strip()) + if not hooks.is_absolute(): + hooks = repo / hooks + hooks.mkdir(parents=True, exist_ok=True) + hook = hooks / "pre-commit" + hook.write_text("#!/bin/sh\nexit 1\n", encoding="utf-8", newline="\n") + hook.chmod(0o755) + result = probe_git_capabilities(repo, "probe-hook-block", root / "external") + self.assertFalse(result["ok"], result) + self.assertEqual(result["result"], "GIT_HOOK_BLOCKED") + self.assertEqual(result["cleanup_errors"], []) + self.assertFalse((root / "external/probe-hook-block").exists()) + branches = run("git", "branch", "--list", "plananvil/probe/*", cwd=repo).stdout.strip() + self.assertEqual(branches, "") + self.assertEqual(preflight(repo)["result"], "SOURCE_PREFLIGHT_PASSED") + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_profiles_instructions_scaffold.py b/.agents/skills/plan-anvil/tests/test_profiles_instructions_scaffold.py new file mode 100644 index 0000000..08f4a1c --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_profiles_instructions_scaffold.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +import tempfile +import unittest +from pathlib import Path + +from _helpers import cleanup_worktree, start_fixture + +from common import load_json +from map_instructions import map_instructions +from validate_profile import validate_profile + + +class ProfileInstructionScaffoldTests(unittest.TestCase): + def test_profile_scaffold_and_instruction_map(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + context = start_fixture(Path(tmp)) + try: + self.assertTrue(validate_profile(context["planning"])["ok"]) + output = context["run_root"] / "evidence/instruction-map.json" + result = map_instructions( + context["planning"], + affected_paths=["src/app.py", "tests/test_app.py"], + output=output, + ) + self.assertTrue(result["ok"]) + data = load_json(output) + self.assertEqual(data["files"][0]["path"], "AGENTS.md") + self.assertTrue(data["files"][0]["full_read"]) + state = load_json(context["run_root"] / "state.json") + self.assertEqual(state["status"], "INSTRUCTION_MAP_READY") + local = context["run_root"] / "local-state.json" + ignored = __import__("subprocess").run( + ["git", "-C", str(context["planning"]), "check-ignore", "-q", str(local.relative_to(context["planning"]))], + check=False, + ) + self.assertEqual(ignored.returncode, 0) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + def test_profile_detects_stale_hashed_instruction(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + context = start_fixture(Path(tmp)) + try: + self.assertTrue(validate_profile(context["planning"])["ok"]) + agents = context["planning"] / "AGENTS.md" + agents.write_text(agents.read_text(encoding="utf-8") + "\nChanged after profiling.\n", encoding="utf-8") + result = validate_profile(context["planning"]) + self.assertFalse(result["ok"]) + self.assertTrue( + any(item.get("kind") == "profile-evidence-stale" and item.get("path") == "AGENTS.md" for item in result["findings"]), + result["findings"], + ) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/.agents/skills/plan-anvil/tests/test_validation_review_commit.py b/.agents/skills/plan-anvil/tests/test_validation_review_commit.py new file mode 100644 index 0000000..dea550a --- /dev/null +++ b/.agents/skills/plan-anvil/tests/test_validation_review_commit.py @@ -0,0 +1,121 @@ +from __future__ import annotations + +import json +import tempfile +import unittest +from pathlib import Path + +from _helpers import author_valid_plan, cleanup_worktree, start_fixture + +from commit_plan import commit_plan +from compare_review import compare_review +from map_instructions import map_instructions +from prepare_review_bundle import prepare_review_bundle +from record_blind_review import record_blind_review +from validate_all import validate_all + + +class ValidationReviewCommitTests(unittest.TestCase): + def test_end_to_end_plan_generation_stops_without_implementation(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + context = start_fixture(root) + try: + map_instructions( + context["planning"], + affected_paths=["src/app.py", "tests/test_app.py"], + output=context["run_root"] / "evidence/instruction-map.json", + ) + author_valid_plan(context) + validation = validate_all( + context["planning"], + context["run_root"], + source=context["source"], + phase="pre-review", + advance_state=True, + ) + self.assertTrue(validation["ok"], validation) + + bundle = prepare_review_bundle(context["planning"], context["run_root"]) + self.assertTrue(bundle["ok"]) + review_source = root / "review.md" + review_source.write_text( + """# Blind Plan Review + +## Result + +`PASS` + +## Scope reviewed + +Goal, profile, instructions, plan, stage, traceability, risk, and deterministic validation. + +## Findings + +No blocking findings. + +## Traceability and acceptance review + +The critical requirement reaches automated evidence through a stage, criterion, risk, and control. + +## Testing, rollback, and approvals + +The expected-red cycle, full green verification, rollback, and base-integration approval are explicit. + +## Generator/executor boundary + +The generator stops and requires a separate execution run. + +## Conclusion + +PASS. +""", + encoding="utf-8", + newline="\n", + ) + findings = root / "findings.json" + findings.write_text("[]\n", encoding="utf-8") + recorded = record_blind_review( + context["planning"], + context["run_root"], + review_markdown=review_source, + result="PASS", + findings_file=findings, + ) + self.assertEqual(recorded["review_result"], "PASS") + comparison = compare_review(context["planning"], context["run_root"]) + self.assertTrue(comparison["ok"], comparison) + + result = commit_plan( + context["planning"], + context["run_root"], + source=context["source"], + ) + self.assertEqual(result["result"], "STOPPED") + self.assertFalse(result["implementation_executed"]) + self.assertFalse(result["pushed"]) + self.assertTrue((context["run_root"] / "final/REPORT.md").is_file()) + self.assertEqual( + __import__("subprocess").run( + ["git", "-C", str(context["source"]), "status", "--porcelain"], + text=True, + stdout=__import__("subprocess").PIPE, + check=True, + ).stdout, + "", + ) + self.assertEqual( + __import__("subprocess").run( + ["git", "-C", str(context["planning"]), "status", "--porcelain"], + text=True, + stdout=__import__("subprocess").PIPE, + check=True, + ).stdout, + "", + ) + finally: + cleanup_worktree(context["source"], context["planning"], context["branch"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/.bootstrap/diagnostic.txt b/.bootstrap/diagnostic.txt deleted file mode 100644 index 24813eb..0000000 --- a/.bootstrap/diagnostic.txt +++ /dev/null @@ -1,19 +0,0 @@ -278b1126142d5d6a1c7a0a398bd03e01b1ab05a608cfcde2aa2189f5d069b794 .bootstrap/part-00 -1038a66a086d68d6e6853efdc161e8ec9230ab8326588ac22728e6aec798c372 .bootstrap/fix-01-00 -969b1d29d516e6f884aaa1238f1ce1040eb79bd53c777bc48b5d5ca1ee3de776 .bootstrap/fix-01-01 -4ed9ff03b6060ef19cf5487850288a1a192b08d40631a3a6f73d7d8c1990c7e4 .bootstrap/fix-01-02 -c27fd9ab6b60434442326282a665ed5a28c94c247b8d93378110fd420b95db84 .bootstrap/fix-01-03 -9f4b935b5dc750ab06116079971bc156fe3946de98bcfb3936b78748108485bd .bootstrap/fix-01-04 -6dc8cb1408f44785a781dba5b5ed22b0b2eaf63fd8f94b148bdc15a0493cfba1 .bootstrap/fix-01-05 -05e4003e4584cec8e25899e1ce20c891c7a24149181dd9bd907484213483d8eb .bootstrap/part-02 -093e88fd0b8fc2714d3f083ef10bddf2d0992a29a7e679032fdd9f415c4ba684 .bootstrap/part-03 -124543941a2fef6b58c228e1642e1f0ac080c8293887fdcb8700ed5c61e10042 .bootstrap/fix-04-00 -2225460971a6672bf560ef630a007f54f368fd31f18a87b30574984b02732230 .bootstrap/fix-04-01 -00f988ff3456e2d14acadfc85b0d32532736860c6aaadabb2efd804696f00cba .bootstrap/part-05 -b63ebc9bc7c64eeb6b4f7fde1f4dcf25764134b16c5f2f94e428252fbf78ab6b .bootstrap/part-06 -f77c10a5fbf088a311f9ae7c613f53a49eee306da80b202fe2c8baddb1fc0a44 .bootstrap/part-07 -ccb94a4bdb728ae855f4fdec22711b3168b97cc2a215f11ef5886c1cd5f8b0a2 .bootstrap/part-08 -37cc095b9b582c69bc9b4e2cf5c5e9c9a780147573c2c4e2ffecf5344549b445 .bootstrap/part-09 -24cf9ca867f5dea1cee9bf85ec4d300bb8e8c7b913bbdac3e27d2c3d61b70bd1 .bootstrap/part-10 -ca5804aba885b243d6bf94b221b60ac6d93b656d12abc2e77fc2807cd545d8b7 .bootstrap/part-11 -e8d0a065720a4d4fc28aa0859f5f153c469ae2723020fc7e7fba2623dda152ad .bootstrap/part-12 diff --git a/.bootstrap/fix-01-00 b/.bootstrap/fix-01-00 deleted file mode 100644 index a6a7e3d..0000000 --- a/.bootstrap/fix-01-00 +++ /dev/null @@ -1 +0,0 @@ -Te/qUvRtt/43WI0tHvF7XzFvmlRj7+zayt6qMIZvTUV/vU8+/o+O0q0ZwBn83+qz9RfK/2ftOcZ/f/F0ZeH//yAPhsdm/isWJncbUYEYscIS4dO424E3CpsCV1dYEtb89F7wQfjaRt/01UXXhSXzJG9ER4hI/vdho0kKPkAOx0vSSJ0+ol0NYLMafqA7Z67SaP1IZU0rf/pi0gsskOEzQGVr+/s7MLCXO/XYJmhQjc3/YrpVjUnxy1V2dvZ+rm/HP+Ow4v3awRsqLmKMm4tEsdFsLlrwlCbzuF0/qDUkz3krep/Hd4LIA4/1FpTdp9LSmSJMoIXDpurM97cgDmRrq75/AOx4PdZ7zFQHt9mkm9QPbbns4AColmzf1TjDIgk+Jt76ZUst/lvpzKEj0ArPjlSQwbpsUdyGMysjuUUsJEIn0CAwYMT+HtBuh8CaNPXXQJhy4n/Xg3muPmbh/1U3/tfayounqwv8/xCPkRmB4raKy519Fo1I4Oc/hRWEx8m91tLsmD7KcCbbce1AaAbMSyMQDUbDUbfPhYGPe11v7jfpIGFZdZxPsmR85ky1SYgMPMwssRFahmUAxGaHTYkGdkA0mbBBEwiXZEUurZgElrvC8AxQYsR4gd3VJWogOy02E6IQFMo4DvXwFXV5Iq11JdIAjNHSEoJpM0/V/zFpC4OhsRYNmocaI+1zvHpXTHUQdvy2tq9xtnDvKquwD2aUViWEAPre2fsFaa+BfXkl0cddRFYTgWwZC8f7e4Dff3HRL3lBoo0XGl+ZaPjXgAV/v8+t8L+0ts/Zx6z4j8+1/5e0/1iBVwv8/wCPif93yHRWoX5KTiHNajm8jvTtwkQAaXI6Ssa+24h045BBNISRHN1cGvpZeTVqa2hljC0mBi07vBLTHg7nZRecSYQI9w9ORQwgxM2MuIWLC+KrnT2033fQ9Zuk3RtfqHtERwEzMpg+rg6MO6tyFOpW/qkceGWSXlTGo+75uQiNLIQlVuHosCkPhjTznX/HUHXOPmbGf9Xyvzj/q6tri/ivD/JIS3S61mkKc3Sh++uh7ydr+nbUKSIpVZpfd1xx9RW0BcdD6ui24UzLk2AqXwWHoSRDaQdvq2RtVaxpp+1pPx2h8LVvs61vYoCd3Dvc3da63q1BXwjZoikhZP8eOJd85588Xyusi73/8/9izZX/QCRc0P8HeUz6zxp3NnqforvPecVqFGQWgAoKHYp1X6vvklFLxe+z3IyorBHiSyOniuVTw/fQFBrTKqNdJuRwZMRMG80ZF2nC8VOGv7Bvz1AZJG/QBDqhuw3Mc0AKu/rWIQ0UeGeog0W+ugH/PFgr3/k3/DpvAWPG+SdbH+fflWeu/c/ayosHj/+Ol3PTys36/it9PGdeov3SaWbgqazV1aCXksyR+YmwhkJFMefcTYlrDl7nOkptcoNXYWnoAL56RSbCsaXV1ifWOaSiwKE4wl4SMizunGE0Ori8ZMNgkVrMGgEp+h+OS/96z7Tz \ No newline at end of file diff --git a/.bootstrap/fix-01-01 b/.bootstrap/fix-01-01 deleted file mode 100644 index c4bf0e7..0000000 --- a/.bootstrap/fix-01-01 +++ /dev/null @@ -1 +0,0 @@ -L5w075wAZA77v+dPXzzF/B/Pnz5f2P89xJNn/5XZDb8g25p5+pjB/71YX1X834un68+Q/3u+uuD/HuS5Xoqiwh87yVla2IiuKdtpAQMhqF/we4guBaM+vCr8XURTOVqp/Fu7cnZ8/fzpzR8LZVlyfDVMsFg6HgGjUqDXN/y1YIQ8MRtvdzpkW9fu7Y/QzhwjlxVE4g3V7tD8JKtif+3ReTK23ulRHBnvIjWmsv22P+n1CsarY/X3Tdnoh1u0egHmdCfpn49xqVbLgf6tVaAWl5yWC9Iz3hot1y97sxQvjr3VHpzg7YC92pS5t9vJ2sb91xXcwuPrP92IP57DH7XKK/o7957KECF0RW72FVycQn9g75U5pOJfNv7+5egdPMvHpXfvqvD/8Eq8+PLH0pe/w8/lLzDG/2xX/nmsvrwTT6ngre7UkU+mLY9cmwO5Nv8Zz1qx+AiGhX//AOOsqB+lJzmXEg7WtNHQYXu6Us5/3qT1RlarHKKRp7J2g+t6/JecTavoS2bb6NfWxv0toDlrBcvMaG1JtFj4I42ycDEeD9ON5eUPydXZ2WWKYXEuJifV7mBZyahTaVKBG+M3ZoP4sSIKDkbny51R+2y8vAZyRmV1TTTJlWdhoxAmKkgbVmlBYyKpu+E36QsfqzlZKAg6TmnFhcGO/GCiLlvUjFFNn9nMWnU13AhhEznNKaNYsUaRE92FRpjZdzl7cebCjyIafNw2p1P44yg5wxrfLRNJXNaAblVWISHkjk/FIz8AKnP+yHnOSP65N2DSUfbcHXSnbaP1IETQFWBMd8v30Bru8T00o71TY2HbfR+NAqVA4f8emrqv5TLDjNy2uZyHU83e3S1vWuUgpGWNevquZQDaXTkgd21kEYenkcO5t5OHtiwxa0vvgYssOw3bnENwolgk2IBhjzOrDZIKMk8v6nkzpmgiRDNXyCyOank2RzV9oXKCuLkG7tqKGYWWfMoCzAWnPifqHeGJD6W2za5ZO8QUaFbLWwK3Jef02IP0iWcmRfRPk0XUZEse67Qk1g2YzDHhb52GMpJMH/Nq7qL++pVx3+DJo/8x/apuowKaof959nx9xdH/rK0t9D8P8yz0Pwv9z0L/4y7PQv/z2PU/GTTpW6mAKLXk/YnqLPTklGEdxjwnkrG7mA+33KtaYupc7yYeKb5cWpDeb/Mcq/Y+G8+5d27HU6fsydK32vMHkVJkLZ5e2m8P0wuLZNxRDA+Kp/fPLVwk7c6sQ5spkZP7euywYMEmsgVydtW5TSM5AZBmWPZWNmMI4dnNBX6cyHVede3SvFKvLeYanYZkV4HzM4B2aYoca8So/taibB757/aSHz8z5L/na6uu/Le6urrI//Mgz0L+W8h/C/nPXZ6F/PfY5b9HI/mpW+jcIqAB/9O4MR+Og/fYnMU+HkJVE0X5SNBHgBbyOw42S0B0Nwi65Qh67XQc6/gL9zc1DMprtpb0J5d2a+SKIDwIG3u7ZrP0SRn1hzvIIHTu \ No newline at end of file diff --git a/.bootstrap/fix-01-02 b/.bootstrap/fix-01-02 deleted file mode 100644 index 1289066..0000000 --- a/.bootstrap/fix-01-02 +++ /dev/null @@ -1 +0,0 @@ -XpvFrPoAKv2Y0kcCc2q20B0nly4BDJIaH3Tao1FbX7oWJv3uPyZJQ7SHKZcdtM5pyxyM3r2klVrxWqeIV8noXmQ/khum789u/WdzT4RH6H6z/mqn8frNQbxfa7Xq22YRcqjHHJzuXlpOp4Ei7PDsf3Dc7v0CMtRZ4EvzoPGqtnXQipWTqvl5u36AbqC7jRYllNr5hRPam0Ve7jQoWBc5t2AomoO6BaSGU4tXlwCYnXCcjlsHe/v7dacjivpsvsKQz/Yb7eLiTVV/apADzOtmvdUyC1CN+NVeM2b3WSMWWoyR1ax1+7nWwFBr8WGr3oy1C5BZhj5xaBl7kPShWf8ruQ0EphgObB0+3w8li8pDmCmNEiazz00QfQdJRQBZZWDeIFoqh6nf0hSp91HIu4vHfvLI/0Z61lspAWbJ/89ePHXvf1fXFvnfHuRZyP8L+X8h/7vLs5D/H7v8H6ZJ38wDQCbhtjFUSGLLg++yMR7KQ8Lf1nkf7E18yGkTbJ0eZ+NYgFzKKFjouhdeDrBt1fbxsPwnQFvFNH+fAh6hbgx8eR1u4WQw6CXtfnYTnoAp3ntipnjPwZQtoUF82d7bOsTIaaFvnpgk3vsSlfgg/I/9D7t7B7GOVGpv1rE5yyDhChIY3q/QqoQXuxwEP/Xy2OgvRJKy9REWUsEY9p/vjTPA7JCxo+rh8Yf2ufBmb+/HVgwifcvfTvFxu9HCHcj4erg7tfLhbu0nAAl3C8PcBqWNymBqpts7qGBTwannaoJDDcbj0ST1GKvw2mVMPHNFJKjPXAdfdTR9GjnZK1vOple84lNWMnOFyiGQm4tTu52ezEhme68qQqsTESf3ll5Sn9ojtES5XxWmwznkVaaYM7HwjfxhEvDAErtTWpqi59Csiche/5h1Hnnkf9Nx5zYagOny/+ra+tMXrvz/9Pki/u+DPAv5fyH/L+R/d3kW8v9jl/+zaNI30wCIXAVfW/rvJOnpqDsc+3zxNJQ0h4g9U5I/aO44UKN+3lquN6Nx3du0gpg8r0BsrnP2UNWH+5KBRYaMrw1FAWjN7E02dksYmLpHvr4J9lqaJWRttW3LID5mWDQEOnmcCjQ5qDjAamRJ3vC+dniw95biXDvX5eI7xu1sbKnEa36Bt7Xdw9qOlTLML7T3slVv/pTxUarBhEFCoIuGvNKX4QGnaLHmwkW1rXvHRJRk6JbHArMjfKVjcV+w79pzideed4LkHe4Nn5qWCLIqLbX1SuGlKWfjYbSR5+3hV6fliO0xffcdtNkdTFseaOA+OIH5MNHhLuUOrKNhkkroFURIr+vxz42DN3uHB9OLirxQgDdkcYU/vLKUmEQWE8HAAy3yB1XwZf1N7afGXtMvuX/4cgfwpizgDngbVfLNvZ9qO/elkPdBW0FHaMPvG9zNrGwPAfYOk5PZm2zsVkj/8bEe93DiZ9FEgNB7J4qEvOehinnoyTfZgHHy2VUXfSMBg0aS48CLtfdK0gm6bzTwtaPKWGjG \ No newline at end of file diff --git a/.bootstrap/fix-01-03 b/.bootstrap/fix-01-03 deleted file mode 100644 index 3baf905..0000000 --- a/.bootstrap/fix-01-03 +++ /dev/null @@ -1 +0,0 @@ -lXmUXt7iAZgSL03Rt3txpR6pqv1RPnn0/8io3cH9b7b/37ob/3flxbOF/d+DPAv9/0L/v9D/u8uz0P8/dv2/S5O+ld6/LXJVxHjrP+jnkJ9m2TuEuODpdlO5bh5uo7+9/7Hm02/PL+7d+0jD9ywZeG3aWQGBPfGI3mPdn2xskU+3OXUlupdDO3p0wLVvZ89y7Xtb324cvjXfvGm8fpPhMJp8tKzm7rf1S0AN5+791C3AAXDIiR+5937HKvPk3W2kd4ndc8eeXafj6eqEeVxH9/ZtV8m3jYPGa9cFUzoQklNgq26qBwtbO3uOb2mzXttp/Ce8s/dCEbe8srGOO2N57TFYB7CSveDlbHIUgDz7RHqYKqdkbpwJF/LsLVmaIr0jIV9I7d/syeX/p3xBv4b/3+rqsxfPPf+/B8//tpD/F/J/tJD/F/L/Qv6f2fQjkP/DNOmbaQGQhMZOENC7obYMK6WMO7f8FkrBO37XOsnEfUGHuQxXIIw8stOoebf5hd09ijoS/jjdISgn0vQ82DzbkHyI81vHc7pTXqLu1w6WereAuXcKjDoXHO7Ua66pWmG70Tz4ZT7YM7qX8XRjkHFyOhVyYCK3Rxl2yH1/UGv96L4z4uHc7XT4AVrdEK72/Px1n+sQZVOdrTf1rR/392BinjaJ3YPjSu70WI8+kpcXlG1+XQh6kH1M7FxED6BUHiXppDdDV4dhtswVRZ9n87f0dQ4urWtnecfUZr1B6nmFZ5FKT615W7OYHMQTgyY9lmHlRBU05LK3tnOd/1vHfvtGwQbHQE3vDxofD+s2ubxsj7wUcXeVT2Wzd+a1PqGCMU5PB8MF3/yr5ZuXbq/o9vOIOSHttBrcClonqJPB9Vrn2CIxkq3XEloA+AL03qW/GeLB0jRHcDuG3qNUcOey/wKISD7d3gJsVv6v1afrbvz39ZVF/q8HeRb634X+d6H/dZdnof997PpfnyZ9K93vnTR2Z91+J0eMnDv73MzyGnnV2N1u7EoQXyvfwVckQQ9pLy91FusbuZYu4qVn7yLek9WL9xZdxTBadl7H0rBgNA2pT1+BINHI7RopVyw4RPXunlw8uv3hJJesO7daG9bOasBXNIUIFUzyQ2fwqe9mq5rSqaY+GJ3J9ZjWKgaOk06KPuGb7FT/yjqur+9No+efKVGJ/Q5KTgr7BPdimmhz0oOqESPhKAV58bQ9erxCzuLJfPLG/26DND3of5X4309Xn7r+P2urC/+fh3kW8t9C/lvIf+7yLOS/xy7/hWnSt5IBiR2KmR26BSNrVRfc1C2auZMkitbfI0zylI67p/HHdq/b8dwd5ueP3zZaLbR1CPLHMFzYlq8RH/a3wuH77LzNwPtwNxOiZm23szfThADB/uujuJAAfnVPHv6/C6A8mhDnVrlsD+cWAmbw/y/wm83/r6NIsOD/H+BZ8P8L/n/B/7vLs+D/Hzv/P4UmfTMnAOl7iYdhFleby+5oLvtN9XpGctf2ZDyAjQKu \ No newline at end of file diff --git a/.bootstrap/fix-01-04 b/.bootstrap/fix-01-04 deleted file mode 100644 index 17d7c8c..0000000 --- a/.bootstrap/fix-01-04 +++ /dev/null @@ -1 +0,0 @@ -7+RqnMS97qVtNa4Tvfo9BRO9Aqt71uuePkzguDtGT3O3JnO082xToCN7y9YybpJmxIQFXn/Qm4RjIgdpXBaVC9C5u8Qq5EUsB7cmawLq9T1dYwHUkKdxfNbtJf325cy8W/OJkXkPE/b+1eE+E7Fk9ik+3A/0To/Flwm9iF0Cgw2gF6ddC8mEWj4DWAbZ1vMlMcTuqUEAHWZl3sVyGhslp0lGPOlAzux555q2z5LxVSzPVzya9EKrmgkC8wTAzLmxrr3u3daPBYrZzZl3zn4rsN99jskeU0CBuSjE3MivEJpBAPgzoDawmlkgZb138MDUBcgBRPeNks+TfjK6vQLya+vSrOFJXii0oiHaMo13skiBxxMtTVGgGUxsBEzst1Cf5dH/tIF0XaXd9LYWwIb+Bx/332fPVr3737W19QfW/4wGg/G0crO+/0qfh9P//Hp1BY9A3A0dwYWcO13OTdPJJYVK+vqCKWD7rJwi8+eVxZBTGMP+VaP5NvS9sfuq3mzqKyl+so0dv2W+E+fjryJSdyAyt97f8MreNyt12gPoDWVEClxgNlp7O24Es63mXqtFjmN7u3ZuBcoIU391aN1ximwHtf2GVbK+ddhsWC7zhZ3GT/V4bz/gTy3TwNSy3anvdD8dgOJ7wDe3Qy3nA2Ci57+fv4upqy3U3G+8wNtmoP3Qh8n8GrR+94pLrJa/feKyvHkEvk7esqV5pTDfokEfpuAxCWNE81hMleUU2ghwBS4gL00R1XCUkeTCfkN2DnnkP2BMKypB8i0yAM+Q/576+X/X11ce2v53If99Zfnv3i84H4FYln0yvpklYjtNYi920y0Cz1BDzp5lxmrSfCvQ4Ym1IXcL5jAaDUYeR3DZ/ixZM0uvnicqg2cSyOOWfA5ZA+qKHg0MG2xYRnnmwCW75a14yGTDt1ZUw3rdwNRjte1f7qQylbUoYnCc9tvD9MLSsnyNiGH3b4xzpyhi3X4n+ewy4MEm7AsHsw0OmXGbRnLCkxuby4/eZQ4hPLu5QC8dJ18/3WHIB/U+ePDgkc4+1Hd11xTd3YqFNtVbK97OzCeEMkM/tzg9N8du9mNjKpNSWCCqiUcGyrHAzqEd07jwtN0HGPxn0oled8eRpryRxeb/Njjzh3ny8P+9LkhWV7A/t7wAmsH/r6+tuPa/KAAs+P+HeEL8/+Km5g4iQfCwfCtpIPn4EAldH/aC4QGyhM7PUVjVU6CsGQZB7c/CIOipP6u7mkUhTzjHBRRHp433m/VXO43Xbw5inFTovkkLH94nGcs2/nmv+eNBs17PLNjce9XYqZtCjHxub4eo1jmwDKH9vMe7G0MEfapfash86iGYoHva6WDUeaz2MubolDKV0Mk0Du0EyCTg0vYwUohwwZw94mc6/4e5htLlu/ZBTl7PnmX5fxEvKPk/tAVaWX32YuXFv0TP7mOCs57fuf9Xnv0/HVxeDvrV4dUt+5ju/7f+dO254v+frtL+A7Q8tP3X73T/z0aD \ No newline at end of file diff --git a/.bootstrap/fix-01-05 b/.bootstrap/fix-01-05 deleted file mode 100644 index 9a740a6..0000000 --- a/.bootstrap/fix-01-05 +++ /dev/null @@ -1 +0,0 @@ -yyiOzybjySiJ46h7iTGFonYfuHq6akuXluS70fmwPUoT+Ru5aaRNUTuNOmP5FpVPve6J/IkMrvx7kMq/RqqRNDkdJWP1IZ2cAJ95mqT6zZX6E2jrEK0sl2jQ0H2bbgWTNNIj4ldcAnlJGIr8ug8/+QOQIGD25fta/6ocAeEetU96STlqCa6Ci05GPWiiShOXFeBdOux1x2X8a9Knv5eWWltv6m9r8U/1ZquxtxttKvIr4s/vNc1vK/xta2/3oFnbOjA/rVVXC0tLFLaqsQ0cE7wbJVX0soa5F0fkvPeug35o8F/Xba+01DwM1iMKDpWp5gHVJKe2jJamuLMtlZbIdyxjdOxXBg1qp7LS0pta602ocPA6Cdp/UwuV9u6JSkvG6pJlSwsqCbZmty4tImbwuh6HO4OvdbhZ8bKx2zpoHm6h+Uv8trZvf6zt1nZ+aTVaztvmQeMV7H5L5ijQQ9quH9Sbbxu7jRYFttv5Jf6pttNQnzm0GUc1i39uNg4OVF5DCiZdazZaMA6rDkEUfHyLpdXb1sHe/j79PF5a4j5rOxw0DRf0sEVLem00YU1BhEfAVIkyCF8s41L7RXChaZsyvu1j/y08CK1ACXOF0T5up7F1ECgGB+Cg8ZZ2u1n/34eNVkP3RxOgVSE7pRijPdDkb+AA17eadQQNWJ7mrgakIoi+3Y+oOgD5v1C2YbKCz8v668ZuBAel2apFX+pb0RfMM9lqvYlKf9lvNn6CCUc/1n+hsoVSqSyaJYv07mllPPiAIffthot/6ZbenUCb7WH3KK4c/wU6/9I+RdRIP6nSF0afX4aA8z4Btw413qVPjjY2j/Gfd4Xvj/8iVCuYWaO6/MNm5fh6da18Y46ClBnhQbw7Ob84Gg4m6eg41g0dX6+tlG/enRiNtD+lFR5caJHendR+bNTw9CJCuF59LisDyNVetvZ2Dg/quO5v/MV31uR//cGcT+W4tAwrdDG4TL4cpiC+fBE79eVje/RlfDn8MhiOv6Sjj18u++MvPw16E5CkSstHf3+XvofF+V//fvxDQUzBW3u7r+MSqq1w9KiiWj4uzWwDtVdQ6N279PgH/VdGd960/s/R8rt3x24nsFxLRN8iJXDV8aKx2Jz0kRLTj9IG9QCiI9D1br87juNimvTOyhFMPgVmbyMCAa0cPSlHp4MO/0Kyg0ejtvtTYyeuN5t7TdjDTjJud3vpBlJIKLE76CeicXzSyTAZFUtV1YlovqRLQK9V7AMq4z/2B9E6fBN/weT+Q1HwIlDffyb9zYPRBFrkSW8BH9rud5okzfNAgCeB8Y0nw15yRLOqVqvHYoWBo+nzDLv9Mb1Lx53BZEwzlr+T0Yh/Ly3hik3Gp3F/8KlYiir/jq83jLaAyalKnqeKheA3/v1PWJcqVCxVRwlwz6dJ8bJ7OhrA0Rz0O5srpWo3HbAOsqiLFH5YWdlYWYFVLvwnkjHqXUn6cbdzyyFAhTN8Uyz86y//evmvnYN/ffOvb/+1 \ No newline at end of file diff --git a/.bootstrap/fix-04-00 b/.bootstrap/fix-04-00 deleted file mode 100644 index 398bbb6..0000000 --- a/.bootstrap/fix-04-00 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/fix-04-01 b/.bootstrap/fix-04-01 deleted file mode 100644 index 608ff80..0000000 --- a/.bootstrap/fix-04-01 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/fix-09-00 b/.bootstrap/fix-09-00 deleted file mode 100644 index 22ecfc8..0000000 --- a/.bootstrap/fix-09-00 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/fix-09-01 b/.bootstrap/fix-09-01 deleted file mode 100644 index 11182df..0000000 --- a/.bootstrap/fix-09-01 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/fix-09-02 b/.bootstrap/fix-09-02 deleted file mode 100644 index 484e285..0000000 --- a/.bootstrap/fix-09-02 +++ /dev/null @@ -1 +0,0 @@ -vcBg8IHT/eFVTh8WEvaT8vtVo12C4NNeu3uJ6zg2Cre1IiXpnw0AXGnt5QHCboXS5lPS/gDHDdVLKQwQzknZxEnUZBkVGJ2TwWf62h5iqIl2D17janEsqh5sALyAhYOqY5VFiENTpUZ/l+3RBwDt/rh7mZiIAAARp4wgNqTjDgulY1jxWcazqFUpUmEmFUR8iH7irYe+AWlO+rDPg0uhklKTQrKysbT0/v175MOWhgzMlcto0sdOUjg73ZSEsaiSRtkHj8dc+Wi0gMve7SWwJlHlH9lVI97qZVpeHMjS0s+UxBHRAWmk5DHtdc+S06vTXsIAg3uBjUWXcLphnu2y3CJYek4NJeNBS/zcSwfRZIjHQWjYAP2nQ9wh6EcsO6NL2M6u2A6LDCzUUvf7VJe33tR2X9d39l5/NRZwBv+3tr6u4v+8WF9/ivzfs7WF/d+DPN9FW0T2e4PzpaUaHGZAjHSVz9xAinpzzeEQ8tce/kA1Bao7WqmuVleOo0q0trL2vLLyorK6hh+Acex0kg6yDoIhMJEfow9ErSpvXAUJNeqqux/pvP8Zatr8gEHvNWcTAbVmFTxWACLZ4YaENeIQ2I5e9/xirNAL0SNMTD9KuzhdJDoGCaDrDWyKTRwF40WsG99yUEPALX5IOpr7khEPeQxqmlSUCC00ewYdIOkCop9e9JM0Ffr2suUpeQmUDTujtQG2Y4x8Q0Xy0exOwRQQLTGAtqSn7bOzQQ8RKS0Z4FwxrYoxLR60xOInANLQZXto0K/exLTnOB8gQwIMwVXapZUVlxewHsTytBRnrVghIg0RtAqME4kPeHMBm3l6JQgwj5l5IeKDeM9wfctY+xwY8E737Ewz8GXJ5prcLTeDpiWJnN1HRW9p59QsTtBepSLsVU6A7eglZSEAqDUkkjOC3e7T5dUZ8BFyVJTqkKCJSX90Th6uUGlwglw49XHW7dPkB0OsNpB8lIZEFmkMdkowUZVuv8JJkol4Ym0k/QgO4+RcUk7JLanFNABIsZqwGLg/7V5Z8WtMVLHRcwAOTs3M5jhSxuHZKxCpKFAwIKrKR1lcx9EWT0AcwDwQ9tkkNpksgoT4kHSqUmQiOSJBB2AE+hEMGC/azulw0SfFa/FSnfr3kda9GwmgW3vb9b/FW7X92svGTuPgl/hlrVXfaezyFdyCV5j5VO//ut97ZtD/FyvPPfoPVGRB/x/iMfQ/pioD4/ryOaz0AQV9DJBtEvPGk1Efi6b///a+dLltJEu3f/MpEPKN8EyFKGMn6folSyyZYVnSleiq7unbAYNAwsKYIjkEaVtTURHzax5gYp6wn+TmObkCIAUuEsoLMqqrSwCYyAV59vOdabL4TKWDNgGdgZA5MC/kHpSMTekD8/TDdD5dorKfLdoxpWKo/i6pcoYEtGDZEXSKkp7BwvjpJ2lbQXolzSuAKUwHzQrOoQ4q7Sbp4qefJPEpdn9L+SulvmgWAGoSCosIMYDdzzkNAs66zFA5QS++sApQUnU3Wwgtns3x/dX58QUjOyAR3awlkkpoAXK52gyCZPtQ8RFlOEIGcvgAB0EhTSfAYLHTCTds7k8/UY4d4xr+9NMhasMzSabbQKbvj7DOT4kW34WLefplQwosyTz9APgYkHmK4AsirDgx1/5uw09kpYadi92Q/CCZzpkiye2IqyIsysEVWSm6gi8oD7FoY4gFu8E2811G2E6WTgGGjzAFncSo4Wva/Hp1nenZYGXDYsnp5NM0CgWiNu0QjgRlnQN6/SPdzYWUj8f3Wv//R9Piz/gBEScCTl0cazIRO7CiWhN9gn5toF2nGX3+3piEd1SWx2Ed43d/R9eAvss6gvVMk3swfUBwiZCphdT7c8s+wh/AHqPIkxOqqeR9KLOBxG9yKUFcquIit3PExGiQsB6WvukKkDkcDiaGawNyj2RCUskMB4N68ZAM/HPLO+KCOilYaw5BLlfqA6UhdE8Y9dLs5VwoZ9E/a2Vp/whAUm7BvMfu5wRgKol+PGREcDpeIepK+/HPrQ4dbUglqjyR0fYdflwQhnnw9s+t7pFc/pJpGonjz63eEQ/z0qOpoE+s+yHsYpLgYBcTqqMxuXGVjIiTGoO9EFLHwSY0whXkAUssHCv3oXOj1vrzxE2zeCnAS0eze5Z9bvy/lmG02/yrPeJ/4m4cHG99Qg7YEYFpqU9HmxIsSsax8GV63KGu+BW0NU7Kub5W/hwZGRYslzIbSroo2bvL5BNtcFzE8tNilAxIAPu+8NSQZDovboSa+GHuqziUVvS12g9ncWFCwG+ywhUSTwmDAKBEFGkHOyqctccETIScx3GGrfk48AzQO5Spjadw6FLQg1BnYzsKJztlLgT6/QE5oDTgE9iXP6Xz6QQ+w0OsRk8JODuWn7iGL6LjwDi8zG7h/+/InEcKwjpyAnMkyD2EA+r0R3lamGdGbBz/BNCee2S8DSP6/ZO28E9xWz7jhlLoyBvhMTPyZ435qYO4zJlNKHseM5mM9Qq7BZODr2FBiQMdO0dobCPwYlxhzRdCxpHxGq8Jx0ou4JDTNBx/0fz/swEl/kLkijgL5LJyXDkrfIafwr3yOqGWCqyWfVPX7OXoBgOrkW7toZs1IZ/JHNRZ6Ng+cszcxcnUoFLGJ8YxqIRJx/KBWRfoHUqR5nGbCnn0k+W9cmt9JuWIsjbLfzwhC9h5I4wi0F7hebZr6hCVbf5fl1GfDu5Ut6TD6j7sxYWoYE5DFvyD49I0YykrBXbZ6/H1yevBsH8yfHfdV91pHlrO1eDj4iQkJZn28+HgF4gHvjl53X97fCO7KJqa0JokXL1AGcOF6uXyqn9xPAhOLukUB8cXJ2okXLDNexroac3Q5d3eSLqFfoTdAgUeTU7W5V3ZXf+vx7DWajIySle+mhmWlgtwm2ZUTWFLsibImPUh+ICIThYGLM1x32r9/Q25T5K3N//4l9vFYpa9fPHiA2XdyxH9UO5e8Hv/arww/h7S/aEb+e/h0WysHtav/mtj \ No newline at end of file diff --git a/.bootstrap/fix-11-00 b/.bootstrap/fix-11-00 deleted file mode 100644 index 6e549e0..0000000 --- a/.bootstrap/fix-11-00 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/fix-11-01 b/.bootstrap/fix-11-01 deleted file mode 100644 index f4b313d..0000000 --- a/.bootstrap/fix-11-01 +++ /dev/null @@ -1 +0,0 @@ -z4WuwYUVEW10lrBdrWeaLrGNeqaZiVi1141/xQ0Sl8JyIc0CKm5asyyNuFJQNka8k5YGIYrjT6WJQhNZVwZoU5kpTjMmmIL8EZEYqzL8qrR8KvLN5PNcpSdxCrrMJjYD6GKFfQBLElBJB9JS1mnlIlsor5C/pAr4RJMxxWN8MCV7XEi3hn/rxh0lTnQmmQjkhg9fV3Jg0PIMGMKMRqVzLSo9nXwk6gc5a0yhZAG6d1utOlS3t1I/kuHsBE2LosCEVKDw3GSFD+5nnJr6HdfFQNFvq1oMJ6oqhZL9W60TjFSgW6GVsdAKWLw/ed0/eXN1ObgYwrqKyM/3eRUJvpY1tSRQqxprxpw2gOID9ZM6lfp0/3SReSv+bz8R/7fcIv93zKb+by1tO/5v6/x/O+Pe9lKAvVoKsFdKAfZKKeC5YJTPvwF5QIaoK/avLhVZv72LfTUnAOzw20YM2EMMkDrUtqKAvZUoYDeiwJOIAvb3KQpsxf+dp+L/RfwXyv8b/b+Wth3/d3T+v41zbnvu76zm/s5K7u88yP3tr577l/PmlAygXyxKAc72XtKcDLD1LxsJYH8JwN5aAnC2kgCcRgJ4EgnA+R4lgK34v/tU9n+zbP9v4v9radvxf1fn/5uH12zP/d3V3N9dyf3dB7m/89Vz/211f3fb6KYcz9/ydw3H35/jO1tzfHcrju82HP9JOL77PXL8fNuK/3tPxP/dEv93TLfh/3W07fi/p/P/rUNktxcDvNVigLdSDPAeFAPcr10MWIGro4SBPOpNSSLw9ohZloLBbj9v5IP95QN3a/nA20o+8Br54EnkA+/blw8q+D+S2D3DP3eJ//SoSNDEf9bQNtp/FWS0Uw3ICvnPontfrP/ouw3+ay0tj/+n8FUVLFwcLkJIKxEgRVyIQvQ5hUpXLEdVKAm3pqxcrk4Te6ZQRe8GU+ZY6hrmt6YT+q4szRZAmCmNFHkJSEtjQwZMMiRn2t2CiELyD4yMV6dRxePY1btZGC3yOHJjStjH+UuUrqcfJBzfO0g/LgdWHiq3yqFKdUREJj5UAL3hohX087Z/Onj3lsPZcb6CgyQQmkl0HhdrrAO4GHCZXAVFlq3DJB6RaqvWaANcLR24UKTa8PulonriMi+QfEn5/HcEmPCdtS3ov10r/W/i/2ppT0z/7Q3ov/2n0H97Lf23G/q/B/23G/r/LbUt6L9TK/1v8L9raU9M/50N6L/zp9B/Zy39dxr6vwf9dxr6/y21Lei/Wyv9b/x/tbQnpv/uBvTf/VPov7uW/rsN/d+D/rsN/f+W2hb036uV/jf5H7W0J6b/3gb03/tT6L+3lv57Df3fg/57Df3/lloV/UfcsT0jALb3/3css8F/qqVtuP8crhfCz7Z/x9b7b1s2FQOa/a+hbb//lIndAebj5pJghfxnlus/Or7T+P9qaSj/JekkpnKUVst889rTs1uQDV9i9e32nHxKyeeDQhkvWbfhYUmDf2PTORYC4vjgQTgeF27DMHltr5CDwGeF8hAHcZokxWsA4lq6xgBE9aJCf/xQssqG5x/Wju/u9gxgB/rvOG5D/+toO+z/aEzJBf9jo4SQKvpve0X8R9du/H/1tGfGK9hOVtHjGvdU4jKPF63WeyCLEp4YuQSWHB+Np9FH0L0F7zjKgZ8fIlQxQlkL3fVQQREfyloJH0TdiBey2IQAlUYke4HZ/+cnSn2nbd/zv4kUWGX/ozcL8p/r2438V0v7ndnlNqsZXZYT08lsudAEMo4ErmVMhb7ViTzf8aLI8zoecSNrNOqOQrrhXcseeVEy6vg9fzSyk8SP/LCbuF7PskjXph+D3xkJSa1CE9He6HSjTje2wxjK+xDHI44dRnHkkTgike8kSTxyIqsbuqbVs0nHScLOyOuETs9yrK5nxrJwuEbPSu8IvdiKbbcTUVGlR+IkGpmxRd/hxsTpEAtKr45CL+mSJKIv6RHL63T9pOMQYtHBhKom67o62ObI7nQj36Q9dHsdx+u6xPUs+hrHT6ye5/thYtrdEemOYm/kR2boJnEYuV03cUzHtRIhhMOqBYv7Gcq4r84HF6cBR63/ddD/bXtR/YeSjr//tgP9R5v2PKUHYkMbQJX85zmdIv13rSb/o5bG6n8DRw/Y9j4NHcq9IUtjEoXz4psSKzSTbjdxbJtSS4t+Dz2zF1vd3shNOlR/pKpBJ3LMEb3vd+lrY89OKO3tdkjHTbrJiBce35CXgWNofpdOUiqmRoHiKnkqSDujn7jG8L43UvnQ+YcCm9li7/KPleffcsr1Hxr8v3oaaHq4zY9ckvDPnlfTNmsPnP+E+Xuf/vzbK+q/mA3/r6WBWQe3udU6m45jMlGlOPn+G7N0AvUJF9MtSqdisSlRsrNQdCrNIIiDF478s+f/o7cHzj/5MsOooJ1ivvRWdf4ds+D/szoN/l9Njdl/crA8PJgHcXlkHJR2gANRMY4+mITjjKg4oCCNtRCwXEawUcgQMwoZA0YhgtTQQYdEmJaKKlKV974JMfurbQ+c/yyEGtL/yaLp9qEBlfK/wv8S8Z82JQnN+a+hsfjPUUZlfAFGRY+XyUIdodQmFmUnAYOvKR76ldowoSo42oTN5mR+9U07/+jSI3EbS9s/5jvgjG8X/+eavt34/+to6/YfjL+P9Y4d9t/3/Wb/62gP7f/N326G/bfB1fXlL4Pz/u52gAr+b/m2U4z/da2G/9fSnmHkx/HkUzo2oMh0lqJZ74rFxUGxa/6f3PD30nj/6/H54BTqXZ+JIEEjXNDrq2zt8JjWbZJSwXI+m6cT+AG3+1t7NniHRCmETBXj5vXxyy2MFTzgRY6SYTuyVAc6t3l0m0ISCRpJbu7C8ViaRubyRwz/75wKzktAzD2EqtlgCeWxLhKU9B4qmtMn5lCW/n5xO+WGVbq6EPUSt8fpaA7RL4j7yXp9tUzHMYuoOQTERl7AHDYkjdoiHQMRBul1QH1cTjC6RgyT1T9nt3mpDwUByc8/exUURY+m \ No newline at end of file diff --git a/.bootstrap/fix-11-02 b/.bootstrap/fix-11-02 deleted file mode 100644 index b901db5..0000000 --- a/.bootstrap/fix-11-02 +++ /dev/null @@ -1 +0,0 @@ -k09U1wPkS3zPfyxDcIEbH6COOsNflMiIOWxDXC0jGpOQTmo6/7iYE1Xy/t8JWILytdlbrSEdAJysMqImphmRTCJqjqf3oIHKOvA4FYFJOl8iNOTFFBaaP4kV1he3dGGEIdNYC8pI3xmmYwRcFEiaHLl0kX5iVqvZdJxG961W/wukP6UL/Z4ClZTfIfw6oeLx7YRkdGTyOh2OsqfpeyQ+3JpNYg/Rf/q5pAl4gPY0AFXSf8ss2n+cjtnQ/zra7zJ7j37PwoW5IsI6YE7OfMh22TQEWKbodz2y9LDrQLyB/d4E56gIgNnUYStDBXVHq6nCx4XuygeOkYMpQOfCc+ovFsnDx6ZpuPAU/tnGP3OPychxHt2khSQx6h9oceQlqUk+vpwE8BXBQ2sPnXhYjqk8Gj0uCZ4oxynJtcW1Z7mNV2dtWFuzY9ltqws+l/aJc+qqMCE2E7WAQJACyosmETrpAUNXjABvUe4N1zflsuK3mgig+f73lQH0nZrQN2gDny3n2ZJgBMuLNYvwYkbmlNjRr7gdkzERqa1sDWHb2BKKnw7ZT/8tWNNdsKK7rzVQ4CH6rz69/d5RZf/zOoX4T8unK9rQ/zoas/8JIo/w5khEOW1ezkHMC2SSz3X/6vJ6GBxfnAY3w8urg9xTIhV4shyPmQExzBaBAtfWb0HcgLTjn/Uv+teI/806nJAviyAUaducHtFt+kD0PuAaj2u8uLzoqxM7pbJ2wL7mueaOeHV+efKmfxq8+ltwcj0YDk6Oz4N3F28uLn+7UB4GCFHih9OyN8iOlg4J3ju7vJzFVTztK7GNPnT+C0xz53dUnH/bsUr+v47ZyH+1NCb/hTMmP6REnRd27OhdUQ9ABsExwQ9Z4snxVfvmzeD8vH06uDm5/LV//bcD+Qgv6QEPUt2OyOvq0JxenryDOgH03ODNPw63e3X/r1fng5PBsH18Mhz8qijIE7yeXzMekN1eiOdffEgXbbmoSiiDtmoaZ3QGVF581d9m8KL0wFZDFwPU1O02VcQrRzi4uBlevzuBBW6/Pb56mnGuejFGrLe1YPUN36oRdkjpVDglMfmieMrtdPoxEKzo9eXlm5uAfsfHr845IeeMCvE+uKIuJU2IHs2AJcgOik8wo0dAR5ghH6AreDNUPWscRfxSsrAHmc5yki1nEJeNC8C525lQjwzmnke7RFKMvWH1nMQIjmV1FZDo20xmNmbL7BYQRO4IZbji0dd0pTIjzJjxZDomBpkk03mEfcucLcVHBTJJpVr3OZxPRE4JnwmLQ+Jr8rMxmS6McfqJGCeweYY6V6pSCb73K+Go31Z7iP+XFMsd31El/1te2f/vNPh/tTRl/+HoTWWkJo4IEM5yYfCqWpe6+hXqt017uD10/qW0sOc7tvD/+h3HB/3f9Rr/by1to/2fztMP6SQctz9Mw/H2fuBK+m/bRfwHr8n/qqc9My755hqwua3WCQb/Qc0+KtMtDGHApDKfkS4Madkc30NdteknKL42HhvLjMwNQApsIrq/rbbR+Rcu5h1DQKrOv227xfqvvtXgf9TSnhln9NhLTEfukWcpYeCsjgk3FHxiPm3mBm+LeIbFkXETJkQv8SlEx7yHPgonoMeNCO0xScH/ncynd1oAhVZ28s9ekx+pbXf+d1MCq/z/ll/M/7asThP/VUvL4/8KHzq3xGTz6IUQAI5mmnUnzLLlHWL06jpjRRbJpo7+kunyQGUiqiGAtFLMIPcdYppx4ic9x++4se9Grh9Glms69sgK48R0/Q4htm+NRlGUELNrh243cnthYsWJl3Bn+DpEDiv2uqFlR84odHtm3CMkBqAysxv69HLiu92uGY7oP07c69ld17Nct+dZvdB3Q8tPuPEOELXz8MEVtr6PEzqWFWZ5oLN0rcdFG+iCfMEFPl4ubqngDoa/T0TJcUCVx+QDFebnZMHCvIwMajgDtedvO1KWVr0iNaL5jhZhOilUekaegD2n8znBiYzGpM08eAbtkMyPNEtsYw74etpG9H+FO2Obd1T6//yi/c8GSLiG/tfQGP7HmlCf3QN9DjAKdDlTrhYynzPoTuHmKSYPqYAbef1sMOQ5fpvilAfZJJxltxhkJeKYVoYw3ZIw3iV8KaVS75ciZ3D2bHrQ1zIr9k6ckRm5rt3rJpFFuRllV6PEjego/WTUs127ExLXIq7v9kY9x40od/J6PWvUARCqrudpXiVAmy9zEuZtY+w5WJC72RQikIM5SXSPW3Gzyr481g9yjPv9+0GO9Qjj4fMCdH35ke/bjYhu3qkjiIeZLheP0ZU+Jow/3KETFqvCO8HPe++hsLDqPT4e3g3QkIpetnI4NoJHqW3E/8cp1Q/u6XbspgBW6X+u5xX1P6eJ/6un/c40rlzJl5riX1YkD+P1DKxP7K1WLrKDhVdfvrs+6QdX1/1fzqkKNQzgx39OAM8GE7DLE1BCzaMMOZeksdMYnfIYISrzYnBxFvx2ef1meN3vP+aIywHyu4zaXTFq1mNurC0V2MnSnirNDz+WE/sh+n91fD0cHJ8HPO1h53dU+v8cv1T/pcn/rKc9M64g+jscG7DtrdaNyPJ8IFqaoTutjCxD0G5hGGos+V9/W3v+Hwv88S8bnH/LLeK/mU3+Xz1Nw39sPP8/YFt3/h8N/PEvm+A/FfEfmvNfV9PwH6+FP+gQ60UuZ4eI55ot5iS8a0PVzeUdmfPMe1VvErLhOeNPJ7wHShjujXCUQYBAQxa+5rbu/D8a+ONfNsB/dK1i/qfnNfiPtbTfRbQ3uJKDkrf5IFztRUaPscyiB3eyId3J0lUifcEsW0OU/1Hp8zoN0aILNoSbzCderk7r/C519sds687/o4E//mUH/EcLKr8057+O1uA//thNO/9g8/4MwZvtOQR9psD+HwUDEM74dvh/HkACNfkfNbSq/X8MO1AV/Tf9kv3Xt5v8v1qaZv8RcH5GiLZgxE8LjQzCuxMSIkgZQ4ZuVLrvp1Wd/8ewA1XKf75XPv+N \ No newline at end of file diff --git a/.bootstrap/part-00 b/.bootstrap/part-00 deleted file mode 100644 index bd83a05..0000000 --- a/.bootstrap/part-00 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-01 b/.bootstrap/part-01 deleted file mode 100644 index 45d4b3a..0000000 --- a/.bootstrap/part-01 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-02 b/.bootstrap/part-02 deleted file mode 100644 index 230bef0..0000000 --- a/.bootstrap/part-02 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-03 b/.bootstrap/part-03 deleted file mode 100644 index 6e7fb31..0000000 --- a/.bootstrap/part-03 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-04 b/.bootstrap/part-04 deleted file mode 100644 index 62a0bd2..0000000 --- a/.bootstrap/part-04 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-05 b/.bootstrap/part-05 deleted file mode 100644 index c11088e..0000000 --- a/.bootstrap/part-05 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-06 b/.bootstrap/part-06 deleted file mode 100644 index 49274e9..0000000 --- a/.bootstrap/part-06 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-07 b/.bootstrap/part-07 deleted file mode 100644 index 0224821..0000000 --- a/.bootstrap/part-07 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-08 b/.bootstrap/part-08 deleted file mode 100644 index aa68fbe..0000000 --- a/.bootstrap/part-08 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-09 b/.bootstrap/part-09 deleted file mode 100644 index 8ebe79e..0000000 --- a/.bootstrap/part-09 +++ /dev/null @@ -1 +0,0 @@ -JyyVN2dqcx0wMBS71XYaoyXcZycNET75dLvTtsaApcv2FVvfAdM+5E2aCTuZO0GjC9K74KJkzBF2oVCtFqKuuq/muuRcPk5ZvzsOa6pVWX8IMxYB6A7a9NNpknriJ08IaWjlMlpqdjtzLFNO9IF0xMy69+tCHTlJnsIwAZb3vhCMsYj3iWL4dOAMjzx2mqcFw96XVyUlG3ewVYoB0FyGgNmKWsAUaHonmZBPjR6byygHPRjpxqevqLl6938mgqBv3c8g6YnNyyARdkiJV67S2AAzD4IMQVpyHXTWfsDm4L8UDjYoza3c6+ljT2iKBADH8O3WPmDAXu/xUHFiw2HItwHfqbiYyvlQfMvlupyk8qCzw5Y+3iC4JCMTQJH/TQ0Qrdry68psT3AKOxq1SDdV/9wdF1kk+r1dUGTr/8khqCKuAO90DzDD/2cNc/5o/2+0/37xdHVtof9/iCeP/n+GEj+ovpd3x2VDn3Ab3cM5f3Akf3pNicNs0T+3qoJS/wFKQe8iX3eBCM+2d9HlzwrRlnJxRC9Jtn2CWteCdEgbn2g5+l5bWX1/82ftVRpxYhzC+iy1sofMGBW+ttORDM3Haf+gMT1eXpsM511TX9H3QxEXWpMTaqCF1NmxOSg0E9wk7eol/GiVw6zrSpuyU1MyTnpXZTlNzoRYFh7AIR/dskzvQuopdBGb4RWqXIk4/DtuPbsruV6sVaT/YtP03Ay1W3DxlOfbnRZvPxnhnQg5NJ2Ry5zpKMd345YPm0gYxQvteKsF3NRMj97sBZB+t23yxVpGw3XhnoXmI8pby/LnmrZqC8r6m3yy6b+VIvtOfcyi/yvPVxz6//zF8wX9f5Dntv4/V7flC+7GDtz6KiJws4A/pK2zeUshG2C5UN3OGDcYKqVzCT17xyUpJIVLm8mNS959VsBkDp+ASZzKAL8RGX4MVhG8VVeWgaYixQ7KwCHvKWgYOfe2uyO+B8CU1qk05xY8ioEHHErnpHxyTek07bC/WiZ1wV0JGn5vbnoG3jRoZX/Opd30zg+z1FscWYNCh4hYbEB5O5OR45rOxJr4OjXEh1voBQ1fPM6TTf9lsIC7mwDOiv/xfHXVpf9Pny/ifzzI89jl/wcj+AaV5jD4QfLtmKjMoPLK8xU7uEzSFIRGaFyTnzOQtOmUGSSCbadRvCPj/k5Qr2CFD/7+phwVjDZnKSKAaSGlaSfqDYAnqOhvZRnOK9WRQVBRnYrMCAbV+rPVJRTsU4CO/ileRb3uGlSNSCkm6oq2JiP0njJUJnoBv2d/se9LN3bLfVJ+8L5gDWOduR5qgaCW0BajLj1Qhr5BKaE9EfYfQrZ3lEsI3rH2NxAaplZC/hcs8cMGi+38tRNWhf8xfnz3/M6xnkLPDPy/svL0hRP/aX3t6coC/z/Ec8Rxv46XLtuf4/EFIhy8XXpKvzvJkLzvVxds32/1sfk/IgL33seM8/989YWO//N0Hfm/9VWM/7M4/1//QeGXKF6q/PAK+4N0vMXCqJE0W4vJqryZ4sDx85PG2iAbD6/GF4P+evSu8MfiOUUAExE3IifcRimPLPKu4OrbRVc/d/udwaeUe4wq61HlFLoUPKrwWSkDSzS8KutAEX8ebYpPVbr5NkJIEKsTs8l78eh7GPn35e/V2OFvZ/TfH5dV6AppM10q/Zl6JFaMrswpKMby9zkm+n0JR0usxOb3kov4vuTPnxmnt8yPUIpD4NcGFHLVjInHDUv1vtvIuHuZDMgZc33F/YTXbBt6S42v2qXSCOBRoGQjeItCuSwm7d6X9mQ8kPW4jiiPXrKPC9QstfdvG9isqd4e3CjmYQa0EX//iGBNemQ/DliTLpa/bTCTs7xXCCPVJsmoJGtyqMpukj4QrP29iE4BXwxzui9oG/6FDMO/kJVb9Unpj2E4tETJxwGJCwI7DzzuDNqdR0FeybRyQo6Uk8uE3E1HXwRaz4A9y3LhcQCfa2n224ZAd7b3CoaDXqLi9j4UKjQ0w0VpfvRFmtJ4OHAJ/7pZKBQeyVNdVhnMgHp+8/i/z9bWVyj/y/rTRfzfh3ic/W/Wa9tvMa3WffYx8/7PsP8V+t/n64v4vw/yfBdtIZmKdB5DZZ25tHSAuY87MrF0hFqFJI3Sdh+A5Z9JB+/2AOF3JqddtHJQmVdk+PZRAvxISilgKBri+87gNF3e2tuu/y3equ3XXjZ2Gge/xC9rrfpOYxeh7n11aalmjkUY475v1vebe9uHW/Xt99GkPwZSh75OemhIToFwphtLS+/fv0fKurT1t78tL/3Pf////ue//y/8f6Qg23gn0lybxWA+l8NxdQwN6Jd8N2IWA4pdEcTSKSvTxZAq1XgPHBlIp1W1eO73BH272XRTfPlv8YXtaPktTG5pqcmB8HGJOW0NbyHaDJMbLBrM9KK0NzkvR5hQgX2EOQxHOdKxxKggXfn9Fwy5Mh6hAwa/EysjEl2j5y2wmWXpUFvWSXFk3u2yBgsxVeMT53JR84uaFLcC0zCMkO1Jy9EFpkuQ20l5dChDwTgxzYYPmzucxAbAbNyl3AYpi1JRl16ddWEJKGFCX7g3lyPMus6+NigoYsBmjMAi7jcxBQ50BxgAoJty8FYR6q1e04vuMHXcqGVKC0q/YOeqidLT9tnZoNchW92TCfQ5SBiKe+0T2JceXlLzjskVQuNueZRgoGgDDYwabjAmqmiffsDsENWvwjM5+B8Y7OTzfd8CTMf/qytrz9cc/T/8d3H/9yAP6f/xRGAo4VigEGTr16qrJEAUTPhQUqGUB1Um21jhYpIjTJjaWllVokhBIo5Ywj4rrPVpo1TR5Don84MlIp6cnU1aN9klOdTqBa3nYTz4YWxEkpb5yqH47t4BRizQVUQKbvi0vbd1+La+i7Hg6aOwvptvymszpkz+dDHa7HdPu+O42/84OBXhHtDgECePpoMUQp+KRLqIP/W1xzT19VlTp22s6gvmVeElKQl6dHrR7XVGSV/gaLLFQBScQDkM8HCagIALr/yFWH9MC/F0xkLsAvFAcknrQSDf/tju9shk9BMa1DDfMcETwCsl1wkow6U/+afByZ+ZBqwPOPtnM2a/L/202RXnAvZ6cHaWUnImqMBAz85FCAbMBfmTfnZfk97a2z1o1rYO4u36K+BG7zL157Omri4iOEVUSr5AFD5a+MIi30BBG0ipiPMC9gmXieN2uYvw/DGB/YsZs0f+CnkxuhcAvgeZz1Tme5LwPumn7bNE8tjwZTScBHb/xT1N/B43/0+zN1/ceKJZPgpVQ8P025/inx7T3v7bjMltqYlQVAYRkqF9hr6ThsU7BbajrGmC1W0Tamv3EcR7g8HQX4Z/e3Q7vboya6e1HQWhMPPeh/Yend0xsIK6PRBaYW/2ZlffHAhWZ7Fz+yxQRlYevzMMHfkJhKHTCTopIknTioVTEFMlsT9NaAT+Gjwm/m51Fn8nhOoY5hsjp3NyhUGuMOQGDLh/Sv4hk/Hgso3ipOlO22Olvj/9x8Tjrc7i8axrJoL1dqejfJmRugnNTjsSd1jRSY+CgPoTf0w83eosnk5yNToXI8I0Bi5DzRmNRURXK0etNzX0HwOJm7URxOz48w+zdd8U883i7V6aDs/obKaydHKItjGR/DSBo97RypROgkmQAysQ5vG+6QrMYvGQwQEccMKqJAykMkrO0rLYe9Q/qaQwCgZY2SZUU0LV5i/GffF6GYuxJC76CiqVa9ymptZW1p5XVl5UBCIqCO1ujNpdFuJ5MJG5UhzUBZZFqhIR8WtNoVbrav2Z8BtgbRjnXU0QJeKFbWFxc3jPj6P/21pZvf87wFvc/z1/9mJx//cQT2D/7/0OcNb934rO/y32/ylAwEL/+xDPdxFsefQ///e/o63QDWAlqrs3PRvRbdS1VWiqRbRnI3qvObH38LrJhKRyTvdU8PkqSfG99BZjagbvBTF7v7QkgqScXrT754m4a6TchONB6K5wbN9jystCoXPgwDUGVRI3LsiPdDnaTfQ+fEv+Hu+yvsZlXESXcXPcw/H8y/LuTU9GftD3b2VDn/Z1LpUWz6/m8fD/2uOg/89XFvT/IZ7A/j88/V/16f/64v73QR6k/2tz0v+73F0u+IAFH7B4Hs/j4f/1R0L/Vxf0/yGewP4/PP1fe+HR/0X8h4d5kP6vz0v/782AZ8ENLLiBxfMtHw//P/0k9H9tQf8f4gns/zeg/+u+/L+I//cgD9L/p3PS/7vZrc5D86Ehmdl9QfsXtH/x3Pvj4f9nj4T+ry/o/0M8gf3/BvTf3X+g/wv/3wd5kP4/m5P+38pzwyL7ru3ZgvgviP/i+RaPh/+fPxL6v4j/8SBPYP+/wf3/U5/+v1jQ/4d4kP4/n5f+3819caH0X9D+xfNIHg//v3gk9P/Zgv4/xBPY/29A/5/59/+rC/r/EA/S/xdz0v/bO/DPrwRYMAALBmDxfL3Hw/9/eiT0//mC/j/EE9j/h6b/ABv+/f+zRf7fB3mQ/v9pfvl/SgSbhXj/a6Lu3vn/t0eC/xf+3w/yBPb/4eW/dR//P13c/z7Ig/j/3+bE//cV5GshDf766MXi+W09Lv5fXXkc9H8R/+VhnsD+f4P4L88X9l/f6AH6v7oyr/x327iWC9FwQeoXz6N6PPz/SOK/LeK/PMwT2P9vYP+95tP/hf73QR6k//PGf7uX+M4LXmDBCyyeb/54+P+xxH9bxH95kCew/4/C/mvh//0wD9L/eeO/3TW3wYL0L0j/4nkcj4f/H0v8t0X8lwd5Avv/DfT/fvy3hf/XwzxI/+eN/3b75D4Lyr+g/IvnMT0e/n8s8d8W8V8e5Ans/zfQ/y/8v7/Vg/R/3vhvd85xtzD8WzADi+dRPB7+fyzx3xbxXx7kCez/44j/9nRB/x/iQfo/b/y3O2V3XdD+Be1fPI/m8fD/Y4n/toj/8iBPYP8fh//fIv7LgzxI/+eN/3Zfuc0XrMCCFVg83/apLlfPAR7O+4NR8rX6mIH/V9aeqfyf68+evQD8v/piZeH/9SBPHA+vTtuAteN4eelJdXh1dDroHC9VyXELUN3SxfiyBz+Wl6rDySidJMutX1oH9bcxYNJXjZ16tTc4bfcA4anvo0k/XX6yTO8rsLjjpPpf6aDvfq+eJ33CeYN+BS+Hve/J5+R0oj9/64X6jT58/tvj8ah7Mhkn6dfoY9b5N/L/iPO/9nxx/h/meRKh0cYm2mtGyaC32TtbnLTf01Ndrr2u7x607lHc854Z53997fmaS//X1hbn/0Ge7+g2t9b/CMIQSnNplwQh07Vraem776LaZHwxGIFwuLTUTNqd6H1ncJouN97u79TRhqt20NjbjVv79S2UfUA4GaVjlIDSQe8jhwXtdVEpDAITiVwgGCUgSZ4KQW5wdtY97YJ0sjdM+rWGkJSkL5mQTVCQwoziiXoXpSDjdKGqlF5Gpxdd1D6DYIS/xt0zlLtSYG8u22mZJbouCKnsmj7qwCst9Z6AqNkDsQ5lpzb2k1Kf/UgIdbQO+6NBB9YlOhlM+p32CJZDr5/gaLAeiFTdDv/J0U9J+o2G8uZcji2tRo1x1Mc46XpuuDwRsz8Ji6Ky5Q61UMUIbHTdLm7bK1Lelqp4nhD2bNQejJa5UWg9TYZtZr5wSzhMO8vMPM2Gvc6jCawGagN+TJJh9L7Kqd+W0w/dXi9dxjFV2rgEy60fGzs7BAKw56fdNPlzNJyg7h/E6h52NUrOkhHqFmBl1L6AwAttqNXCGwQQfvvdFB0I0tNRd8j3BlsgpMjf0NI/JiC4R/tXAJn9aL26uvqDmjIcatyeTtTrnoxgm6JBv3eFTWDQ+vbonOAK/hi1r6ClNlQZQT0MZneR9HqR4j3xIGAkg1Oj56pch9N2f9AH4OtFf23t7drDlrOrSEgAWIMtuMTivavoExylcSIE7jPcucFZRCxz1D6BQwM7T7HyCRTS5HSUcL8HGFMJNmA6L/6emuVdfe8y4vARziEJfB3RJX+E5veGnG8HejjFI/heJflDvcBg8IHT/eFVTh8WEvaT8vtVo12C4NNeu3uJ6zg2Cre1IiXpnw0AXGnt5QHCboXS5lPS/gDHDdVLKQwQzknZxEnUZBkVGJ2TwWf62h5iqIl2D17janEsqh5sALyAhYOqY5VFiENTpUZ/l+3RBwDt/rh7mZiIAAARp4wgNqTjDgulY1jxWcazqFUpUmEmFUR8iH7irYe+AWlO+rDPg0uhklKTQrKysbT0/v175MOWhgzMlcto0sdOUjg73ZSEsaiSRtkHj8dc+Wi0gMve7SWwJlHlH9lVI97qZVpeHMjS0s+UxBHRAWmk5DHtdc+S06vTXsIAg3uBjUWXcLphnu2y3CJYek4NJeNBS/zcSwfRZIjHQWjYAP2nQ9wh6EcsO6NL2M6u2A6LDCzUUvf7VJe33tR2X9d39l5/NRZwBv+3tr6u4v+8WF9/ivzfs7WF/d+DPN9FW0T2e4PzpaUaHGZAjHSVz9xAinpzzeEQ8tce/kA1Bao7WqmuVleOo0q0trL2vLLyorK6hh+Acex0kg6yDoIhMJEfow9ErSpvXAUJNeqqux/pvP8Zatr8gEHvNWcTAbVmFTxWACLZ4YaENeIQ2I5e9/xirNAL0SNMTD9KuzhdJDoGCaDrDWyKTRwF40WsG99yUEPALX5IOpr7khEPeQxqmlSUCC00ewYdIOkCop9e9JM0Ffr2suUpeQmUDTujtQG2Y4x8Q0Xy0exOwRQQLTGAtqSn7bOzQQ8RKS0Z4FwxrYoxLR60xOInANLQZXto0K/exLTnOB8gQwIMwVXapZUVlxewHsTytBRnrVghIg0RtAqME4kPeHMBm3l6JQgwj5l5IeKDeM9wfctY+xwY8E737Ewz8GXJ5prcLTeDpiWJnN1HRW9p59QsTtBepSLsVU6A7eglZSEAqDUkkjOC3e7T5dUZ8BFyVJTqkKCJSX90Th6uUGlwglw49XHW7dPkB0OsNpB8lIZEFmkMdkowUZVuv8JJkol4Ym0k/QgO4+RcUk7JLanFNABIsZqwGLg/7V5Z8WtMVLHRcwAOTs3M5jhSxuHZKxCpKFAwIKrKR1lcx9EWT0AcwDwQ9tkkNpksgoT4kHSqUmQiOSJBB2AE+hEMGC/azulw0SfFa/FSnfr3kda9GwmgW3vb9b/FW7X92svGTuPgl/hlrVXfaezyFdyCV5j5VO//ut97ZtD/FyvPPfoPVGRB/x/iMfQ/pioD4/ryOaz0AQV9DJBtEvPGk1Efi6b///a+dLltJEu3f/MpEPKN8EyFKGMn6folSyyZYVnSleiq7unbAYNAwsKYIjkEaVtTURHzax5gYp6wn+TmObkCIAUuEsoLMqqrSwCYyAV59vOdabL4TKWDNgGdgZA5MC/kHpSMTekD8/TDdD5dorKfLdoxpWKo/i6pcoYEtGDZEXSKkp7BwvjpJ2lbQXolzSuAKUwHzQrOoQ4q7Sbp4qefJPEpdn9L+SulvmgWAGoSCosIMYDdzzkNAs66zFA5QS++sApQUnU3Wwgtns3x/dX58QUjOyAR3awlkkpoAXK52gyCZPtQ8RFlOEIGcvgAB0EhTSfAYLHTCTds7k8/UY4d4xr+9NMhasMzSabbQKbvj7DOT4kW34WLefplQwosyTz9APgYkHmK4AsirDgx1/5uw09kpYadi92Q/CCZzpkiye2IqyIsysEVWSm6gi8oD7FoY4gFu8E2811G2E6WTgGGjzAFncSo4Wva/Hp1nenZYGXDYsnp5NM0CgWiNu0QjgRlnQN6/SPdzYWUj8f3Wv//R9Piz/gBEScCTl0cazIRO7CiWhN9gn5toF2nGX3+3piEd1SWx2Ed43d/R9eAvss6gvVMk3swfUBwiZCphdT7c8s+wh/AHqPIkxOqqeR9KLOBxG9yKUFcquIit3PExGiQsB6WvukKkDkcDiaGawNyj2RCUskMB4N68ZAM/HPLO+KCOilYaw5BLlfqA6UhdE8Y9dLs5VwoZ9E/a2Vp/whAUm7BvMfu5wRgKol+PGREcDpeIepK+/HPrQ4dbUglqjyR0fYdflwQhnnw9s+t7pFc/pJpGonjz63eEQ/z0qOpoE+s+yHsYpLgYBcTqqMxuXGVjIiTGoO9EFLHwSY0whXkAUssHCv3oXOj1vrzxE2zeCnAS0eze5Z9bvy/lmG02/yrPeJ/4m4cHG99Qg7YEYFpqU9HmxIsSsax8GV63KGu+BW0NU7Kub5W/hwZGRYslzIbSroo2bvL5BNtcFzE8tNilAxIAPu+8NSQZDovboSa+GHuqziUVvS12g9ncWFCwG+ywhUSTwmDAKBEFGkHOyqctccETIScx3GGrfk48AzQO5Spjadw6FLQg1BnYzsKJztlLgT6/QE5oDTgE9iXP6Xz6QQ+w0OsRk8JODuWn7iGL6LjwDi8zG7h/+/InEcKwjpyAnMkyD2EA+r0R3lamGdGbBz/BNCee2S8DSP6/ZO28E9xWz7jhlLoyBvhMTPyZ435qYO4zJlNKHseM5mM9Qq7BZODr2FBiQMdO0dobCPwYlxhzRdCxpHxGq8Jx0ou4JDTNBx/0fz/swEl/kLkijgL5LJyXDkrfIafwr3yOqGWCqyWfVPX7OXoBgOrkW7toZs1IZ/JHNRZ6Ng+cszcxcnUoFLGJ8YxqIRJx/KBWRfoHUqR5nGbCnn0k+W9cmt9JuWIsjbLfzwhC9h5I4wi0F7hebZr6hCVbf5fl1GfDu5Ut6TD6j7sxYWoYE5DFvyD49I0YykrBXbZ6/H1yevBsH8yfHfdV91pHlrO1eDj4iQkJZn28+HgF4gHvjl53X97fCO7KJqa0JokXL1AGcOF6uXyqn9xPAhOLukUB8cXJ2okXLDNexroac3Q5d3eSLqFfoTdAgUeTU7W5V3ZXf+vx7DWajIySle+mhmWlgtwm2ZUTWFLsibImPUh+ICIThYGLM1x32r9/Q25T5K3N//4l9vFYpa9fPHiA2XdyxH9UO5e8Hv/arww/h7S/aEb+e/h0WysHtav/mtj \ No newline at end of file diff --git a/.bootstrap/part-10 b/.bootstrap/part-10 deleted file mode 100644 index 18a13f4..0000000 --- a/.bootstrap/part-10 +++ /dev/null @@ -1 +0,0 @@ -V/lu2tELYQh8/Lwf0bbJ/3Fc5f9p8n+evmn7n91RrtJmfp9H/Ri233/XbPDf6mnr9p9qKY/2Deyw/03915raQ/tfiC7a2UNQYf+3fBX/zfe/41p+Y/+vo+nxn9fKuHnF7F+ogXFTGDMevzTe/3p8PsD0vDOpsYeQhKc8/0Or+9I06T//xrL4ZLcJVaHJnKpmE/gBFW9tz39p7dngHX1hEUYd/ub1Me0+JvHID0d+13VGienHThh1ur1eGCZOp2c73Z7fszxCOu+54qksu2gzEBqKrrK0WjdwSGTynVLKmfZ3Ts/OkhkveFyZNNXPyARGCAb0CX1iTrVbroWij18ELLZFwCLqfqzXV8t0HDOfAARhgXGD2d8AYLkt7T5gOaDXMxZsBuqsGCaqnPw2N0xCQue9yE2E889ehUaS6eQTWBKEMvIfyxA1GtBkaOeXE7B2QOjHZMFMNcIyhKvFjcTCTiKjZosVI8CUyo0s9GTl7uDnhhYjYX8/RUsQs+ug1sdtrNPxeESVHhGfejHlNiOMMGRKPV0YvgwQj0xV7oUIEFUDh3eG6Xgpolmu0+wjm42MQzFm03Ea3bdafW6I1++x4FL4pfwOeVwn89DTX4nrdDizdAImpcU0t0fiw63Zaf0Q/aefS5rQTwfDRvd4RxX99zoS/63jOh7Sf7PJ/66l/d4yjANhuwm45yw7eGnADXpLWFYC5kehNw4sCPU6OGT381agAAye8Ix9ZIkn0CQv3sB+b9Lf05t/HOLL0dsTByHeXMVEsKcD6TYVo4THTTmWAzSGqoGrWH94Tv2FH7MYG9rwAqQo8FQxVFqfAtznHl5xWVH/gPuL4KGS1CQfX04C+IrgobWHTjwsx1Qeje4Igif0v9mDcm1x7dMYx37WhrU1O5bdtrpw7trH1iubrZ2aiVpAIEgBs4bD78HyK0aAtyj3huubclnxW00EwOk9jgyg7xTY6bWB81B5uPNizSK84C6eNrh41OrBhrHFEz8ash/9W7CmoyDXEXbCzo3+zbLz0/rjq7CiPUT/1ae33zsq6L8Jxp48/fc7ltnQ/zoa0n9J5FkoKtAATptZXEUwozeQGl33ry6vh8HxxWlwM7y8Osg9hTIVfWqyHI/xxjjMFoGqCK7fAo+PIKnBWf+if43OB9bhhHxZBKzCuKJHdJs+EL0PuHY/w14uLi/66txOqawdcMRxmMzf/8GJ3KeUn0HLfvBsspuo7yBFpzO96p+yyyx94UF29ZUc7Y3aQ+e/wDR3fkfF+bdd3yvKfx2zqf9TS2Pyn+ZdgvOCh4sdO3pX+JfkSWKCHzLGk+OrNub8tU8HNyeXv/av/3YgHxGxXfRBqtsReV2dLFUC4ABv/nG43av7f706H5wMhu3jk+HgV0VBnuD1/JrxgOz2QjwPrjUt7F4KZdBWTeOMzoDKi6/62wyervXgl8GWQxcD1NTtNlXEK0c4uLgZXr87gQVuvz2+eupxclwp5tBmUSkv9Ch+JVVv9njV9F6dDy5O29f9Xwf93/aYW4v3foDOd8W6wAsfCI73+vLyzU1Aj8vxq3POVDg/HMNtbg+QAq0MVJQdFJ/g1bjQkw736UbdDFXPGncTv5Sc8kEGuJxkyxksLK4A252DMxm8qqJhp0kpLxsjeMQIjmUxMFAc2jyELxd/Ix5lESghi63JpuPVOaMHcqExNDHdQHv8HM5BL8i0mbCECL4mP2O0EkYRrU0/OML3fkvcvbo9xP9LiuWO76iy/4CxP8f/6Ta6Tfx/LU3Zf6bjFbw/JiyyklOHX6bREmINRdhKe46Bh7GRUJm8nS3TBWHRwjzW7+igSGyH1+dt06L/qDv6D5B+gVWUvwgt12CbVTFakBc1iRG/Lsx4eCvY5PHtYOydpJSwfJgTMjkq0WVIN5unYXmipSXAq9pwS9xjtWwirgZCNTl+N7x8e0zpcTDs3wyL63F8UlwNiPwtjOJ6cPNm3SiEzkWVlOOzvnxETflDOMvpQCq8bsUiFJeHke+TdS8XiYlFBsnmdt3/v8XJcb6Q6z4/cL17CJ6DjvqlMFwWuMgidbXkfHYBwjQxLI89WvoIvnKLTL3tIfovpcU937GF/9/vOD7Yf1yv8f/X0jba/+k8/QD5rRg1v30cQJX9zzLdvP/ftjyr8f/U0p4Zl3xzMUGl1do+JeIHpJrfT9vo/K+yFmzxjir53+rYBfmf/meD/1ZLY/b/JEFBKhA+VK4iZ/PoBacF0/nR7F56ICE2BbMTgtxtKWLJ8t9YGzwYp3cpSHKO3fG73EDCEeGUaJqELJgjAEcqSm7aPcgqKcura8b90Nirxp+XQLGyOfoLTHkNVJ0AMmSLUi8MAmV6Aaio5N7ZnEREaAuqqwwTqAIhRgcYxpLXJzCDB3rVVCnmM9W8p/aeTXXNC7iDuQkUEfoOui0ZKeoUIvCr0uzSyNpfeduI/osQsx1DQKvoP5X6CvKf6VtN/ada2jPjTM9Lljl4lDYSzEOKpndkJ6mwEFSpakoMtag3FozIzL2CmmNS1nQiMxVz8YesX4ZZBXiDWSZtRywkkFKtVmtwc3kONhf29LHoWOVLaglnrUsEisJ4QIUfaNzRiYwIy19NVbQkQ4cQOJq8/yxb3s04Vqo+O6JF/eUT6WRsYi768t3k42T6mYdd6mYxDG0UbMJYsscEuIJYaghmZJYxNhl9jjdoeEGrCd2jdAHTgRR8FpW6wLzG2SIUkYsysFL10Yj532Xbjv7v5gSolP99syD/00sN/l8t7Ynkf0URV5raE2k6Vy7UlYZ1JbOLIG4qVq81FP9SpLsMLyzLgRko5NmSdyDHTqBDwUcOtopULU2gMHguRFO+iwFXmiDfI7Ydur2o40ee73S6nm/7hPiuHXXsaGRa3qgTxZEXjTwnDEe9bpj4iRs5ZqfXS3qW5bH3A65tTBlEqffQ70bdUUg6UWR1Hd+yzNijS9TtOBHVwX036nqW23PDkdXzwzBOkhG9FnpRJ4nIKIl5rCjTCw7OL397WMbnTmTG0lCraaT+r65tRP9XhLNs846q+C+nRP9tKAnU0P8aGtL/daHeuwd6H3CkFRUDQ+bz6Vw3bhwwKCEMAj2+udHCruX1s8EwALCDv21AaBi+T5BNwll2i0H2Io59ZQj7LTPgbB2+jrhVRcLq7Nn0oP9lVuydOCMzcl27100iK6IEOkxGlOrTUfrJqGe7dickrkVc3+2Neg4l2G7P6/WsEWUf9qjreVq4z4LMVjBk5q5l3C0AELopZKAFc5LosVDFzSrHcrF+GFrY/v3EBEC29u+HzwvhxcRHvm83Irttp44gHpoq1o/RlT4mzD/ZoRMW0Mw7wc9776GwtLo9Ph7eDdCQil5a20SCNfJHqW3E/yVc3m4KYGX8l+cV9T/HauK/amm/M4VldTzQ08Y/F86zcm+A+ZG91crF3LI4p8t31yf94Oq6/8v54Oz1MIAf/zkB3BtMwC5PQAk1jzLkXJLuTmN0ymOErJyLwcVZ8Nvl9Zvhdb//mCMuJ0juMmp3xahZj7mxSv4g0t4bl1WuPUT/ebrr3u+ooP+ereg/x//wOo3+V08rlfoCOJCXxil35VyE4P2BgmAcXBIRQQBcdHD60ni/Jg0WUT+W/JmdcmexyjfPGX+pQZTYRxa9c5yv7Eb5BJxQeuOVQvCkbwZ97724ui0mCJumhjlMf71tKjFDFtk/wAp7Ya44AfydTlKRexFPJwQQJgBNU/Pj8GBeBikNZbLIRAK75r1YiMOLaL70v8H1Y6DvB6ITBK6FSvvA5x6sfldAaEc3lyw7gVAZUPOuiBAroCVz6LBstuJJgRQbMgcXB6EVuO2qXjAg7DKE9lZrkMN2l6juh8Z4GsZsbAwrF6tg5JAlWY2QSZRyJGt98QBPRea18jKBYngI7woPQhorL1EmnHJ8zBDUwVyF3FU3T0mScXN1vvi8+j38iKOMfInGSwZU2VqdXJMrHrKcIGIshszDsZnOOSrNciJ715FyGdIp2NHhPTFCyOfdnIfCB8k7yjt3JSINhu3g3gNsrNDQDM07gL+elH2b3Kl5vBphm9eglF7S+/ySYRZzXASbESDI4eSef/9YfIbviIKsZQxQ84if5NwClAwIr8D7I/pBcVe1ROTR/a6iWB5CCHMHsr7hEtyGYQOlohpL7oWtVv4B3BeBQcNWj/XJPdbZx3Q2E3t2w0C/2QOo3CPsq4i5ZwCi10h9VlCezPh8C18/B1NXgfXpZLZcsDcMtSQhui8i5t/453//jyFeg3+INAL+M/q9MajwOOeIznu9X5Hb8FPKMNLBfy2gic+oSHphCCxW7L7/16v+Cd0U45r+Dy7kUW3x0i/vzs/5b/GJi9P+VZ/+62JoMDfUCT4roZAKRXgYWD3mibQRtIjDDokaE6Jk1jSKlnOJ8rwIs49A0LSuJDpSxtC9y+jSom4C+651aGmAX+JBCXMD0aFDqEoIWFO5CqXwGn0xBVa2hByXtRMpDYEjASefPUKnPddQ/FkiPmJmryExYl8y9WUuMxgefwWPUBBBBQKFCjgWZVxhdMs/UHpwoYpAIfjgHgvJLu84ZWXY6opWMyIjwKYlyRZREfhD8Ua4k4qKjEBChPYkYaW0gpgCtZ1heDFqUKrSdbiKHYjBMAANegiBtdLHUypiLxBcXBYIYUcYGUUkUJlvBNIagiOgNgPyyIV6it67QSR0jbepfEzgfxBgIo7fEZNDfklZRSrE8p/ncLavOcA/Q2TPfza8du0h/ybhM8UcpcJXdGRcTItpoJ/DTHDFGJahMOKNaqzQE8T1kCYC5QlaBf7Lh8fABQbheDv8T9/y3Cb/p462wf5LMrKrKaDK/+u7nSL+p9dp8H9qae12u5W3eCmDF+5/kMa57FIeEvrSeL6r2Pi8FRUk6udCon7e0vnSS+Pvz6VA+fwfLZGeCteFNEkvIzfCZ2WeLL0aa0Izxp6oaj2BrkvQe7+vCt1/ijD7P+goIMKUxAHqHizeCoZejLR6fmg8XxNlRecGm9Z6ponX+wrxlyLOd69euFp7KfRfqVyquFvNPjHisn1ZpX0n9VUhUeNPpaKrSZ4rA3yp6CPqa6BdISIxYrf+qnRFqK8qn+eKIYEKJbzYZYXmCV2s0DIRuJQKLJAisk63E4kvebXuJVXjJpqoKB7jgylZdUIqtPMTgIW6sASUAi/NdF0FBi1PhiGMMVCuSEU1swpa4gc5nb4AbIp+wFarDg3srVRzZDg0QQOVgKGVehArI1v44H7GqanfcZVKlmTloeQKu1aJ8FTpZzXIpjrYrQZz+/7kdf/kzdXl4GII6yqCGN/nNR34WtYgzs55HRx5R9UKEqqR+nSfUPJ9iP8jYX0EFPgd5D/Tthr5r45Wvf+KduyKAVPl/zdtt4j/YtmN/FdLy8d/q8wbFbssZQ8VulwCSykApawBW8khibBnCvgyF1C+aZz+pygptRzH3DeSR/TgvwVUdvbLB4bBwUgUhgq7ejfjcMRv+6eDd2/Z1TEl1+NccDMl1ukHGQ9+JapKki8ps19OciNGFwFYg9hoxdHiA4aoJg23V75DGLxwnKsZxtHGEZB6HLywWklAywJUjLjM0cygWNZ36uZu2pr2IP3nsHr7vmMH/u/4jf2nlrbJ/itv9W6fwtb7b5ue1eD/1NK23P9seXcHHpmtJMEK+c907SL+n2NZDf5HLQ3lvySdxAIcc1uEBwkNPpsTDrcqagqUYvgell+UoPlS/kEC+k0Wbq+oTpEVQgUP4jRJitdkFQf9mqrbIJNQfigJaJPzr8Pq7vKOHei/b3kN/a+jbbv/BRTmjd5RRf8h2S+//45nN/gftbRnxiss/Y4xnde4rTJwYrxotd4DWZTxA8glEIwCyyuAAix4x1EuEohVK2P17rl2e6hiBVSFeVnU54UMRhRRHxjpJGK6Gt//E7W9zv+GUmCl/c8v2v9cq8F/q6cx/OcNgQ3KciJ6/zSBTFTIUk7TKOoQ0407dux4YWh2KGu3qcSfJHHidGNK7/1O4naSru/FXi/qOb3EHoWhb3XMaGSOuqFebOsBZUTPxu1GnW5shzGEeBPHI44dAmoCiSMS+Q5988iJrG7omlbPJh0nCTsjrxM6Pcuxup4p63WV62pprmDL73Ycx4yTmPTcxIw8O+51Qs+JQ0In5pr+iPRC3yWeTzphZHr0JaTjO5Sz0fFEPZWTuw6swRzZnW7km12SdHsdx+u6xPUsuiaOn1g9z/fDxLS7I9Idxd7Ij8zQTeIwcrtu4piOayWqsNd8IcGosc5BwMPKZLGDrUT1H0o6/v7btvQfGHI4T+lp2NwGUCX/eU6nqP/7nSb/s5bG8B+AqQdsh5+GDuXekKUxicJ58U2jJHZHvu/GJOx1fZNEnh/T/+t2fLtLPyDL96hYkHg903SJQ/wu/V7CEGi6bTkhJb/bgfSA92h+B8UCAKZUcZU8FWQ1BnIA+t8XqVx7/hkG4GOk/1Wef7Pjl/z/nQb/q5Ym0R4b5O8fsq07/wqxbP93VNp/VsT/+A3/r6WBWecLK23PC2LJVE2BYqrqlW+ePovZICKls5AVkmZGOhGJhX/2/H/0tu78iwpPj1D+d4Pz7xfr/3pew/9racz+UwF8WSjyLlK6BDq8ii4K0lgLCtMrO/2jEGukUtu+CTH5u23rzn8WAsAAC2vblwZUnX/LNYv1f90G/7eexuI/R9l0vBT5KKJExQHmwgaYxMoh3YqHfqU2TKgKjjZhsznZX33Tzz9sdLKUJODR3oEq/lbxf65vNvH/tbQH9h9MwI/yju3333PNJv6jllax/yWstl3eUcH/Ld8u1X+xqBjQ8P8a2jMNXEur1nLF4uIQ7Yv9p5EJVIpfj88HpwBIcSaCBI1wwYG+irZ2RAJT3SYp/bDms3k6gR9wu7+1Z4N3yPTE0S5YX4VSNSyhkyVQ0LnNo9sUMk3QSHIDQrJWvkb8iCX+ndODs4Sk+UOAtQBMFh7rIrOR7wFyhD4xB9yY+8UtoGSkCwRAgaiXuD1OR4B2zLA4WK+vluk4ZhE1h5CqyRFGYEPSqC3RlkBEo9ch3XM5wegaMUwGUMJuGwIIUeR+5irQAGpJNJ0AHqiEZ8rV32GJlzIlMpfUiKtlIGqvRLKRmDSYxFMAT2FwUQilU0qjxXRtoiCSxtN70EAlUEuuTA0H4rmYwkLzJ1WNHWHLNNZmY06wxjRmWooUWp6uvEg/MavVbDpOI4CrkdhL6p7KJpXfIRbFpuLx7YRkGaCzqUpAyp6m75H4cGs2iVXQ/xy66K7vqKT/plPK/2vqv9bTVP13+j0LF+aKCOuAOTnzIdtl0xAkMaPf9cjSw64D8Qb2exOcoyIAZlOHrQwV1B2tpgofF7orHzhGDqYhrzKj/mKRPHxsmoYLT+GfbYbapD8mI8d5dJMWksSof6DFkZfhbcXjy0kAXxE89NCh06sBYI/lAemhSfBEOVRJLi8uP8uBLEBWWqbZfmWfOCpSiE1GK52wpi6EuLVLZQgWRiakAM39v68YoG8WoFRpA38At1Mswgsm3rQpv8A1kOsHu8aWrwrIVHQVFLr6qmMEKui/+vT2eEeV/c+zOyX7n93Y/2ppzP4niDximiAR5bR5OQcxL5BJPtf9q8vrYXB8cRrcDC+vDnJPiQTjyXI8ZgbEMFsEClVDv3U3jSXSeHDWv+hfI/AH6xDw8IJQ5HZzYkS36QPR+4BrPK7x4vKir47slMraAQaok3kudOdTyg+fZW+QTi19FTDTK+ELYeUyvpsyExXnv8A3d3tHxfm33U6x/pPpNvgP9TQm/4lKB+mqKts6vr+C6Gc88eT4qn3zZnB+3j4d3Jxc/tq//ptesAWxvEqFstXJOr08eQcAQZvUb1j16v5fr84HJ4Nh+/hkOPhVUZAneP2qygYrDsx2FSTUTM7oJKjI+Kq/zfhl7cRtRi8GqGncbaqLV45wcHEzvH53Amvcfnt89dTj3CD5TC/pvlGuykPTw9D4thYVv9vcWgojBSopSe51O51+DATTe315+eYmoCfm+NW5rHyJLBHBR7hJQAq0EKeaAYeSHRSfYOaVgA4xQ7ZEN+pmqHrWGJz4pWSWFdUbs+UMFhZXgLv1FRa8AmudJsUoHwYeKUawGqV8tsxuAQrrjlDWLh59TVcqM0KGfZxNx8Qgk2Q6j7BvmR2mYgo2KfyED34O5xORvcJnwiKe+Jr8jCDziIPMkGnV8VVgaPjeb4nBV7QK/l9SLHd5RwX/990y/lPHb+z/tTRl/9HxnCRtLuAzcQTFMI6xRMRnMFhjRsgCkcK5xgs1IuZQ7OCgSGcVPJO8o4NNMwAkME8LtEfCUP6pRM/wHsOxKu7LYRsRIl3qGEereczqecTLcNxG7ECDUgIOxf2ZezrAuA9wT5ygZWtmY381s4EdSdLxmFv4M+ZYgBCNO8SxVN2um4vz1cyFAdEjVmPGEd8Z6icQY31ga2bifjUzmY4YYhhyMzYrrW6F9GB8SgWVXT0hr44JtdZCt+nFu/OkAq/mcdfyItZqGV5clamJbwdnzAQQUBHstH9x0i8uhESPU9IZABTmR6LhvJVGUgZAW7mPD03R3meKx++Gl28hqjIY9m+Gq6Znbza91aMoTs/efnrO0++gs9kUV4+kOEVn+ym6Tz9Fd7Mprh5JcYru9lP0nn6K3mZTXD2S4hS9Ivn5EM5ydjsFCb6CIBVJFV7VkSbzLxeVhooaHYeJFHDjB/nRFmaXJyB69wvyBdWQ401FpNW7u3ZSq4/+BpOyN52UvX5Sp9vJS1tObfWR32BqzqZTc9ZP7dU2wtOWE1t90DeYmLvpxNz1E7vZXJLaclqrD/cG0/I2nZa3flqXW4tVBRrztTrkam4V+r+0Fu7zji3iP/2O44P/z+o08Z+1tE33f8qLWLahiOWWcaBV/l/LKeR/27bdxH/W00rlSa/JbBxGWGQznXyQcZ9GNB0v73iwYmjkQxwMNF3jvekSSnt+nrB6dH/27JpW1TY9/6u8RZu+oyr+r1PM/7IdSgCa819Hy+P/ \ No newline at end of file diff --git a/.bootstrap/part-11 b/.bootstrap/part-11 deleted file mode 100644 index 4544c47..0000000 --- a/.bootstrap/part-11 +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/.bootstrap/part-12 b/.bootstrap/part-12 deleted file mode 100644 index a810e36..0000000 --- a/.bootstrap/part-12 +++ /dev/null @@ -1 +0,0 @@ -/7+Wptl/IPNDRCNBMDADcgRrz2Q6vwvHiMvIDD3wmYSjMTk0RssFgkbOScJCi9MJ6BCyH4wLwrjjOaiPk7RxC31Vrer8z+jGjtMPt/uAQFaef7tY/9Vs9L+aGup/049aEoGm1K2LtdEDbpcTJhQILJZG5/umWtX53zP0H1ul/dcqxf+5ZnP+a2k5/L8sgP1fkEnOyAPQyCQOpjPQDnhIlIzKpt9K0mbBv4wsIC1RP0YE0pXGWoiDu+pfvx3c3AwuL2S9TT32/7frwRDCuW6G14OTYUN4nqBVnf/H8ANVnX/bt4v832nOfz0Nzz/d+UAR+YdP3ybOGQb5zNI98zcYTPLKexsRieaQP3KrOv+P4QeqlP9L9b8s22rq/9bSGv/Pj9208w9h82/3KPOztlWcf8vpFPCfLMds8J/qaYD/ki/7K74HNAhmxOAcABBbmKUwA4TReZTSe6x+DJMQtUJCMYkQRJvVj5kuF7PlwshuwxnJjgza6z2+DXAEBF6/fD37iUgpwcoqgAC6US3hVtt4n0F9Hl7B8r3xz//6X9oFMcbTz20AXjBG5Db8lE7nvP4LvOu9KiX6/gi7yNfBZL0kEP4CYXGfoUgPIGPTAYzGxLhLP8zzEfCr+tRjK1iHYQ5aRyDuZIvpbMZq84igHAGvIGJzsL9VvJr1C8bYO7IIISTXEDfZ8KYzBt86X07oQiRTqO3MBLIM8F5hbMq8S7XAI4EGFMb38rOAgF+D5cgYPEfGeI8ZMu8PNTgfOq4xixlCnnJIN+5uiTZjAyDWyWcjo1schXN6C1eTbg/tiTEUXjRJlz2w6/mCfj/nD0LB0omNp5MPAGURk7nxXoe2fkFHCCBEULuoMUI3rWlNa1rTmta0pjWtaU1rWtOa1rSmNa1pTWta05rWtO+1/X/QoBuxAPgHAA== \ No newline at end of file diff --git a/.codex/agents/plan-anvil-profiler.toml b/.codex/agents/plan-anvil-profiler.toml new file mode 100644 index 0000000..8cb629c --- /dev/null +++ b/.codex/agents/plan-anvil-profiler.toml @@ -0,0 +1,6 @@ +name = "plan_anvil_profiler" +description = "Read-only repository profiler for PlanAnvil evidence gathering and instruction discovery." +sandbox_mode = "read-only" +developer_instructions = """ +Gather repository evidence only. Read every instruction file assigned by exact path and verify its expected hash. Map architecture, dependencies, test/build commands, state, deployment, rollback, and affected paths. Distinguish VERIFIED, USER_CONFIRMED, INFERRED, and UNKNOWN facts. Do not edit files, create plans, propose implementation code, run mutating commands, or rely on conversation memory as canonical state. Return concise findings with repository-relative paths and evidence. +""" diff --git a/.codex/agents/plan-anvil-reviewer.toml b/.codex/agents/plan-anvil-reviewer.toml new file mode 100644 index 0000000..f3078ae --- /dev/null +++ b/.codex/agents/plan-anvil-reviewer.toml @@ -0,0 +1,6 @@ +name = "plan_anvil_reviewer" +description = "Fresh read-only blind reviewer for generated PlanAnvil contracts." +sandbox_mode = "read-only" +developer_instructions = """ +Review only the supplied immutable PlanAnvil review bundle. Do not request or use planner reasoning, self-review, prior conversation rationale, or implementation work. Check outcome coverage, instruction compliance, stable stages, acceptance evidence, traceability, risk controls, testing, Git isolation, approvals, rollback, recovery, privacy, and the generator/executor boundary. Report concrete findings by severity and conclude PASS or FAIL. Do not edit repository files; return one review for the controller to record immutably. +""" diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..c46e764 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,3 @@ +[agents] +max_threads = 4 +max_depth = 1 diff --git a/.codex/hooks.json b/.codex/hooks.json new file mode 100644 index 0000000..8c6fdcd --- /dev/null +++ b/.codex/hooks.json @@ -0,0 +1,74 @@ +{ + "hooks": { + "PostCompact": [ + { + "hooks": [ + { + "command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/plan-anvil-recovery.py\"", + "commandWindows": "py -3 -c \"import pathlib,runpy,subprocess;r=pathlib.Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip());runpy.run_path(str(r/'.codex/hooks/plan-anvil-recovery.py'),run_name='__main__')\"", + "statusMessage": "Restoring PlanAnvil recovery pointer", + "timeout": 30, + "type": "command" + } + ], + "matcher": "manual|auto" + } + ], + "PreCompact": [ + { + "hooks": [ + { + "command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/plan-anvil-compaction.py\"", + "commandWindows": "py -3 -c \"import pathlib,runpy,subprocess;r=pathlib.Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip());runpy.run_path(str(r/'.codex/hooks/plan-anvil-compaction.py'),run_name='__main__')\"", + "statusMessage": "Checking PlanAnvil recovery state", + "timeout": 30, + "type": "command" + } + ], + "matcher": "manual|auto" + } + ], + "PreToolUse": [ + { + "hooks": [ + { + "command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/plan-anvil-guard.py\"", + "commandWindows": "py -3 -c \"import pathlib,runpy,subprocess;r=pathlib.Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip());runpy.run_path(str(r/'.codex/hooks/plan-anvil-guard.py'),run_name='__main__')\"", + "statusMessage": "Checking PlanAnvil write and Git boundaries", + "timeout": 30, + "type": "command" + } + ], + "matcher": "^(Bash|apply_patch|Edit|Write|mcp__.*)$" + } + ], + "SessionStart": [ + { + "hooks": [ + { + "command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/plan-anvil-recovery.py\"", + "commandWindows": "py -3 -c \"import pathlib,runpy,subprocess;r=pathlib.Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip());runpy.run_path(str(r/'.codex/hooks/plan-anvil-recovery.py'),run_name='__main__')\"", + "statusMessage": "Loading PlanAnvil recovery pointer", + "timeout": 30, + "type": "command" + } + ], + "matcher": "startup|resume|clear|compact" + } + ], + "SubagentStart": [ + { + "hooks": [ + { + "command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/plan-anvil-agent-context.py\"", + "commandWindows": "py -3 -c \"import pathlib,runpy,subprocess;r=pathlib.Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip());runpy.run_path(str(r/'.codex/hooks/plan-anvil-agent-context.py'),run_name='__main__')\"", + "statusMessage": "Loading PlanAnvil role boundary", + "timeout": 30, + "type": "command" + } + ], + "matcher": "^plan_anvil_(profiler|reviewer)$" + } + ] + } +} diff --git a/.codex/hooks/plan-anvil-agent-context.py b/.codex/hooks/plan-anvil-agent-context.py new file mode 100644 index 0000000..114f76c --- /dev/null +++ b/.codex/hooks/plan-anvil-agent-context.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from plan_anvil_hooklib import active_run_for_event, context, read_event + + +def main() -> int: + event = read_event() + agent = str(event.get("agent_type") or "") + active = active_run_for_event(event) + pointer = "" + if active is not None: + pointer = f" Canonical run state is {active.run_root / 'state.json'}; verify it before work and do not treat conversation context as state." + if agent == "plan_anvil_profiler": + context( + "SubagentStart", + "Remain read-only. Read assigned instruction files completely, verify hashes, gather repository evidence, and return facts with repository-relative paths. Do not author or execute implementation." + pointer, + ) + elif agent == "plan_anvil_reviewer": + context( + "SubagentStart", + "Perform one fresh blind review from the supplied bundle only. Do not request planner reasoning, edit files, or execute implementation. Return a PASS/FAIL conclusion and concrete findings." + pointer, + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.codex/hooks/plan-anvil-compaction.py b/.codex/hooks/plan-anvil-compaction.py new file mode 100644 index 0000000..4bd25aa --- /dev/null +++ b/.codex/hooks/plan-anvil-compaction.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import json +import sys + +from plan_anvil_hooklib import active_run_for_event, read_event + + +def main() -> int: + event = read_event() + active = active_run_for_event(event) + if active is None: + return 0 + state = active.state + if not isinstance(state.get("revision"), int) or not isinstance(state.get("next_action"), dict): + json.dump( + { + "continue": False, + "stopReason": "PlanAnvil canonical state is invalid. Repair and persist state before compaction.", + }, + sys.stdout, + ) + sys.stdout.write("\n") + return 0 + if state.get("mode") == "PLAN_EXECUTION" and not state.get("last_checkpoint"): + json.dump( + { + "continue": False, + "stopReason": "Create and validate a durable PlanAnvil execution checkpoint before compaction.", + }, + sys.stdout, + ) + sys.stdout.write("\n") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.codex/hooks/plan-anvil-guard.py b/.codex/hooks/plan-anvil-guard.py new file mode 100644 index 0000000..80f5a6f --- /dev/null +++ b/.codex/hooks/plan-anvil-guard.py @@ -0,0 +1,134 @@ +from __future__ import annotations + +import re +from pathlib import Path +from typing import Any + +from plan_anvil_hooklib import ( + active_run_for_event, + allowed_control_path, + deny, + event_cwd, + flatten_strings, + is_within, + read_event, +) + +DANGEROUS_GIT = re.compile( + r"(?is)(?:^|[;&|]\s*)git(?:\s+-C\s+\S+)?\s+(?:stash|reset|clean|push|merge|rebase|cherry-pick|revert|checkout|switch)\b" +) +DANGEROUS_RUNTIME = re.compile( + r"(?is)(?:^|[;&|]\s*)(?:rm\s+-rf|del\s+/[sq]|remove-item\b[^\n]*-recurse|" + r"kubectl\s+(?:apply|delete|rollout|scale)|terraform\s+(?:apply|destroy)|" + r"systemctl\s+(?:start|stop|restart)|docker(?:\s+compose)?\s+(?:up|down|restart)|" + r"npm\s+publish|composer\s+publish)\b" +) +PATCH_PATH = re.compile(r"(?m)^\*\*\*\s+(?:Add|Update|Delete)\s+File:\s*(.+?)\s*$") +UNIFIED_PATH = re.compile(r"(?m)^\+\+\+\s+(?:b/)?([^\t\n]+)") +WRITE_WORDS = re.compile(r"(?i)\b(?:write|create|update|edit|patch|delete|remove|move|rename|replace)\b") +PATH_KEYS = {"path", "file_path", "file", "filename", "target", "destination", "output", "root"} + + +def _command(tool_input: Any) -> str: + if isinstance(tool_input, dict): + value = tool_input.get("command") + if isinstance(value, str): + return value + if isinstance(value, list): + return " ".join(str(item) for item in value) + return "" + + +def _patch_paths(command: str) -> list[str]: + paths = PATCH_PATH.findall(command) + paths.extend(path for path in UNIFIED_PATH.findall(command) if path != "/dev/null") + return [path.strip().strip('"\'') for path in paths] + + +def _mcp_paths(value: Any) -> list[str]: + found: list[str] = [] + if isinstance(value, dict): + for key, item in value.items(): + if key.lower() in PATH_KEYS and isinstance(item, str): + found.append(item) + else: + found.extend(_mcp_paths(item)) + elif isinstance(value, list): + for item in value: + found.extend(_mcp_paths(item)) + return found + + +def main() -> int: + event = read_event() + active = active_run_for_event(event) + if active is None or active.state.get("mode") != "PLAN_GENERATION": + return 0 + + tool = str(event.get("tool_name") or "") + tool_input = event.get("tool_input") + cwd = event_cwd(event) + + if tool == "Bash": + command = _command(tool_input) + if DANGEROUS_GIT.search(command): + deny("PlanAnvil generation forbids destructive or integrating Git commands. Use only the deterministic PlanAnvil scripts and planning-control branch.") + return 0 + if DANGEROUS_RUNTIME.search(command): + deny("PlanAnvil generates a plan only; deployment, migration, service switching, publication, and destructive cleanup are forbidden.") + return 0 + return 0 + + if tool in {"Edit", "Write"}: + if not is_within(active.worktree, cwd): + deny("PlanAnvil file edits are permitted only in the isolated planning worktree.") + return 0 + paths = _mcp_paths(tool_input) + if not paths: + deny("PlanAnvil could not prove the file-edit target is an allowed planning-control path.") + return 0 + for raw_path in paths: + candidate = Path(raw_path) + if candidate.is_absolute(): + try: + relative = candidate.resolve().relative_to(active.worktree.resolve()).as_posix() + except (OSError, ValueError): + deny("PlanAnvil file edits may not escape the planning worktree.") + return 0 + else: + relative = candidate.as_posix() + if ".." in Path(relative).parts or not allowed_control_path(relative): + deny("PlanAnvil file edits may modify only .pursue/** and .gitignore inside the planning worktree.") + return 0 + return 0 + + if tool == "apply_patch": + if not is_within(active.worktree, cwd): + deny("PlanAnvil file edits are permitted only in the isolated planning worktree.") + return 0 + command = _command(tool_input) + paths = _patch_paths(command) + if not paths: + deny("PlanAnvil could not prove the apply_patch target is an allowed planning-control path.") + return 0 + escaped = [path for path in paths if Path(path).is_absolute() or ".." in Path(path).parts] + forbidden = [path for path in paths if not allowed_control_path(path)] + if escaped or forbidden: + deny("PlanAnvil apply_patch may modify only .pursue/** and .gitignore inside the planning worktree.") + return 0 + + if tool.startswith("mcp__"): + text = " ".join(flatten_strings(tool_input)) + if not WRITE_WORDS.search(tool + " " + text): + return 0 + if not is_within(active.worktree, cwd): + deny("PlanAnvil write-capable MCP calls are permitted only in the isolated planning worktree.") + return 0 + paths = _mcp_paths(tool_input) + if not paths or any(Path(path).is_absolute() or ".." in Path(path).parts or not allowed_control_path(path) for path in paths): + deny("PlanAnvil write-capable MCP calls must prove every target is under .pursue/** or is .gitignore.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.codex/hooks/plan-anvil-recovery.py b/.codex/hooks/plan-anvil-recovery.py new file mode 100644 index 0000000..d85436e --- /dev/null +++ b/.codex/hooks/plan-anvil-recovery.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from plan_anvil_hooklib import active_run_for_event, context, read_event + + +def main() -> int: + event = read_event() + active = active_run_for_event(event) + if active is None: + return 0 + state = active.state + next_action = state.get("next_action") if isinstance(state.get("next_action"), dict) else {} + message = ( + f"Recover PlanAnvil from files: read {active.run_root / 'manifest.json'}, " + f"{active.run_root / 'state.json'}, ignored local-state.json, profiles, and the latest valid checkpoint; " + f"then reconcile Git before continuing. Current state is {state.get('status')}; " + f"next action is {next_action.get('type')} targeting {next_action.get('target')}." + ) + context(str(event.get("hook_event_name") or "SessionStart"), message) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.codex/hooks/plan_anvil_hooklib.py b/.codex/hooks/plan_anvil_hooklib.py new file mode 100644 index 0000000..281d484 --- /dev/null +++ b/.codex/hooks/plan_anvil_hooklib.py @@ -0,0 +1,153 @@ +from __future__ import annotations + +import json +import subprocess +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Iterable + +TERMINAL_STATES = { + "STOPPED", + "BLOCKED", + "FAILED", + "USER_ACCEPTED", + "USER_REJECTED", + "BLOCKED_BY_UNRESOLVED_FAILURE", +} + + +@dataclass(frozen=True) +class ActiveRun: + worktree: Path + run_root: Path + state: dict[str, Any] + + +def read_event() -> dict[str, Any]: + try: + value = json.load(sys.stdin) + except (json.JSONDecodeError, OSError): + return {} + return value if isinstance(value, dict) else {} + + +def git_root(cwd: str | None) -> Path | None: + path = Path(cwd or ".").resolve() + result = subprocess.run( + ["git", "-C", str(path), "rev-parse", "--show-toplevel"], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + check=False, + ) + if result.returncode != 0: + return None + return Path(result.stdout.strip()).resolve() + + +def linked_worktrees(repo: Path) -> list[Path]: + result = subprocess.run( + ["git", "-C", str(repo), "worktree", "list", "--porcelain"], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + check=False, + ) + if result.returncode != 0: + return [repo] + paths: list[Path] = [] + for line in result.stdout.splitlines(): + if line.startswith("worktree "): + paths.append(Path(line.removeprefix("worktree ")).resolve()) + return paths or [repo] + + +def _load_state(path: Path) -> dict[str, Any] | None: + try: + value = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError): + return None + return value if isinstance(value, dict) else None + + +def active_runs(repo: Path) -> list[ActiveRun]: + found: list[ActiveRun] = [] + for worktree in linked_worktrees(repo): + runs = worktree / ".pursue/runs" + if not runs.is_dir(): + continue + for state_path in runs.glob("*/state.json"): + state = _load_state(state_path) + if not state or state.get("status") in TERMINAL_STATES: + continue + if state.get("mode") not in {"PLAN_GENERATION", "PLAN_EXECUTION"}: + continue + found.append(ActiveRun(worktree, state_path.parent, state)) + return sorted(found, key=lambda item: item.run_root.name) + + +def active_run_for_event(event: dict[str, Any]) -> ActiveRun | None: + repo = git_root(event.get("cwd") if isinstance(event.get("cwd"), str) else None) + if repo is None: + return None + runs = active_runs(repo) + return runs[-1] if runs else None + + +def event_cwd(event: dict[str, Any]) -> Path: + raw = event.get("cwd") + return Path(raw).resolve() if isinstance(raw, str) and raw else Path.cwd().resolve() + + +def is_within(root: Path, candidate: Path) -> bool: + try: + candidate.resolve().relative_to(root.resolve()) + return True + except (OSError, ValueError): + return False + + +def allowed_control_path(path: str) -> bool: + normalized = path.replace("\\", "/") + while normalized.startswith("./"): + normalized = normalized[2:] + return normalized == ".gitignore" or normalized.startswith(".pursue/") + + +def deny(reason: str) -> None: + json.dump( + { + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": reason, + } + }, + sys.stdout, + ) + sys.stdout.write("\n") + + +def context(event_name: str, text: str) -> None: + json.dump( + { + "hookSpecificOutput": { + "hookEventName": event_name, + "additionalContext": text, + } + }, + sys.stdout, + ) + sys.stdout.write("\n") + + +def flatten_strings(value: Any) -> Iterable[str]: + if isinstance(value, str): + yield value + elif isinstance(value, dict): + for item in value.values(): + yield from flatten_strings(item) + elif isinstance(value, list): + for item in value: + yield from flatten_strings(item) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/workflows/materialize-plananvil.yml b/.github/workflows/materialize-plananvil.yml deleted file mode 100644 index 3f12df4..0000000 --- a/.github/workflows/materialize-plananvil.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Materialize PlanAnvil implementation - -on: - push: - branches: - - agent/implement-plananvil-skill - -permissions: - contents: write - -jobs: - materialize: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - ref: agent/implement-plananvil-skill - - name: Restore implementation archive - shell: bash - run: | - set -euo pipefail - cat \ - .bootstrap/part-00 \ - .bootstrap/fix-01-00 \ - .bootstrap/fix-01-01 \ - .bootstrap/fix-01-02 \ - .bootstrap/fix-01-03 \ - .bootstrap/fix-01-04 \ - .bootstrap/fix-01-05 \ - .bootstrap/part-02 \ - .bootstrap/part-03 \ - .bootstrap/fix-04-00 \ - .bootstrap/fix-04-01 \ - .bootstrap/part-05 \ - .bootstrap/part-06 \ - .bootstrap/part-07 \ - .bootstrap/part-08 \ - .bootstrap/fix-09-00 \ - .bootstrap/fix-09-01 \ - .bootstrap/fix-09-02 \ - .bootstrap/part-10 \ - .bootstrap/fix-11-00 \ - .bootstrap/fix-11-01 \ - .bootstrap/fix-11-02 \ - .bootstrap/part-12 \ - > /tmp/plananvil.tar.gz.b64 - test "$(sha256sum /tmp/plananvil.tar.gz.b64 | cut -d' ' -f1)" = "d5eb34452b058a1e7aa7d07446dfb1e1bd2477ce7efe21db180ec366f20e6d10" - base64 --decode /tmp/plananvil.tar.gz.b64 > /tmp/plananvil.tar.gz - test "$(sha256sum /tmp/plananvil.tar.gz | cut -d' ' -f1)" = "addffaecbf114a6a7fff2dff227b50fe66a47c14f1fb62df88113b49636e29d2" - tar -tzf /tmp/plananvil.tar.gz >/dev/null - tar -xzf /tmp/plananvil.tar.gz -C . - rm -rf .bootstrap .github/workflows/materialize-plananvil.yml - - name: Validate implementation - shell: bash - run: | - set -euo pipefail - python -m unittest discover -s .agents/skills/plan-anvil/tests -v - python -m compileall -q .agents/skills/plan-anvil .codex/hooks - find . -type d -name __pycache__ -prune -exec rm -rf {} + - git diff --check - - name: Commit materialized implementation - shell: bash - run: | - set -euo pipefail - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "Implement PlanAnvil skill" - git push origin HEAD:agent/implement-plananvil-skill diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8640847 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +__pycache__/ +*.py[cod] +.coverage +htmlcov/ +.pursue/SYSTEM_PROFILE.local.md +.pursue/runs/*/local-state.json +.pursue/runs/*/.generation-lock +.pursue/runs/*/.execution-lock diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..51bb431 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,31 @@ +# PlanAnvil repository instructions + +## Authority + +Read `docs/IMPLEMENTATION_SPEC.md` first. Resolve conflicts in this order: current official OpenAI Codex documentation, the implementation specification, architecture, artifact schemas, compliance record, capability baseline, examples, then README. + +## Product boundary + +PlanAnvil generates, validates, and commits planning artifacts. It never implements or executes the generated plan. Preserve source-worktree immutability and the generator/executor separation in every change. + +## Implementation rules + +- Keep `.agents/skills/plan-anvil/SKILL.md` concise; put detail in references, schemas, templates, and deterministic scripts. +- Core scripts require Python 3.11+ and the standard library only. +- Use argument arrays rather than shell execution inside core scripts. +- Keep canonical JSON deterministic, schema-validated, atomically written, and free of local absolute paths or secrets. +- Treat `.pursue/SYSTEM_PROFILE.local.md` and every `local-state.json` as ignored local state. +- Optional `.codex` agents and hooks are defense in depth. Never claim that hooks are a complete enforcement boundary. +- Do not weaken Git signing, repository hooks, sandboxing, approvals, path allowlists, or postcondition checks. +- Do not mark runtime capability tests as reproduced without a committed sanitized evidence package. + +## Validation + +Run from the repository root: + +```text +python -m unittest discover -s .agents/skills/plan-anvil/tests -v +python -m compileall -q .agents/skills/plan-anvil .codex/hooks +``` + +When changing schemas, lifecycle states, skill metadata, hooks, or agent configuration, also update the corresponding tests and compatibility documentation. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d0f025d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to PlanAnvil are documented here. + +## [0.1.0] - 2026-07-12 + +### Added + +- concise repository skill with explicit-only activation; +- deterministic Python 3.11 generator utilities; +- read-only source preflight and complete reversible Git capability probe; +- isolated planning branch and linked-worktree creation; +- repository and local profiling, freshness hashes, instruction mapping with critical-conflict blocking, and run scaffolding; +- durable Git-capability and lifecycle bootstrap evidence plus immutable goal analysis; +- versioned JSON Schemas, canonical state transitions, privacy checks, and atomic writes; +- plan, stage, diff, artifact, source-immutability, and traceability validation; +- immutable blind-review bundle, recording, and comparison workflow; +- planning-only commit gate and observable final stop; +- optional read-only Codex agents and defense-in-depth hooks; +- unit, integration, boundary, privacy, freshness, schema-traversal, and hook tests; +- golden contract examples and capability-evidence scaffolding. + +### Release status + +The deterministic core is implemented. Production readiness remains gated on reproduced Codex capability evidence defined in `docs/CODEX_CAPABILITY_BASELINE.md`. diff --git a/README.md b/README.md index 41a430b..bcc1f5d 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,83 @@ # PlanAnvil -A Codex-native skill for generating rigorous, test-driven, auditable software implementation plans. +PlanAnvil is a Codex-native repository skill that turns a software-engineering goal into a rigorous, test-driven, auditable implementation contract. -PlanAnvil **generates and validates a plan but never executes it**. Implementation happens only in a separate later Codex run using the execution contract written into `PLAN.md`. +It **generates and validates a plan but never executes it**. Product implementation happens only in a separate later Codex run using the execution prompt written into `PLAN.md`. -## Current status +## Status -The repository currently contains the authoritative implementation contract and compatibility baseline. The production skill and its deterministic test suite are not yet implemented. +The deterministic generator core, schemas, templates, tests, optional planning agents, and defense-in-depth hooks are implemented. -## Documentation +Release status is **candidate**, not production-ready. The Codex capability matrix in `docs/CODEX_CAPABILITY_BASELINE.md` remains a release gate until the required tests have committed sanitized `REPRODUCED` evidence for the current Codex version, model, operating systems, permission modes, and project-trust modes. -- [`docs/IMPLEMENTATION_SPEC.md`](docs/IMPLEMENTATION_SPEC.md) — authoritative product and implementation contract -- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — generator architecture and trust boundaries -- [`docs/ARTIFACT_SCHEMAS.md`](docs/ARTIFACT_SCHEMAS.md) — canonical state and artifact formats -- [`docs/OPENAI_COMPLIANCE.md`](docs/OPENAI_COMPLIANCE.md) — current Codex compatibility decisions -- [`docs/CODEX_CAPABILITY_BASELINE.md`](docs/CODEX_CAPABILITY_BASELINE.md) — reproducible capability-test requirements -- [`docs/EXAMPLES.md`](docs/EXAMPLES.md) — expected decisions and output shapes +## Use -## Core guarantees +The repository skill is discovered from: -A production PlanAnvil run must: +```text +.agents/skills/plan-anvil/ +``` -- require explicit `$plan-anvil` activation; -- start from a clean Git worktree; -- verify actual Git branch, worktree, index, and commit capabilities; -- create an isolated planning branch and worktree; -- leave the source worktree unchanged; -- profile the repository and map all applicable project instructions; -- generate stable stages, acceptance criteria, risks, tests, and rollback procedures; -- perform deterministic validation and immutable blind plan review; -- commit only planning artifacts; -- stop without implementing product code or tests. +Implicit invocation is disabled. Invoke it explicitly: -## Target installation +```text +$plan-anvil Generate a plan to add validation that rejects an empty display name. +``` -The canonical skill path is: +A run must: + +1. verify a clean source worktree; +2. run a real reversible Git ref, branch, worktree, index, and commit probe; +3. create an isolated planning branch and external linked worktree; +4. preserve schema-validated Git/lifecycle bootstrap evidence; +5. profile the repository, map complete applicable instructions, and record immutable goal analysis; +6. author stable plan, stage, risk, control, and traceability artifacts; +7. pass deterministic validation and immutable blind review; +8. commit planning artifacts only; +9. report the result and stop without implementing anything. + +The deterministic controller can also be inspected directly: ```text -.agents/skills/plan-anvil/ +python .agents/skills/plan-anvil/scripts/plan_anvil.py start \ + --source . \ + --goal "Add validation that rejects an empty display name." ``` -Implicit invocation is disabled. +The bootstrap controller stops after isolation, profiling, run scaffolding, and durable bootstrap evidence. The skill then performs evidence-based analysis and plan authoring before deterministic validation, blind review, and the planning-only commit gate. + +## Safety boundary + +PlanAnvil does not modify application code or tests, execute generated stages, deploy, migrate, restart services, switch a live environment, use destructive Git cleanup, or push or merge the base branch. + +The retained planning worktree is the durable control root. Machine-specific paths remain only in ignored local files; committed artifacts use repository-relative paths and Git identity. + +Project-scoped `.codex` agents and hooks are optional. Hooks require project trust and remain defense in depth; mandatory filesystem and Git postconditions apply in every hook mode. + +## Requirements + +- Python 3.11 or newer; +- Git 2.30 or newer; +- no elevated privileges; +- no third-party Python packages for the deterministic core; +- no network access for local validation. + +## Validation + +```text +python -m unittest discover -s .agents/skills/plan-anvil/tests -v +python -m compileall -q .agents/skills/plan-anvil .codex/hooks +``` + +## Documentation -Optional project-scoped Codex agents and hooks live under `.codex/`, but hooks remain defense in depth rather than the sole enforcement boundary. +- `docs/IMPLEMENTATION_SPEC.md` — authoritative product and implementation contract +- `docs/ARCHITECTURE.md` — architecture and trust boundaries +- `docs/ARTIFACT_SCHEMAS.md` — canonical state and artifact formats +- `docs/OPENAI_COMPLIANCE.md` — Codex compatibility decisions +- `docs/CODEX_CAPABILITY_BASELINE.md` — reproducible capability release gate +- `docs/EXAMPLES.md` — expected decisions and output shapes +- `capabilities/README.md` — evidence-package workflow ## Author diff --git a/capabilities/C01/README.md b/capabilities/C01/README.md new file mode 100644 index 0000000..e00e844 --- /dev/null +++ b/capabilities/C01/README.md @@ -0,0 +1,8 @@ +# C01 — Capability evidence + +- Expected behavior: Repository skills are discovered from .agents/skills. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C02/README.md b/capabilities/C02/README.md new file mode 100644 index 0000000..af19922 --- /dev/null +++ b/capabilities/C02/README.md @@ -0,0 +1,8 @@ +# C02 — Capability evidence + +- Expected behavior: allow_implicit_invocation false disables implicit invocation. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C03/README.md b/capabilities/C03/README.md new file mode 100644 index 0000000..da64c39 --- /dev/null +++ b/capabilities/C03/README.md @@ -0,0 +1,8 @@ +# C03 — Capability evidence + +- Expected behavior: agents.max_depth 1 permits direct children and prevents deeper descendants. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C04/README.md b/capabilities/C04/README.md new file mode 100644 index 0000000..87a6c7d --- /dev/null +++ b/capabilities/C04/README.md @@ -0,0 +1,8 @@ +# C04 — Capability evidence + +- Expected behavior: Nested agents are available when configured depth permits them. +- Source: `DOCUMENTED` +- Release-gating: `conditional` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C05/README.md b/capabilities/C05/README.md new file mode 100644 index 0000000..2e0edfc --- /dev/null +++ b/capabilities/C05/README.md @@ -0,0 +1,8 @@ +# C05 — Capability evidence + +- Expected behavior: Planning-agent handoffs use explicit files and hashes. +- Source: `CONTRACT_DEFINED` +- Release-gating: `conditional` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C06/README.md b/capabilities/C06/README.md new file mode 100644 index 0000000..eb5df6e --- /dev/null +++ b/capabilities/C06/README.md @@ -0,0 +1,8 @@ +# C06 — Capability evidence + +- Expected behavior: PreToolUse covers supported calls but not every equivalent path. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C07/README.md b/capabilities/C07/README.md new file mode 100644 index 0000000..f3f89a1 --- /dev/null +++ b/capabilities/C07/README.md @@ -0,0 +1,8 @@ +# C07 — Capability evidence + +- Expected behavior: The Git guard rejects the configured unsafe-command corpus. +- Source: `CONTRACT_DEFINED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C08/README.md b/capabilities/C08/README.md new file mode 100644 index 0000000..abae5ed --- /dev/null +++ b/capabilities/C08/README.md @@ -0,0 +1,8 @@ +# C08 — Capability evidence + +- Expected behavior: PreCompact can stop compaction. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C09/README.md b/capabilities/C09/README.md new file mode 100644 index 0000000..3dacf2e --- /dev/null +++ b/capabilities/C09/README.md @@ -0,0 +1,8 @@ +# C09 — Capability evidence + +- Expected behavior: Compaction is allowed after checkpoint creation without a permanent loop. +- Source: `CONTRACT_DEFINED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C10/README.md b/capabilities/C10/README.md new file mode 100644 index 0000000..47eea9a --- /dev/null +++ b/capabilities/C10/README.md @@ -0,0 +1,8 @@ +# C10 — Capability evidence + +- Expected behavior: PostCompact and SessionStart can provide recovery context. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C11/README.md b/capabilities/C11/README.md new file mode 100644 index 0000000..738c931 --- /dev/null +++ b/capabilities/C11/README.md @@ -0,0 +1,8 @@ +# C11 — Capability evidence + +- Expected behavior: Project instructions follow documented directory scope and precedence. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C12/README.md b/capabilities/C12/README.md new file mode 100644 index 0000000..29a1141 --- /dev/null +++ b/capabilities/C12/README.md @@ -0,0 +1,8 @@ +# C12 — Capability evidence + +- Expected behavior: project_doc_max_bytes may truncate automatic instruction loading. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C13/README.md b/capabilities/C13/README.md new file mode 100644 index 0000000..961e8db --- /dev/null +++ b/capabilities/C13/README.md @@ -0,0 +1,8 @@ +# C13 — Capability evidence + +- Expected behavior: SubagentStart can add context but is not a startup blocker. +- Source: `DOCUMENTED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C14/README.md b/capabilities/C14/README.md new file mode 100644 index 0000000..42a5676 --- /dev/null +++ b/capabilities/C14/README.md @@ -0,0 +1,8 @@ +# C14 — Capability evidence + +- Expected behavior: Planning isolation preserves source branch, SHA, index, and files. +- Source: `CONTRACT_DEFINED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C15/README.md b/capabilities/C15/README.md new file mode 100644 index 0000000..1ca062c --- /dev/null +++ b/capabilities/C15/README.md @@ -0,0 +1,8 @@ +# C15 — Capability evidence + +- Expected behavior: Blind review is immutable and detects seeded contract defects. +- Source: `CONTRACT_DEFINED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/C16/README.md b/capabilities/C16/README.md new file mode 100644 index 0000000..430a1d6 --- /dev/null +++ b/capabilities/C16/README.md @@ -0,0 +1,8 @@ +# C16 — Capability evidence + +- Expected behavior: Git probe reports refs, branches, worktrees, index, commits, and cleanup. +- Source: `CONTRACT_DEFINED` +- Release-gating: `yes` +- Current result: `NOT_RUN` + +Do not change the result to `REPRODUCED` until this directory contains the complete sanitized package defined in `capabilities/README.md`. Record the exact Codex version, model slug, operating system, permission mode, project trust, fixture commit, setup, cleanup, expected result, actual sanitized result, evaluation, and hashes. diff --git a/capabilities/README.md b/capabilities/README.md new file mode 100644 index 0000000..5469389 --- /dev/null +++ b/capabilities/README.md @@ -0,0 +1,22 @@ +# Codex capability evidence + +This directory stores sanitized, reproducible evidence for the release gate in `docs/CODEX_CAPABILITY_BASELINE.md`. + +A capability is not `REPRODUCED` until its directory contains: + +```text +CXX/ +├── README.md +├── fixture/ +├── prompt.txt +├── config/ +├── run-command.txt +├── expected.json +├── actual.sanitized.json +├── evaluation.json +└── hashes.json +``` + +Record the exact Codex version, model slug, operating system, permission mode, project-trust mode, fixture commit, setup, cleanup, expected behavior, sanitized actual behavior, and evaluation. Remove usernames, home directories, private repository URLs, credentials, session identifiers, transcripts, unrelated Git databases, and proprietary source. + +The repository ships deterministic contract tests and evidence scaffolding, but does not label live Codex behavior as reproduced without these packages. diff --git a/capabilities/index.json b/capabilities/index.json new file mode 100644 index 0000000..ea58423 --- /dev/null +++ b/capabilities/index.json @@ -0,0 +1,135 @@ +{ + "baseline_version": "2.1", + "capabilities": [ + { + "evidence_directory": "capabilities/C01", + "expected_behavior": "Repository skills are discovered from .agents/skills", + "id": "C01", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C02", + "expected_behavior": "allow_implicit_invocation false disables implicit invocation", + "id": "C02", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C03", + "expected_behavior": "agents.max_depth 1 permits direct children and prevents deeper descendants", + "id": "C03", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C04", + "expected_behavior": "Nested agents are available when configured depth permits them", + "id": "C04", + "required": false, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C05", + "expected_behavior": "Planning-agent handoffs use explicit files and hashes", + "id": "C05", + "required": false, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + }, + { + "evidence_directory": "capabilities/C06", + "expected_behavior": "PreToolUse covers supported calls but not every equivalent path", + "id": "C06", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C07", + "expected_behavior": "The Git guard rejects the configured unsafe-command corpus", + "id": "C07", + "required": true, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + }, + { + "evidence_directory": "capabilities/C08", + "expected_behavior": "PreCompact can stop compaction", + "id": "C08", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C09", + "expected_behavior": "Compaction is allowed after checkpoint creation without a permanent loop", + "id": "C09", + "required": true, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + }, + { + "evidence_directory": "capabilities/C10", + "expected_behavior": "PostCompact and SessionStart can provide recovery context", + "id": "C10", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C11", + "expected_behavior": "Project instructions follow documented directory scope and precedence", + "id": "C11", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C12", + "expected_behavior": "project_doc_max_bytes may truncate automatic instruction loading", + "id": "C12", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C13", + "expected_behavior": "SubagentStart can add context but is not a startup blocker", + "id": "C13", + "required": true, + "result": "NOT_RUN", + "source": "DOCUMENTED" + }, + { + "evidence_directory": "capabilities/C14", + "expected_behavior": "Planning isolation preserves source branch, SHA, index, and files", + "id": "C14", + "required": true, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + }, + { + "evidence_directory": "capabilities/C15", + "expected_behavior": "Blind review is immutable and detects seeded contract defects", + "id": "C15", + "required": true, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + }, + { + "evidence_directory": "capabilities/C16", + "expected_behavior": "Git probe reports refs, branches, worktrees, index, commits, and cleanup", + "id": "C16", + "required": true, + "result": "NOT_RUN", + "source": "CONTRACT_DEFINED" + } + ], + "generated_at": "2026-07-12", + "release_gate": "Required capabilities must have committed sanitized REPRODUCED evidence before production readiness." +} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..e2b7b4e --- /dev/null +++ b/examples/README.md @@ -0,0 +1,10 @@ +# Golden contract examples + +These sanitized fixtures exercise the expected PlanAnvil decisions and output shapes. They contain planning contracts and evidence only; no product implementation is included. + +- `small-change` — one low-risk behavior stage and `PLAN_READY`. +- `stateful-change` — five backward-compatible migration stages and `PLAN_READY`. +- `blocked-plan` — a destructive request stopped by critical policy unknowns. +- `git-write-restricted` — Git metadata restriction stops the run before profiles or plans are written. + +The ready examples use schema version `1.1.0`, repository-relative paths, immutable review sidecars, comparison results, and sanitization reports. Live Codex capability evidence belongs under `capabilities/`, not here. diff --git a/examples/blocked-plan/expected.json b/examples/blocked-plan/expected.json new file mode 100644 index 0000000..a8cb6ab --- /dev/null +++ b/examples/blocked-plan/expected.json @@ -0,0 +1,10 @@ +{ + "critical_unknowns": [ + "authoritative deletion scope", + "legal retention", + "irreversibility approval", + "recovery policy" + ], + "implementation_executed": false, + "status": "BLOCKED_BY_CRITICAL_UNKNOWN" +} diff --git a/examples/blocked-plan/fixture.md b/examples/blocked-plan/fixture.md new file mode 100644 index 0000000..5cf72be --- /dev/null +++ b/examples/blocked-plan/fixture.md @@ -0,0 +1,3 @@ +# Fixture + +Retention, backup, downstream-consumer, and recovery policies are intentionally absent. diff --git a/examples/blocked-plan/request.md b/examples/blocked-plan/request.md new file mode 100644 index 0000000..1ac8122 --- /dev/null +++ b/examples/blocked-plan/request.md @@ -0,0 +1,3 @@ +# Request + +Change account deletion so it permanently removes all user data. diff --git a/examples/blocked-plan/run/PARTIAL_PLAN.md b/examples/blocked-plan/run/PARTIAL_PLAN.md new file mode 100644 index 0000000..022b4b6 --- /dev/null +++ b/examples/blocked-plan/run/PARTIAL_PLAN.md @@ -0,0 +1,3 @@ +# Partial plan + +Status: `BLOCKED_BY_CRITICAL_UNKNOWN`. No implementation stages are approved. diff --git a/examples/blocked-plan/run/SYSTEM_PROFILE.md b/examples/blocked-plan/run/SYSTEM_PROFILE.md new file mode 100644 index 0000000..4850ddf --- /dev/null +++ b/examples/blocked-plan/run/SYSTEM_PROFILE.md @@ -0,0 +1,38 @@ +# PlanAnvil Repository Profile + +- Profile status: `VALID` +- Generated at: `2026-07-12T18:00:00Z` +- Repository fingerprint: `sha256:1111111111111111111111111111111111111111111111111111111111111111` +- Evidence base SHA: `dedb6ab6843bf06d3ac7899aaf37923896915ee7` + +## Repository structure and architecture + +Small fixture repository. + +## Languages, runtimes, and dependency managers + +Python with standard-library tests. + +## Build, test, lint, and static-analysis commands + +Run the fixture test command recorded by the example. + +## Git conventions and quality gates + +One coherent stage commit and a clean worktree. + +## Project instruction map + +The root instruction file applies. + +## Deployment, state, and rollback rules + +No deployment for this fixture. Revert the stage commit on failure. + +## Risk and activation policy + +Explicit activation only. + +## Evidence and freshness + +Evidence is pinned to the fixture base SHA. diff --git a/examples/blocked-plan/run/compliance.json b/examples/blocked-plan/run/compliance.json new file mode 100644 index 0000000..1c03d00 --- /dev/null +++ b/examples/blocked-plan/run/compliance.json @@ -0,0 +1,55 @@ +{ + "capabilities": [ + { + "evidence": [], + "id": "CAP-SKILL-DISCOVERY", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [], + "id": "CAP-EXPLICIT-ACTIVATION", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [ + "examples/blocked-plan/run/evidence/git-capability.json" + ], + "id": "CAP-GIT-PROBE", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [ + "evidence/instruction-map.json" + ], + "id": "CAP-INSTRUCTION-MAP", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [], + "id": "CAP-BLIND-REVIEW", + "required": true, + "status": "UNKNOWN" + } + ], + "codex": { + "hook_mode": "HOOKS_DISABLED", + "model": "fixture", + "permission_mode": "fixture", + "project_trust": "TRUSTED", + "version": "fixture" + }, + "schema_version": "1.1.0", + "unsupported": [ + "Generator execution of implementation stages", + "Automatic base-branch push or merge", + "Hooks as the sole enforcement boundary" + ], + "verified_at": "2026-07-12T18:00:00Z", + "warnings": [ + "Golden fixture; not live Codex capability evidence." + ] +} diff --git a/examples/blocked-plan/run/evidence/analysis.json b/examples/blocked-plan/run/evidence/analysis.json new file mode 100644 index 0000000..3ae89d2 --- /dev/null +++ b/examples/blocked-plan/run/evidence/analysis.json @@ -0,0 +1,22 @@ +{ + "affected_paths": [ + "src/deletion.py" + ], + "assumptions": [], + "classification": "STATEFUL", + "created_at": "2026-07-12T18:00:00Z", + "evidence": [ + "fixture.md" + ], + "goal_hash": "sha256:63e00df6f93674d64c46ac14032b1adf0467ee261bbccfe082a48c49af1df5f4", + "markdown_hash": "sha256:1d58a12c3ba490d9eed213308a6a12f64880ab0ab3d9928451449519a64a16f0", + "risk": "HIGH", + "schema_version": "1.1.0", + "unknowns": [ + { + "critical": true, + "text": "Authoritative deletion and legal-retention scope is unknown.", + "verification": "Obtain the approved policy and irreversible-action owner." + } + ] +} diff --git a/examples/blocked-plan/run/evidence/analysis.md b/examples/blocked-plan/run/evidence/analysis.md new file mode 100644 index 0000000..da82e81 --- /dev/null +++ b/examples/blocked-plan/run/evidence/analysis.md @@ -0,0 +1,3 @@ +# Goal analysis + +The request is destructive and policy-dependent. Safe acceptance criteria and rollback cannot be defined from repository evidence. diff --git a/examples/blocked-plan/run/evidence/git-capability.json b/examples/blocked-plan/run/evidence/git-capability.json new file mode 100644 index 0000000..743030c --- /dev/null +++ b/examples/blocked-plan/run/evidence/git-capability.json @@ -0,0 +1,59 @@ +{ + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "cleanup": { + "errors": [], + "result": "PASS" + }, + "result": "GIT_READY", + "schema_version": "1.1.0", + "source_snapshot": { + "branch": "main", + "head": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "index_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333", + "status_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "steps": [ + { + "id": "create_temporary_ref", + "result": "PASS" + }, + { + "id": "verify_temporary_ref", + "result": "PASS" + }, + { + "id": "delete_temporary_ref", + "result": "PASS" + }, + { + "id": "create_probe_branch", + "result": "PASS" + }, + { + "id": "create_probe_worktree", + "result": "PASS" + }, + { + "id": "checkout_probe_worktree", + "result": "PASS" + }, + { + "id": "create_probe_file", + "result": "PASS" + }, + { + "id": "update_probe_index", + "result": "PASS" + }, + { + "id": "create_probe_commit", + "result": "PASS" + }, + { + "id": "verify_probe_clean", + "result": "PASS" + } + ], + "verified_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/blocked-plan/run/evidence/lifecycle.json b/examples/blocked-plan/run/evidence/lifecycle.json new file mode 100644 index 0000000..0a3d6a1 --- /dev/null +++ b/examples/blocked-plan/run/evidence/lifecycle.json @@ -0,0 +1,38 @@ +{ + "events": [ + { + "evidence": [ + "examples/blocked-plan/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 1, + "state": "SOURCE_PREFLIGHT_PASSED" + }, + { + "evidence": [ + "examples/blocked-plan/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 2, + "state": "GIT_READY" + }, + { + "evidence": [ + "examples/blocked-plan/run/manifest.json" + ], + "result": "PASS", + "sequence": 3, + "state": "PLANNING_WORKTREE_READY" + }, + { + "evidence": [ + "examples/blocked-plan/run/SYSTEM_PROFILE.md" + ], + "result": "PASS", + "sequence": 4, + "state": "PROFILE_READY" + } + ], + "recorded_at": "2026-07-12T18:00:00Z", + "schema_version": "1.1.0" +} diff --git a/examples/blocked-plan/run/evidence/original-goal.md b/examples/blocked-plan/run/evidence/original-goal.md new file mode 100644 index 0000000..1e73ff6 --- /dev/null +++ b/examples/blocked-plan/run/evidence/original-goal.md @@ -0,0 +1,3 @@ +# Original goal + +Change account deletion so it permanently removes all user data. diff --git a/examples/blocked-plan/run/manifest.json b/examples/blocked-plan/run/manifest.json new file mode 100644 index 0000000..c1ffef2 --- /dev/null +++ b/examples/blocked-plan/run/manifest.json @@ -0,0 +1,27 @@ +{ + "contract_versions": { + "artifact_schema": "1.1.0", + "implementation_spec": "2.1", + "plan_contract": "1.0.0" + }, + "created_at": "2026-07-12T18:00:00Z", + "generator_version": "0.1.0", + "paths": { + "compliance": "compliance.json", + "local_state": "local-state.json", + "plan": "PLAN.md", + "repository_profile": "SYSTEM_PROFILE.md", + "run_root": "examples/blocked-plan/run", + "state": "state.json", + "traceability": "traceability.json" + }, + "plan_id": "PG-20260712-180200-C3D4", + "repository": { + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "fingerprint": "sha256:1111111111111111111111111111111111111111111111111111111111111111", + "planning_branch": "pursue/plan/PG-20260712-180200-C3D4/permanent-deletion" + }, + "run_id": "20260712T180200Z_PG-20260712-180200-C3D4_permanent-deletion", + "schema_version": "1.1.0" +} diff --git a/examples/blocked-plan/run/state.json b/examples/blocked-plan/run/state.json new file mode 100644 index 0000000..3b1bdce --- /dev/null +++ b/examples/blocked-plan/run/state.json @@ -0,0 +1,18 @@ +{ + "artifact_hashes": {}, + "current_phase": "REPORT_AND_STOP", + "current_stage": null, + "last_checkpoint": null, + "mode": "PLAN_GENERATION", + "next_action": { + "target": null, + "type": "NONE" + }, + "open_blockers": [ + "BLOCKED_BY_CRITICAL_UNKNOWN" + ], + "revision": 12, + "schema_version": "1.1.0", + "status": "BLOCKED", + "updated_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/blocked-plan/run/traceability.json b/examples/blocked-plan/run/traceability.json new file mode 100644 index 0000000..e2d0827 --- /dev/null +++ b/examples/blocked-plan/run/traceability.json @@ -0,0 +1,7 @@ +{ + "controls": [], + "criteria": [], + "gaps": [], + "requirements": [], + "schema_version": "1.1.0" +} diff --git a/examples/blocked-plan/sanitization.json b/examples/blocked-plan/sanitization.json new file mode 100644 index 0000000..1868d60 --- /dev/null +++ b/examples/blocked-plan/sanitization.json @@ -0,0 +1,6 @@ +{ + "absolute_paths": 0, + "local_state_committed": false, + "result": "PASS", + "secrets": 0 +} diff --git a/examples/git-write-restricted/expected.json b/examples/git-write-restricted/expected.json new file mode 100644 index 0000000..828c9cb --- /dev/null +++ b/examples/git-write-restricted/expected.json @@ -0,0 +1,7 @@ +{ + "git_capability": "GIT_WRITE_RESTRICTED", + "implementation_executed": false, + "plan_created": false, + "profile_created": false, + "status": "BLOCKED_BY_GIT_PERMISSIONS" +} diff --git a/examples/git-write-restricted/fixture.md b/examples/git-write-restricted/fixture.md new file mode 100644 index 0000000..28a65a4 --- /dev/null +++ b/examples/git-write-restricted/fixture.md @@ -0,0 +1,3 @@ +# Fixture + +The worktree is clean and normal files are writable, but Git ref and linked-worktree creation are denied. diff --git a/examples/git-write-restricted/git-capability.json b/examples/git-write-restricted/git-capability.json new file mode 100644 index 0000000..c4b4e59 --- /dev/null +++ b/examples/git-write-restricted/git-capability.json @@ -0,0 +1,8 @@ +{ + "artifacts_written": false, + "failed_operation": "temporary-ref-create", + "ok": false, + "plan_status": "BLOCKED_BY_GIT_PERMISSIONS", + "result": "GIT_WRITE_RESTRICTED", + "source_unchanged": true +} diff --git a/examples/git-write-restricted/preflight.json b/examples/git-write-restricted/preflight.json new file mode 100644 index 0000000..2dd054e --- /dev/null +++ b/examples/git-write-restricted/preflight.json @@ -0,0 +1,5 @@ +{ + "ok": true, + "result": "SOURCE_PREFLIGHT_PASSED", + "source_unchanged": true +} diff --git a/examples/git-write-restricted/request.md b/examples/git-write-restricted/request.md new file mode 100644 index 0000000..870aa9c --- /dev/null +++ b/examples/git-write-restricted/request.md @@ -0,0 +1,3 @@ +# Request + +Generate a plan for a safe feature change. diff --git a/examples/git-write-restricted/sanitization.json b/examples/git-write-restricted/sanitization.json new file mode 100644 index 0000000..1868d60 --- /dev/null +++ b/examples/git-write-restricted/sanitization.json @@ -0,0 +1,6 @@ +{ + "absolute_paths": 0, + "local_state_committed": false, + "result": "PASS", + "secrets": 0 +} diff --git a/examples/small-change/expected.json b/examples/small-change/expected.json new file mode 100644 index 0000000..2bec825 --- /dev/null +++ b/examples/small-change/expected.json @@ -0,0 +1,8 @@ +{ + "classification": "ISOLATED", + "implementation_executed": false, + "stage_ids": [ + "STAGE-01" + ], + "status": "PLAN_READY" +} diff --git a/examples/small-change/fixture.md b/examples/small-change/fixture.md new file mode 100644 index 0000000..f7e6583 --- /dev/null +++ b/examples/small-change/fixture.md @@ -0,0 +1,3 @@ +# Fixture + +Golden contract fixture pinned to `dedb6ab6843bf06d3ac7899aaf37923896915ee7`. No product implementation is included. diff --git a/examples/small-change/request.md b/examples/small-change/request.md new file mode 100644 index 0000000..8866455 --- /dev/null +++ b/examples/small-change/request.md @@ -0,0 +1,3 @@ +# Request + +Add validation that rejects an empty display name. diff --git a/examples/small-change/run/PLAN.md b/examples/small-change/run/PLAN.md new file mode 100644 index 0000000..825bd62 --- /dev/null +++ b/examples/small-change/run/PLAN.md @@ -0,0 +1,88 @@ +# Implementation Plan: Display Name + +## Identity + +- Plan ID: `PG-20260712-180000-A1B2` +- Run ID: `20260712T180000Z_PG-20260712-180000-A1B2_display-name` +- Contract: PlanAnvil 2.1 +- Artifact schema: 1.1.0 +- Base branch: `main` +- Base SHA: `dedb6ab6843bf06d3ac7899aaf37923896915ee7` +- Planning branch: `pursue/plan/PG-20260712-180000-A1B2/display-name` + +## Original goal + +Add validation that rejects an empty display name. + +## Outcome and definition of done + +Every acceptance criterion is proven and the later executor can stop or roll back safely. + +## Generator stop boundary + +PlanAnvil generates and validates this contract only. It does not modify product code or tests and does not execute a stage. + +## Separate execution-run prompt + +In a separate Codex run, load this plan and canonical state, reconcile Git and the latest checkpoint, then execute only the next approved stage. + +## Scope + +The stage briefs define the complete approved scope. + +## Exclusions + +Automatic base-branch integration, unrelated refactors, and unapproved destructive work are excluded. + +## Assumptions, unknowns, and evidence + +The analysis files contain verified assumptions and no critical unknowns. + +## Applicable instructions + +Read and verify the complete hashed instruction map before any later write. + +## System and change analysis + +Classification: `ISOLATED`. Component and state boundaries are defined by the stage briefs. + +## Dependencies and classification + +Dependencies are explicit and no stage may be skipped. + +## Stable stage index + +- `STAGE-01` — Reject empty display names while preserving valid input. + +## Traceability + +REQ-01-01 → STAGE-01 → AC-01-01. + +## Testing and independent verification + +Behavior stages require GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Git, integration, and control-root rules + +Product changes occur only in task or integration worktrees. The planning worktree remains the control root. One modifier acts at a time. + +## Production verification, switching, and approvals + +Any live switch, irreversible action, or base-branch integration requires explicit user approval. + +## Rollback and recovery + +Each stage has a rollback boundary. Resume only after canonical files and Git reconcile. + +## Resume and reconciliation + +Read manifest, state, local state, profiles, analysis, instruction map, latest checkpoint, and Git state. Stop on mismatch. + +## Status and next action + +- Status: `PLAN_READY` +- Next action: `Start a separate execution run for STAGE-01.` + +## Final report requirements + +Report tests, verification, commits, remaining risks, and approvals. No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md. diff --git a/examples/small-change/run/SYSTEM_PROFILE.md b/examples/small-change/run/SYSTEM_PROFILE.md new file mode 100644 index 0000000..4850ddf --- /dev/null +++ b/examples/small-change/run/SYSTEM_PROFILE.md @@ -0,0 +1,38 @@ +# PlanAnvil Repository Profile + +- Profile status: `VALID` +- Generated at: `2026-07-12T18:00:00Z` +- Repository fingerprint: `sha256:1111111111111111111111111111111111111111111111111111111111111111` +- Evidence base SHA: `dedb6ab6843bf06d3ac7899aaf37923896915ee7` + +## Repository structure and architecture + +Small fixture repository. + +## Languages, runtimes, and dependency managers + +Python with standard-library tests. + +## Build, test, lint, and static-analysis commands + +Run the fixture test command recorded by the example. + +## Git conventions and quality gates + +One coherent stage commit and a clean worktree. + +## Project instruction map + +The root instruction file applies. + +## Deployment, state, and rollback rules + +No deployment for this fixture. Revert the stage commit on failure. + +## Risk and activation policy + +Explicit activation only. + +## Evidence and freshness + +Evidence is pinned to the fixture base SHA. diff --git a/examples/small-change/run/compliance.json b/examples/small-change/run/compliance.json new file mode 100644 index 0000000..a61f04c --- /dev/null +++ b/examples/small-change/run/compliance.json @@ -0,0 +1,58 @@ +{ + "capabilities": [ + { + "evidence": [], + "id": "CAP-SKILL-DISCOVERY", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [], + "id": "CAP-EXPLICIT-ACTIVATION", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [ + "examples/small-change/run/evidence/git-capability.json" + ], + "id": "CAP-GIT-PROBE", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [ + "evidence/instruction-map.json" + ], + "id": "CAP-INSTRUCTION-MAP", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [ + "reports/plan-review/blind-review.md", + "reports/plan-review/blind-review.json" + ], + "id": "CAP-BLIND-REVIEW", + "required": true, + "status": "VERIFIED" + } + ], + "codex": { + "hook_mode": "HOOKS_DISABLED", + "model": "fixture", + "permission_mode": "fixture", + "project_trust": "TRUSTED", + "version": "fixture" + }, + "schema_version": "1.1.0", + "unsupported": [ + "Generator execution of implementation stages", + "Automatic base-branch push or merge", + "Hooks as the sole enforcement boundary" + ], + "verified_at": "2026-07-12T18:00:00Z", + "warnings": [ + "Golden fixture; not live Codex capability evidence." + ] +} diff --git a/examples/small-change/run/evidence/analysis.json b/examples/small-change/run/evidence/analysis.json new file mode 100644 index 0000000..34043d7 --- /dev/null +++ b/examples/small-change/run/evidence/analysis.json @@ -0,0 +1,25 @@ +{ + "affected_paths": [ + "src/validator.py", + "tests/test_validator.py" + ], + "assumptions": [ + { + "confidence": "VERIFIED", + "evidence": [ + "fixture.md" + ], + "text": "Fixture evidence defines the planning boundary." + } + ], + "classification": "ISOLATED", + "created_at": "2026-07-12T18:00:00Z", + "evidence": [ + "fixture.md" + ], + "goal_hash": "sha256:9e22a49c76c563785626ee642c72cb015b7cdc5cb53aab98af6f4c30799f9115", + "markdown_hash": "sha256:9a68c8bae7cc1836110d5def873c17264c851494ab196aadffb64ca5c7fcebfd", + "risk": "LOW", + "schema_version": "1.1.0", + "unknowns": [] +} diff --git a/examples/small-change/run/evidence/analysis.md b/examples/small-change/run/evidence/analysis.md new file mode 100644 index 0000000..0c315e8 --- /dev/null +++ b/examples/small-change/run/evidence/analysis.md @@ -0,0 +1,29 @@ +# Goal analysis + +## Requested outcome + +Add validation that rejects an empty display name. + +## Repository evidence + +The fixture records the affected components and quality gates. + +## Change classification and risk + +ISOLATED. + +## Affected paths and boundaries + +Only stage allowlists may be modified by the later executor. + +## Assumptions + +The fixture evidence is authoritative for this example. + +## Unknowns and verification + +No critical unknown remains. + +## Recommended stage boundaries + +Stages are split by independent acceptance and rollback boundaries. diff --git a/examples/small-change/run/evidence/git-capability.json b/examples/small-change/run/evidence/git-capability.json new file mode 100644 index 0000000..743030c --- /dev/null +++ b/examples/small-change/run/evidence/git-capability.json @@ -0,0 +1,59 @@ +{ + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "cleanup": { + "errors": [], + "result": "PASS" + }, + "result": "GIT_READY", + "schema_version": "1.1.0", + "source_snapshot": { + "branch": "main", + "head": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "index_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333", + "status_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "steps": [ + { + "id": "create_temporary_ref", + "result": "PASS" + }, + { + "id": "verify_temporary_ref", + "result": "PASS" + }, + { + "id": "delete_temporary_ref", + "result": "PASS" + }, + { + "id": "create_probe_branch", + "result": "PASS" + }, + { + "id": "create_probe_worktree", + "result": "PASS" + }, + { + "id": "checkout_probe_worktree", + "result": "PASS" + }, + { + "id": "create_probe_file", + "result": "PASS" + }, + { + "id": "update_probe_index", + "result": "PASS" + }, + { + "id": "create_probe_commit", + "result": "PASS" + }, + { + "id": "verify_probe_clean", + "result": "PASS" + } + ], + "verified_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/small-change/run/evidence/instruction-map.json b/examples/small-change/run/evidence/instruction-map.json new file mode 100644 index 0000000..fdf9b0a --- /dev/null +++ b/examples/small-change/run/evidence/instruction-map.json @@ -0,0 +1,27 @@ +{ + "affected_paths": [ + "src/validator.py", + "tests/test_validator.py" + ], + "automatic_byte_limit": 32768, + "conflicts": [], + "fallback_filenames": [], + "files": [ + { + "affected_paths": [ + "src/validator.py", + "tests/test_validator.py" + ], + "bytes": 120, + "full_read": true, + "path": "AGENTS.md", + "precedence": 0, + "safety_critical_rules": [], + "scope": ".", + "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222", + "truncation_risk": false + } + ], + "generated_at": "2026-07-12T18:00:00Z", + "schema_version": "1.1.0" +} diff --git a/examples/small-change/run/evidence/lifecycle.json b/examples/small-change/run/evidence/lifecycle.json new file mode 100644 index 0000000..1914307 --- /dev/null +++ b/examples/small-change/run/evidence/lifecycle.json @@ -0,0 +1,38 @@ +{ + "events": [ + { + "evidence": [ + "examples/small-change/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 1, + "state": "SOURCE_PREFLIGHT_PASSED" + }, + { + "evidence": [ + "examples/small-change/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 2, + "state": "GIT_READY" + }, + { + "evidence": [ + "examples/small-change/run/manifest.json" + ], + "result": "PASS", + "sequence": 3, + "state": "PLANNING_WORKTREE_READY" + }, + { + "evidence": [ + "examples/small-change/run/SYSTEM_PROFILE.md" + ], + "result": "PASS", + "sequence": 4, + "state": "PROFILE_READY" + } + ], + "recorded_at": "2026-07-12T18:00:00Z", + "schema_version": "1.1.0" +} diff --git a/examples/small-change/run/evidence/original-goal.md b/examples/small-change/run/evidence/original-goal.md new file mode 100644 index 0000000..1b63d0b --- /dev/null +++ b/examples/small-change/run/evidence/original-goal.md @@ -0,0 +1,3 @@ +# Original goal + +Add validation that rejects an empty display name. diff --git a/examples/small-change/run/manifest.json b/examples/small-change/run/manifest.json new file mode 100644 index 0000000..360eda7 --- /dev/null +++ b/examples/small-change/run/manifest.json @@ -0,0 +1,27 @@ +{ + "contract_versions": { + "artifact_schema": "1.1.0", + "implementation_spec": "2.1", + "plan_contract": "1.0.0" + }, + "created_at": "2026-07-12T18:00:00Z", + "generator_version": "0.1.0", + "paths": { + "compliance": "compliance.json", + "local_state": "local-state.json", + "plan": "PLAN.md", + "repository_profile": "SYSTEM_PROFILE.md", + "run_root": "examples/small-change/run", + "state": "state.json", + "traceability": "traceability.json" + }, + "plan_id": "PG-20260712-180000-A1B2", + "repository": { + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "fingerprint": "sha256:1111111111111111111111111111111111111111111111111111111111111111", + "planning_branch": "pursue/plan/PG-20260712-180000-A1B2/display-name" + }, + "run_id": "20260712T180000Z_PG-20260712-180000-A1B2_display-name", + "schema_version": "1.1.0" +} diff --git a/examples/small-change/run/reports/plan-review/blind-review.json b/examples/small-change/run/reports/plan-review/blind-review.json new file mode 100644 index 0000000..f15e873 --- /dev/null +++ b/examples/small-change/run/reports/plan-review/blind-review.json @@ -0,0 +1,13 @@ +{ + "created_at": "2026-07-12T18:00:00Z", + "findings": [], + "inputs": { + "PLAN.md": "sha256:cc7e04d72d35aa070612042ffdf38d53467f47f865d59c939f2baa6170cb0b8a", + "reports/validation/summary.json": "sha256:38c78d2ad3bf0e35e32acdc5edcec63ffdb3c18a40192e73fa7b57a39131850d", + "traceability.json": "sha256:21687330dfde94f0c52d97a53daedf3406be9a64e56e7ac05fa7e7632355e3c9" + }, + "markdown_hash": "sha256:0b278c608ef8973584e451cb036f19566af028be8bd5b6c0a4fdac484f30341f", + "report_type": "BLIND_PLAN_REVIEW", + "result": "PASS", + "schema_version": "1.1.0" +} diff --git a/examples/small-change/run/reports/plan-review/blind-review.md b/examples/small-change/run/reports/plan-review/blind-review.md new file mode 100644 index 0000000..17f586d --- /dev/null +++ b/examples/small-change/run/reports/plan-review/blind-review.md @@ -0,0 +1,9 @@ +# Blind Plan Review + +## Result + +`PASS` + +## Findings + +No blocking findings. Traceability, testing, rollback, approvals, and the generator/executor boundary are complete. diff --git a/examples/small-change/run/reports/plan-review/comparison.json b/examples/small-change/run/reports/plan-review/comparison.json new file mode 100644 index 0000000..468bd1e --- /dev/null +++ b/examples/small-change/run/reports/plan-review/comparison.json @@ -0,0 +1,9 @@ +{ + "blind_review_hash": "sha256:0b278c608ef8973584e451cb036f19566af028be8bd5b6c0a4fdac484f30341f", + "blind_review_sidecar_hash": "sha256:bfd4b664dea9860ec56d60e87628006165410f59004e3e68250aadcec213a2d9", + "created_at": "2026-07-12T18:00:00Z", + "deterministic_validation": "PASS", + "reasons": [], + "result": "PASS", + "schema_version": "1.1.0" +} diff --git a/examples/small-change/run/reports/validation/summary.json b/examples/small-change/run/reports/validation/summary.json new file mode 100644 index 0000000..d63e31b --- /dev/null +++ b/examples/small-change/run/reports/validation/summary.json @@ -0,0 +1,14 @@ +{ + "findings": [], + "generated_at": "2026-07-12T18:00:00Z", + "phase": "pre-review", + "result": "PASS", + "schema_version": "1.1.0", + "validator": "validate_all", + "validators": { + "artifacts": "PASS", + "diff": "PASS", + "plan": "PASS", + "profile": "PASS" + } +} diff --git a/examples/small-change/run/risks/RISK-01-01.json b/examples/small-change/run/risks/RISK-01-01.json new file mode 100644 index 0000000..a791a4f --- /dev/null +++ b/examples/small-change/run/risks/RISK-01-01.json @@ -0,0 +1,25 @@ +{ + "affected_components": [ + "validator" + ], + "controls": [ + "CTRL-01-01" + ], + "criteria": [ + "AC-01-01" + ], + "description": "Normalization could reject valid names.", + "detection": [ + "CTRL-01-01" + ], + "id": "RISK-01-01", + "impact": "MEDIUM", + "level": "LOW", + "mitigation": "Preserve existing normalization and test valid examples.", + "probability": "LOW", + "rollback": "Revert the stage commit.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-01", + "status": "OPEN" +} diff --git a/examples/small-change/run/stages/STAGE-01.md b/examples/small-change/run/stages/STAGE-01.md new file mode 100644 index 0000000..eb644c6 --- /dev/null +++ b/examples/small-change/run/stages/STAGE-01.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-01" +outcome: 'Reject empty display names while preserving valid input.' +classification: 'ISOLATED' +requirements: ['REQ-01-01'] +criteria: ['AC-01-01'] +risks: ['RISK-01-01'] +dependencies: [] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['src/validator.py', 'tests/test_validator.py'] +--- + +# STAGE-01 — Reject empty display names while preserving valid input. + +## Outcome + +Reject empty display names while preserving valid input. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: none. Stop on conflict. + +## Acceptance criteria + +AC-01-01 must pass. + +## Risks and controls + +RISK-01-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-01-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/small-change/run/state.json b/examples/small-change/run/state.json new file mode 100644 index 0000000..9d0bdf9 --- /dev/null +++ b/examples/small-change/run/state.json @@ -0,0 +1,16 @@ +{ + "artifact_hashes": {}, + "current_phase": "REPORT_AND_STOP", + "current_stage": null, + "last_checkpoint": null, + "mode": "PLAN_GENERATION", + "next_action": { + "target": null, + "type": "NONE" + }, + "open_blockers": [], + "revision": 12, + "schema_version": "1.1.0", + "status": "STOPPED", + "updated_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/small-change/run/traceability.json b/examples/small-change/run/traceability.json new file mode 100644 index 0000000..bfd7d00 --- /dev/null +++ b/examples/small-change/run/traceability.json @@ -0,0 +1,38 @@ +{ + "controls": [ + { + "description": "Focused expected-red and full-suite verification.", + "id": "CTRL-01-01", + "verification": "The focused test fails for the intended reason and all suites finish green." + } + ], + "criteria": [ + { + "controls": [ + "CTRL-01-01" + ], + "evidence": [], + "evidence_type": "AUTOMATED_TEST", + "id": "AC-01-01", + "risks": [ + "RISK-01-01" + ], + "stage": "STAGE-01" + } + ], + "gaps": [], + "requirements": [ + { + "criteria": [ + "AC-01-01" + ], + "critical": true, + "id": "REQ-01-01", + "stages": [ + "STAGE-01" + ], + "text": "Empty display names are rejected without rejecting valid names." + } + ], + "schema_version": "1.1.0" +} diff --git a/examples/small-change/sanitization.json b/examples/small-change/sanitization.json new file mode 100644 index 0000000..1868d60 --- /dev/null +++ b/examples/small-change/sanitization.json @@ -0,0 +1,6 @@ +{ + "absolute_paths": 0, + "local_state_committed": false, + "result": "PASS", + "secrets": 0 +} diff --git a/examples/stateful-change/expected.json b/examples/stateful-change/expected.json new file mode 100644 index 0000000..5874eb9 --- /dev/null +++ b/examples/stateful-change/expected.json @@ -0,0 +1,12 @@ +{ + "classification": "STATEFUL", + "implementation_executed": false, + "stage_ids": [ + "STAGE-01", + "STAGE-02", + "STAGE-03", + "STAGE-04", + "STAGE-05" + ], + "status": "PLAN_READY" +} diff --git a/examples/stateful-change/fixture.md b/examples/stateful-change/fixture.md new file mode 100644 index 0000000..f7e6583 --- /dev/null +++ b/examples/stateful-change/fixture.md @@ -0,0 +1,3 @@ +# Fixture + +Golden contract fixture pinned to `dedb6ab6843bf06d3ac7899aaf37923896915ee7`. No product implementation is included. diff --git a/examples/stateful-change/request.md b/examples/stateful-change/request.md new file mode 100644 index 0000000..b1abb6d --- /dev/null +++ b/examples/stateful-change/request.md @@ -0,0 +1,3 @@ +# Request + +Replace a single status column with a status-history model without downtime. diff --git a/examples/stateful-change/run/PLAN.md b/examples/stateful-change/run/PLAN.md new file mode 100644 index 0000000..80df379 --- /dev/null +++ b/examples/stateful-change/run/PLAN.md @@ -0,0 +1,92 @@ +# Implementation Plan: Status History + +## Identity + +- Plan ID: `PG-20260712-180100-B2C3` +- Run ID: `20260712T180000Z_PG-20260712-180100-B2C3_status-history` +- Contract: PlanAnvil 2.1 +- Artifact schema: 1.1.0 +- Base branch: `main` +- Base SHA: `dedb6ab6843bf06d3ac7899aaf37923896915ee7` +- Planning branch: `pursue/plan/PG-20260712-180100-B2C3/status-history` + +## Original goal + +Replace a single status column with a status-history model without downtime. + +## Outcome and definition of done + +Every acceptance criterion is proven and the later executor can stop or roll back safely. + +## Generator stop boundary + +PlanAnvil generates and validates this contract only. It does not modify product code or tests and does not execute a stage. + +## Separate execution-run prompt + +In a separate Codex run, load this plan and canonical state, reconcile Git and the latest checkpoint, then execute only the next approved stage. + +## Scope + +The stage briefs define the complete approved scope. + +## Exclusions + +Automatic base-branch integration, unrelated refactors, and unapproved destructive work are excluded. + +## Assumptions, unknowns, and evidence + +The analysis files contain verified assumptions and no critical unknowns. + +## Applicable instructions + +Read and verify the complete hashed instruction map before any later write. + +## System and change analysis + +Classification: `STATEFUL`. Component and state boundaries are defined by the stage briefs. + +## Dependencies and classification + +Dependencies are explicit and no stage may be skipped. + +## Stable stage index + +- `STAGE-01` — Add backward-compatible history storage. +- `STAGE-02` — Dual-write old and new status representations. +- `STAGE-03` — Backfill records with resumable checkpoints. +- `STAGE-04` — Switch reads after integrity verification. +- `STAGE-05` — Observe the switch and verify rollback viability. + +## Traceability + +REQ-01-01 → STAGE-01 → AC-01-01; REQ-02-01 → STAGE-02 → AC-02-01; REQ-03-01 → STAGE-03 → AC-03-01; REQ-04-01 → STAGE-04 → AC-04-01; REQ-05-01 → STAGE-05 → AC-05-01. + +## Testing and independent verification + +Behavior stages require GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Git, integration, and control-root rules + +Product changes occur only in task or integration worktrees. The planning worktree remains the control root. One modifier acts at a time. + +## Production verification, switching, and approvals + +Any live switch, irreversible action, or base-branch integration requires explicit user approval. + +## Rollback and recovery + +Each stage has a rollback boundary. Resume only after canonical files and Git reconcile. + +## Resume and reconciliation + +Read manifest, state, local state, profiles, analysis, instruction map, latest checkpoint, and Git state. Stop on mismatch. + +## Status and next action + +- Status: `PLAN_READY` +- Next action: `Start a separate execution run for STAGE-01.` + +## Final report requirements + +Report tests, verification, commits, remaining risks, and approvals. No implementation was executed. Start a separate Codex run using the execution prompt in PLAN.md. diff --git a/examples/stateful-change/run/SYSTEM_PROFILE.md b/examples/stateful-change/run/SYSTEM_PROFILE.md new file mode 100644 index 0000000..4850ddf --- /dev/null +++ b/examples/stateful-change/run/SYSTEM_PROFILE.md @@ -0,0 +1,38 @@ +# PlanAnvil Repository Profile + +- Profile status: `VALID` +- Generated at: `2026-07-12T18:00:00Z` +- Repository fingerprint: `sha256:1111111111111111111111111111111111111111111111111111111111111111` +- Evidence base SHA: `dedb6ab6843bf06d3ac7899aaf37923896915ee7` + +## Repository structure and architecture + +Small fixture repository. + +## Languages, runtimes, and dependency managers + +Python with standard-library tests. + +## Build, test, lint, and static-analysis commands + +Run the fixture test command recorded by the example. + +## Git conventions and quality gates + +One coherent stage commit and a clean worktree. + +## Project instruction map + +The root instruction file applies. + +## Deployment, state, and rollback rules + +No deployment for this fixture. Revert the stage commit on failure. + +## Risk and activation policy + +Explicit activation only. + +## Evidence and freshness + +Evidence is pinned to the fixture base SHA. diff --git a/examples/stateful-change/run/compliance.json b/examples/stateful-change/run/compliance.json new file mode 100644 index 0000000..e08ca99 --- /dev/null +++ b/examples/stateful-change/run/compliance.json @@ -0,0 +1,58 @@ +{ + "capabilities": [ + { + "evidence": [], + "id": "CAP-SKILL-DISCOVERY", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [], + "id": "CAP-EXPLICIT-ACTIVATION", + "required": true, + "status": "DOCUMENTED" + }, + { + "evidence": [ + "examples/stateful-change/run/evidence/git-capability.json" + ], + "id": "CAP-GIT-PROBE", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [ + "evidence/instruction-map.json" + ], + "id": "CAP-INSTRUCTION-MAP", + "required": true, + "status": "VERIFIED" + }, + { + "evidence": [ + "reports/plan-review/blind-review.md", + "reports/plan-review/blind-review.json" + ], + "id": "CAP-BLIND-REVIEW", + "required": true, + "status": "VERIFIED" + } + ], + "codex": { + "hook_mode": "HOOKS_DISABLED", + "model": "fixture", + "permission_mode": "fixture", + "project_trust": "TRUSTED", + "version": "fixture" + }, + "schema_version": "1.1.0", + "unsupported": [ + "Generator execution of implementation stages", + "Automatic base-branch push or merge", + "Hooks as the sole enforcement boundary" + ], + "verified_at": "2026-07-12T18:00:00Z", + "warnings": [ + "Golden fixture; not live Codex capability evidence." + ] +} diff --git a/examples/stateful-change/run/evidence/analysis.json b/examples/stateful-change/run/evidence/analysis.json new file mode 100644 index 0000000..3318fba --- /dev/null +++ b/examples/stateful-change/run/evidence/analysis.json @@ -0,0 +1,32 @@ +{ + "affected_paths": [ + "migrations/**", + "ops/verification/**", + "scripts/backfill/**", + "src/models/**", + "src/status/**", + "tests/backfill/**", + "tests/integration/**", + "tests/migrations/**", + "tests/status/**" + ], + "assumptions": [ + { + "confidence": "VERIFIED", + "evidence": [ + "fixture.md" + ], + "text": "Fixture evidence defines the planning boundary." + } + ], + "classification": "STATEFUL", + "created_at": "2026-07-12T18:00:00Z", + "evidence": [ + "fixture.md" + ], + "goal_hash": "sha256:0bfb3f3c83377485b723efd0ca5431b44801d5c2e3d7ed673a2642c4ceac7ca7", + "markdown_hash": "sha256:88c0e4b2e445880040bbe55062b03a066bd6735bae934bfa8fa16ae03af081bd", + "risk": "HIGH", + "schema_version": "1.1.0", + "unknowns": [] +} diff --git a/examples/stateful-change/run/evidence/analysis.md b/examples/stateful-change/run/evidence/analysis.md new file mode 100644 index 0000000..f80b567 --- /dev/null +++ b/examples/stateful-change/run/evidence/analysis.md @@ -0,0 +1,29 @@ +# Goal analysis + +## Requested outcome + +Replace a single status column with a status-history model without downtime. + +## Repository evidence + +The fixture records the affected components and quality gates. + +## Change classification and risk + +STATEFUL. + +## Affected paths and boundaries + +Only stage allowlists may be modified by the later executor. + +## Assumptions + +The fixture evidence is authoritative for this example. + +## Unknowns and verification + +No critical unknown remains. + +## Recommended stage boundaries + +Stages are split by independent acceptance and rollback boundaries. diff --git a/examples/stateful-change/run/evidence/git-capability.json b/examples/stateful-change/run/evidence/git-capability.json new file mode 100644 index 0000000..743030c --- /dev/null +++ b/examples/stateful-change/run/evidence/git-capability.json @@ -0,0 +1,59 @@ +{ + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "cleanup": { + "errors": [], + "result": "PASS" + }, + "result": "GIT_READY", + "schema_version": "1.1.0", + "source_snapshot": { + "branch": "main", + "head": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "index_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333", + "status_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "steps": [ + { + "id": "create_temporary_ref", + "result": "PASS" + }, + { + "id": "verify_temporary_ref", + "result": "PASS" + }, + { + "id": "delete_temporary_ref", + "result": "PASS" + }, + { + "id": "create_probe_branch", + "result": "PASS" + }, + { + "id": "create_probe_worktree", + "result": "PASS" + }, + { + "id": "checkout_probe_worktree", + "result": "PASS" + }, + { + "id": "create_probe_file", + "result": "PASS" + }, + { + "id": "update_probe_index", + "result": "PASS" + }, + { + "id": "create_probe_commit", + "result": "PASS" + }, + { + "id": "verify_probe_clean", + "result": "PASS" + } + ], + "verified_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/stateful-change/run/evidence/instruction-map.json b/examples/stateful-change/run/evidence/instruction-map.json new file mode 100644 index 0000000..1adde67 --- /dev/null +++ b/examples/stateful-change/run/evidence/instruction-map.json @@ -0,0 +1,41 @@ +{ + "affected_paths": [ + "migrations/**", + "ops/verification/**", + "scripts/backfill/**", + "src/models/**", + "src/status/**", + "tests/backfill/**", + "tests/integration/**", + "tests/migrations/**", + "tests/status/**" + ], + "automatic_byte_limit": 32768, + "conflicts": [], + "fallback_filenames": [], + "files": [ + { + "affected_paths": [ + "migrations/**", + "ops/verification/**", + "scripts/backfill/**", + "src/models/**", + "src/status/**", + "tests/backfill/**", + "tests/integration/**", + "tests/migrations/**", + "tests/status/**" + ], + "bytes": 120, + "full_read": true, + "path": "AGENTS.md", + "precedence": 0, + "safety_critical_rules": [], + "scope": ".", + "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222", + "truncation_risk": false + } + ], + "generated_at": "2026-07-12T18:00:00Z", + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/run/evidence/lifecycle.json b/examples/stateful-change/run/evidence/lifecycle.json new file mode 100644 index 0000000..2382bc6 --- /dev/null +++ b/examples/stateful-change/run/evidence/lifecycle.json @@ -0,0 +1,38 @@ +{ + "events": [ + { + "evidence": [ + "examples/stateful-change/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 1, + "state": "SOURCE_PREFLIGHT_PASSED" + }, + { + "evidence": [ + "examples/stateful-change/run/evidence/git-capability.json" + ], + "result": "PASS", + "sequence": 2, + "state": "GIT_READY" + }, + { + "evidence": [ + "examples/stateful-change/run/manifest.json" + ], + "result": "PASS", + "sequence": 3, + "state": "PLANNING_WORKTREE_READY" + }, + { + "evidence": [ + "examples/stateful-change/run/SYSTEM_PROFILE.md" + ], + "result": "PASS", + "sequence": 4, + "state": "PROFILE_READY" + } + ], + "recorded_at": "2026-07-12T18:00:00Z", + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/run/evidence/original-goal.md b/examples/stateful-change/run/evidence/original-goal.md new file mode 100644 index 0000000..730c513 --- /dev/null +++ b/examples/stateful-change/run/evidence/original-goal.md @@ -0,0 +1,3 @@ +# Original goal + +Replace a single status column with a status-history model without downtime. diff --git a/examples/stateful-change/run/manifest.json b/examples/stateful-change/run/manifest.json new file mode 100644 index 0000000..1dafa77 --- /dev/null +++ b/examples/stateful-change/run/manifest.json @@ -0,0 +1,27 @@ +{ + "contract_versions": { + "artifact_schema": "1.1.0", + "implementation_spec": "2.1", + "plan_contract": "1.0.0" + }, + "created_at": "2026-07-12T18:00:00Z", + "generator_version": "0.1.0", + "paths": { + "compliance": "compliance.json", + "local_state": "local-state.json", + "plan": "PLAN.md", + "repository_profile": "SYSTEM_PROFILE.md", + "run_root": "examples/stateful-change/run", + "state": "state.json", + "traceability": "traceability.json" + }, + "plan_id": "PG-20260712-180100-B2C3", + "repository": { + "base_branch": "main", + "base_sha": "dedb6ab6843bf06d3ac7899aaf37923896915ee7", + "fingerprint": "sha256:1111111111111111111111111111111111111111111111111111111111111111", + "planning_branch": "pursue/plan/PG-20260712-180100-B2C3/status-history" + }, + "run_id": "20260712T180000Z_PG-20260712-180100-B2C3_status-history", + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/run/reports/plan-review/blind-review.json b/examples/stateful-change/run/reports/plan-review/blind-review.json new file mode 100644 index 0000000..43fe48e --- /dev/null +++ b/examples/stateful-change/run/reports/plan-review/blind-review.json @@ -0,0 +1,13 @@ +{ + "created_at": "2026-07-12T18:00:00Z", + "findings": [], + "inputs": { + "PLAN.md": "sha256:a617c5635cc5575e4c1bb8ba152812b5cfb7696bb2ff6c6a8f45911e8207467b", + "reports/validation/summary.json": "sha256:38c78d2ad3bf0e35e32acdc5edcec63ffdb3c18a40192e73fa7b57a39131850d", + "traceability.json": "sha256:3a5d1d247c1339edfcb0d1c5e4de37e1852bba5f8efc92e9e15786f73ee1acda" + }, + "markdown_hash": "sha256:0b278c608ef8973584e451cb036f19566af028be8bd5b6c0a4fdac484f30341f", + "report_type": "BLIND_PLAN_REVIEW", + "result": "PASS", + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/run/reports/plan-review/blind-review.md b/examples/stateful-change/run/reports/plan-review/blind-review.md new file mode 100644 index 0000000..17f586d --- /dev/null +++ b/examples/stateful-change/run/reports/plan-review/blind-review.md @@ -0,0 +1,9 @@ +# Blind Plan Review + +## Result + +`PASS` + +## Findings + +No blocking findings. Traceability, testing, rollback, approvals, and the generator/executor boundary are complete. diff --git a/examples/stateful-change/run/reports/plan-review/comparison.json b/examples/stateful-change/run/reports/plan-review/comparison.json new file mode 100644 index 0000000..b1478a0 --- /dev/null +++ b/examples/stateful-change/run/reports/plan-review/comparison.json @@ -0,0 +1,9 @@ +{ + "blind_review_hash": "sha256:0b278c608ef8973584e451cb036f19566af028be8bd5b6c0a4fdac484f30341f", + "blind_review_sidecar_hash": "sha256:f1a0f88f3221571225909d189b4f77553447c30b322686afd52f39e87e74f8fb", + "created_at": "2026-07-12T18:00:00Z", + "deterministic_validation": "PASS", + "reasons": [], + "result": "PASS", + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/run/reports/validation/summary.json b/examples/stateful-change/run/reports/validation/summary.json new file mode 100644 index 0000000..d63e31b --- /dev/null +++ b/examples/stateful-change/run/reports/validation/summary.json @@ -0,0 +1,14 @@ +{ + "findings": [], + "generated_at": "2026-07-12T18:00:00Z", + "phase": "pre-review", + "result": "PASS", + "schema_version": "1.1.0", + "validator": "validate_all", + "validators": { + "artifacts": "PASS", + "diff": "PASS", + "plan": "PASS", + "profile": "PASS" + } +} diff --git a/examples/stateful-change/run/risks/RISK-01-01.json b/examples/stateful-change/run/risks/RISK-01-01.json new file mode 100644 index 0000000..22f39c7 --- /dev/null +++ b/examples/stateful-change/run/risks/RISK-01-01.json @@ -0,0 +1,26 @@ +{ + "affected_components": [ + "database", + "application" + ], + "controls": [ + "CTRL-01-01" + ], + "criteria": [ + "AC-01-01" + ], + "description": "State may become inconsistent during the staged migration.", + "detection": [ + "CTRL-01-01" + ], + "id": "RISK-01-01", + "impact": "HIGH", + "level": "HIGH", + "mitigation": "Use backward-compatible, resumable, verified steps.", + "probability": "MEDIUM", + "rollback": "Restore the verified recovery point or switch reads back before contraction.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-01", + "status": "OPEN" +} diff --git a/examples/stateful-change/run/risks/RISK-02-01.json b/examples/stateful-change/run/risks/RISK-02-01.json new file mode 100644 index 0000000..616852a --- /dev/null +++ b/examples/stateful-change/run/risks/RISK-02-01.json @@ -0,0 +1,26 @@ +{ + "affected_components": [ + "database", + "application" + ], + "controls": [ + "CTRL-02-01" + ], + "criteria": [ + "AC-02-01" + ], + "description": "State may become inconsistent during the staged migration.", + "detection": [ + "CTRL-02-01" + ], + "id": "RISK-02-01", + "impact": "HIGH", + "level": "HIGH", + "mitigation": "Use backward-compatible, resumable, verified steps.", + "probability": "MEDIUM", + "rollback": "Restore the verified recovery point or switch reads back before contraction.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-02", + "status": "OPEN" +} diff --git a/examples/stateful-change/run/risks/RISK-03-01.json b/examples/stateful-change/run/risks/RISK-03-01.json new file mode 100644 index 0000000..329ecdd --- /dev/null +++ b/examples/stateful-change/run/risks/RISK-03-01.json @@ -0,0 +1,26 @@ +{ + "affected_components": [ + "database", + "application" + ], + "controls": [ + "CTRL-03-01" + ], + "criteria": [ + "AC-03-01" + ], + "description": "State may become inconsistent during the staged migration.", + "detection": [ + "CTRL-03-01" + ], + "id": "RISK-03-01", + "impact": "HIGH", + "level": "HIGH", + "mitigation": "Use backward-compatible, resumable, verified steps.", + "probability": "MEDIUM", + "rollback": "Restore the verified recovery point or switch reads back before contraction.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-03", + "status": "OPEN" +} diff --git a/examples/stateful-change/run/risks/RISK-04-01.json b/examples/stateful-change/run/risks/RISK-04-01.json new file mode 100644 index 0000000..1f7dadc --- /dev/null +++ b/examples/stateful-change/run/risks/RISK-04-01.json @@ -0,0 +1,26 @@ +{ + "affected_components": [ + "database", + "application" + ], + "controls": [ + "CTRL-04-01" + ], + "criteria": [ + "AC-04-01" + ], + "description": "State may become inconsistent during the staged migration.", + "detection": [ + "CTRL-04-01" + ], + "id": "RISK-04-01", + "impact": "HIGH", + "level": "HIGH", + "mitigation": "Use backward-compatible, resumable, verified steps.", + "probability": "MEDIUM", + "rollback": "Restore the verified recovery point or switch reads back before contraction.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-04", + "status": "OPEN" +} diff --git a/examples/stateful-change/run/risks/RISK-05-01.json b/examples/stateful-change/run/risks/RISK-05-01.json new file mode 100644 index 0000000..51c9e00 --- /dev/null +++ b/examples/stateful-change/run/risks/RISK-05-01.json @@ -0,0 +1,26 @@ +{ + "affected_components": [ + "database", + "application" + ], + "controls": [ + "CTRL-05-01" + ], + "criteria": [ + "AC-05-01" + ], + "description": "State may become inconsistent during the staged migration.", + "detection": [ + "CTRL-05-01" + ], + "id": "RISK-05-01", + "impact": "HIGH", + "level": "HIGH", + "mitigation": "Use backward-compatible, resumable, verified steps.", + "probability": "MEDIUM", + "rollback": "Restore the verified recovery point or switch reads back before contraction.", + "schema_version": "1.1.0", + "source": "Fixture analysis", + "stage": "STAGE-05", + "status": "OPEN" +} diff --git a/examples/stateful-change/run/stages/STAGE-01.md b/examples/stateful-change/run/stages/STAGE-01.md new file mode 100644 index 0000000..41cbc13 --- /dev/null +++ b/examples/stateful-change/run/stages/STAGE-01.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-01" +outcome: 'Add backward-compatible history storage.' +classification: 'STATEFUL' +requirements: ['REQ-01-01'] +criteria: ['AC-01-01'] +risks: ['RISK-01-01'] +dependencies: [] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['src/models/**', 'migrations/**', 'tests/migrations/**'] +--- + +# STAGE-01 — Add backward-compatible history storage. + +## Outcome + +Add backward-compatible history storage. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: none. Stop on conflict. + +## Acceptance criteria + +AC-01-01 must pass. + +## Risks and controls + +RISK-01-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-01-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/stateful-change/run/stages/STAGE-02.md b/examples/stateful-change/run/stages/STAGE-02.md new file mode 100644 index 0000000..0031573 --- /dev/null +++ b/examples/stateful-change/run/stages/STAGE-02.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-02" +outcome: 'Dual-write old and new status representations.' +classification: 'STATEFUL' +requirements: ['REQ-02-01'] +criteria: ['AC-02-01'] +risks: ['RISK-02-01'] +dependencies: ['STAGE-01'] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['src/status/**', 'tests/status/**'] +--- + +# STAGE-02 — Dual-write old and new status representations. + +## Outcome + +Dual-write old and new status representations. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: STAGE-01. Stop on conflict. + +## Acceptance criteria + +AC-02-01 must pass. + +## Risks and controls + +RISK-02-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-02-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/stateful-change/run/stages/STAGE-03.md b/examples/stateful-change/run/stages/STAGE-03.md new file mode 100644 index 0000000..a3d24a4 --- /dev/null +++ b/examples/stateful-change/run/stages/STAGE-03.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-03" +outcome: 'Backfill records with resumable checkpoints.' +classification: 'STATEFUL' +requirements: ['REQ-03-01'] +criteria: ['AC-03-01'] +risks: ['RISK-03-01'] +dependencies: ['STAGE-02'] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['scripts/backfill/**', 'tests/backfill/**'] +--- + +# STAGE-03 — Backfill records with resumable checkpoints. + +## Outcome + +Backfill records with resumable checkpoints. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: STAGE-02. Stop on conflict. + +## Acceptance criteria + +AC-03-01 must pass. + +## Risks and controls + +RISK-03-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-03-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/stateful-change/run/stages/STAGE-04.md b/examples/stateful-change/run/stages/STAGE-04.md new file mode 100644 index 0000000..d2fff82 --- /dev/null +++ b/examples/stateful-change/run/stages/STAGE-04.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-04" +outcome: 'Switch reads after integrity verification.' +classification: 'STATEFUL' +requirements: ['REQ-04-01'] +criteria: ['AC-04-01'] +risks: ['RISK-04-01'] +dependencies: ['STAGE-03'] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['src/status/**', 'tests/status/**'] +--- + +# STAGE-04 — Switch reads after integrity verification. + +## Outcome + +Switch reads after integrity verification. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: STAGE-03. Stop on conflict. + +## Acceptance criteria + +AC-04-01 must pass. + +## Risks and controls + +RISK-04-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-04-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/stateful-change/run/stages/STAGE-05.md b/examples/stateful-change/run/stages/STAGE-05.md new file mode 100644 index 0000000..deef85d --- /dev/null +++ b/examples/stateful-change/run/stages/STAGE-05.md @@ -0,0 +1,62 @@ +--- +schema_version: "1.1.0" +stage_id: "STAGE-05" +outcome: 'Observe the switch and verify rollback viability.' +classification: 'STATEFUL' +requirements: ['REQ-05-01'] +criteria: ['AC-05-01'] +risks: ['RISK-05-01'] +dependencies: ['STAGE-04'] +applicable_instructions: [{"path": "AGENTS.md", "sha256": "sha256:2222222222222222222222222222222222222222222222222222222222222222"}] +allowed_write_paths: ['ops/verification/**', 'tests/integration/**'] +--- + +# STAGE-05 — Observe the switch and verify rollback viability. + +## Outcome + +Observe the switch and verify rollback viability. + +## Scope + +Only the approved paths and acceptance behavior. + +## Exclusions + +Unrelated changes and automatic integration. + +## Affected paths or discovery procedure + +Verify the mapped paths before editing. + +## Applicable instructions + +Read the hashed instruction file in full. + +## Dependencies and conflicts + +Dependencies: STAGE-04. Stop on conflict. + +## Acceptance criteria + +AC-05-01 must pass. + +## Risks and controls + +RISK-05-01 is controlled by the linked controls and evidence. + +## Evidence cycle + +GREEN BASELINE → EXPECTED RED → IMPLEMENTATION → FULL GREEN → INDEPENDENT VERIFICATION. + +## Modifier and verifier roles + +One modifier writes approved paths; the verifier remains read-only. + +## Commit and checkpoint + +Create one coherent commit and `CHECKPOINT-05-VERIFIED`. + +## Rollback + +Revert the stage commit or apply the stage-specific recovery procedure. diff --git a/examples/stateful-change/run/state.json b/examples/stateful-change/run/state.json new file mode 100644 index 0000000..9d0bdf9 --- /dev/null +++ b/examples/stateful-change/run/state.json @@ -0,0 +1,16 @@ +{ + "artifact_hashes": {}, + "current_phase": "REPORT_AND_STOP", + "current_stage": null, + "last_checkpoint": null, + "mode": "PLAN_GENERATION", + "next_action": { + "target": null, + "type": "NONE" + }, + "open_blockers": [], + "revision": 12, + "schema_version": "1.1.0", + "status": "STOPPED", + "updated_at": "2026-07-12T18:00:00Z" +} diff --git a/examples/stateful-change/run/traceability.json b/examples/stateful-change/run/traceability.json new file mode 100644 index 0000000..8e11c0c --- /dev/null +++ b/examples/stateful-change/run/traceability.json @@ -0,0 +1,150 @@ +{ + "controls": [ + { + "description": "Verify add backward-compatible history storage.", + "id": "CTRL-01-01", + "verification": "Record automated and operational evidence before the checkpoint." + }, + { + "description": "Verify dual-write old and new status representations.", + "id": "CTRL-02-01", + "verification": "Record automated and operational evidence before the checkpoint." + }, + { + "description": "Verify backfill records with resumable checkpoints.", + "id": "CTRL-03-01", + "verification": "Record automated and operational evidence before the checkpoint." + }, + { + "description": "Verify switch reads after integrity verification.", + "id": "CTRL-04-01", + "verification": "Record automated and operational evidence before the checkpoint." + }, + { + "description": "Verify observe the switch and verify rollback viability.", + "id": "CTRL-05-01", + "verification": "Record automated and operational evidence before the checkpoint." + } + ], + "criteria": [ + { + "controls": [ + "CTRL-01-01" + ], + "evidence": [], + "evidence_type": "MIGRATION_EVIDENCE", + "id": "AC-01-01", + "risks": [ + "RISK-01-01" + ], + "stage": "STAGE-01" + }, + { + "controls": [ + "CTRL-02-01" + ], + "evidence": [], + "evidence_type": "AUTOMATED_TEST", + "id": "AC-02-01", + "risks": [ + "RISK-02-01" + ], + "stage": "STAGE-02" + }, + { + "controls": [ + "CTRL-03-01" + ], + "evidence": [], + "evidence_type": "MIGRATION_EVIDENCE", + "id": "AC-03-01", + "risks": [ + "RISK-03-01" + ], + "stage": "STAGE-03" + }, + { + "controls": [ + "CTRL-04-01" + ], + "evidence": [], + "evidence_type": "MIGRATION_EVIDENCE", + "id": "AC-04-01", + "risks": [ + "RISK-04-01" + ], + "stage": "STAGE-04" + }, + { + "controls": [ + "CTRL-05-01" + ], + "evidence": [], + "evidence_type": "MIGRATION_EVIDENCE", + "id": "AC-05-01", + "risks": [ + "RISK-05-01" + ], + "stage": "STAGE-05" + } + ], + "gaps": [], + "requirements": [ + { + "criteria": [ + "AC-01-01" + ], + "critical": true, + "id": "REQ-01-01", + "stages": [ + "STAGE-01" + ], + "text": "Add backward-compatible history storage." + }, + { + "criteria": [ + "AC-02-01" + ], + "critical": true, + "id": "REQ-02-01", + "stages": [ + "STAGE-02" + ], + "text": "Dual-write old and new status representations." + }, + { + "criteria": [ + "AC-03-01" + ], + "critical": true, + "id": "REQ-03-01", + "stages": [ + "STAGE-03" + ], + "text": "Backfill records with resumable checkpoints." + }, + { + "criteria": [ + "AC-04-01" + ], + "critical": true, + "id": "REQ-04-01", + "stages": [ + "STAGE-04" + ], + "text": "Switch reads after integrity verification." + }, + { + "criteria": [ + "AC-05-01" + ], + "critical": true, + "id": "REQ-05-01", + "stages": [ + "STAGE-05" + ], + "text": "Observe the switch and verify rollback viability." + } + ], + "schema_version": "1.1.0" +} diff --git a/examples/stateful-change/sanitization.json b/examples/stateful-change/sanitization.json new file mode 100644 index 0000000..1868d60 --- /dev/null +++ b/examples/stateful-change/sanitization.json @@ -0,0 +1,6 @@ +{ + "absolute_paths": 0, + "local_state_committed": false, + "result": "PASS", + "secrets": 0 +}