optz: Goal orchestrator
This commit is contained in:
@@ -92,3 +92,57 @@
|
|||||||
{"timestamp":"2026-07-10T06:20:20Z","trace_id":"trace-1783664420-1347","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44","output_hash":"d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44"}
|
{"timestamp":"2026-07-10T06:20:20Z","trace_id":"trace-1783664420-1347","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44","output_hash":"d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44"}
|
||||||
{"timestamp":"2026-07-10T07:20:30Z","trace_id":"trace-1783668030-52","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa","output_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa"}
|
{"timestamp":"2026-07-10T07:20:30Z","trace_id":"trace-1783668030-52","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa","output_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa"}
|
||||||
{"timestamp":"2026-07-10T07:21:21Z","trace_id":"trace-1783668081-716","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e","output_hash":"280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e"}
|
{"timestamp":"2026-07-10T07:21:21Z","trace_id":"trace-1783668081-716","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e","output_hash":"280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e"}
|
||||||
|
{"timestamp":"2026-07-10T08:10:53Z","trace_id":"trace-1783671053-3456","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"a5029c2ba88119946f6ad1c38d796eea7f3519b4ef847a98ef827633e796c717","output_hash":"a5029c2ba88119946f6ad1c38d796eea7f3519b4ef847a98ef827633e796c717"}
|
||||||
|
{"timestamp":"2026-07-10T08:37:34Z","trace_id":"trace-1783672654-290","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:38:21Z","trace_id":"trace-1783672701-1074","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:38:29Z","trace_id":"trace-1783672709-1683","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:39:00Z","trace_id":"trace-1783672740-2286","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:39:07Z","trace_id":"trace-1783672747-2894","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:39:13Z","trace_id":"trace-1783672753-3495","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:39:54Z","trace_id":"trace-1783672794-129","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5","output_hash":"305d51e7bd89770c78e56848036699dbdf4040c1d17a325c8b534703c5fa45c5"}
|
||||||
|
{"timestamp":"2026-07-10T08:40:24Z","trace_id":"trace-1783672824-709","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"98be3b34b18aae993bb1a5c6f2151a21b9e103a8f56c19e650bf03514231cb26","output_hash":"98be3b34b18aae993bb1a5c6f2151a21b9e103a8f56c19e650bf03514231cb26"}
|
||||||
|
{"timestamp":"2026-07-10T08:45:46Z","trace_id":"trace-1783673146-2396","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"2fcbb74936de0bc90851761d4f0c53506b696fc83f50c1f5b91119236af6ed83","output_hash":"2fcbb74936de0bc90851761d4f0c53506b696fc83f50c1f5b91119236af6ed83"}
|
||||||
|
{"timestamp":"2026-07-10T08:46:14Z","trace_id":"trace-1783673174-3110","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"a5bbfed3fa6a86702ff80efcdac35d14cfb2a3cfb9692c03584baf2a5fe9b76c","output_hash":"a5bbfed3fa6a86702ff80efcdac35d14cfb2a3cfb9692c03584baf2a5fe9b76c"}
|
||||||
|
{"timestamp":"2026-07-10T08:48:31Z","trace_id":"trace-1783673311-3706","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"ade0e2d2828ff5a8f87d08d62f320f69e057fdbcbba54935a5346601c6ef93fc","output_hash":"ade0e2d2828ff5a8f87d08d62f320f69e057fdbcbba54935a5346601c6ef93fc"}
|
||||||
|
{"timestamp":"2026-07-10T08:48:51Z","trace_id":"trace-1783673331-4392","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"2c52b7763ce9f000c563843ffc3301f85f1d95f6b5f8e818c02acb7dd2aa842f","output_hash":"2c52b7763ce9f000c563843ffc3301f85f1d95f6b5f8e818c02acb7dd2aa842f"}
|
||||||
|
{"timestamp":"2026-07-10T08:49:37Z","trace_id":"trace-1783673377-4840","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"18f3c234faddf6ad5421a2b9cae1036a7a958bc4ecc534f8e8f8395670c2530c","output_hash":"18f3c234faddf6ad5421a2b9cae1036a7a958bc4ecc534f8e8f8395670c2530c"}
|
||||||
|
{"timestamp":"2026-07-10T08:49:57Z","trace_id":"trace-1783673397-5474","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"757ffca4ffccc7668753e79687ee40738d795428588fee4c6b8180c0bc734124","output_hash":"757ffca4ffccc7668753e79687ee40738d795428588fee4c6b8180c0bc734124"}
|
||||||
|
{"timestamp":"2026-07-10T08:51:04Z","trace_id":"trace-1783673464-5971","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"1ce53bc84ad799d7ca3890e6a79e8a695ea48b8fce13f78c38eb657e2fe80ed7","output_hash":"1ce53bc84ad799d7ca3890e6a79e8a695ea48b8fce13f78c38eb657e2fe80ed7"}
|
||||||
|
{"timestamp":"2026-07-10T08:51:25Z","trace_id":"trace-1783673485-6637","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"14b9e1c2352607b7a4d0dfa80e22d6d4ec1409db91511cc610bd3c7f975d3321","output_hash":"14b9e1c2352607b7a4d0dfa80e22d6d4ec1409db91511cc610bd3c7f975d3321"}
|
||||||
|
{"timestamp":"2026-07-10T14:24:32Z","trace_id":"trace-1783693472-175","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"6a4afba59fa567c089a84e6e933c8665380c63c93f00de70e1cba2a26512f623","output_hash":"6a4afba59fa567c089a84e6e933c8665380c63c93f00de70e1cba2a26512f623"}
|
||||||
|
{"timestamp":"2026-07-10T14:25:28Z","trace_id":"trace-1783693528-893","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"317d789d9c23693bb1dda981d9f75e1eff9ca8fa1aa9a722115c6fef78caad23","output_hash":"317d789d9c23693bb1dda981d9f75e1eff9ca8fa1aa9a722115c6fef78caad23"}
|
||||||
|
{"timestamp":"2026-07-10T14:26:59Z","trace_id":"trace-1783693619-122","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"491375254fe83e91fad084ef998ddda780654f1ef921a2cd9148466a74fb1c9a","output_hash":"491375254fe83e91fad084ef998ddda780654f1ef921a2cd9148466a74fb1c9a"}
|
||||||
|
{"timestamp":"2026-07-10T14:27:46Z","trace_id":"trace-1783693666-838","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"642e21a39cd734fd6667a540da58d494fe3e3a2d4a2297b49334dc5536834c77","output_hash":"642e21a39cd734fd6667a540da58d494fe3e3a2d4a2297b49334dc5536834c77"}
|
||||||
|
{"timestamp":"2026-07-10T14:33:04Z","trace_id":"trace-1783693984-175","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"5e9f6afb8b00b1c071e64b07ffa8ee66d67f298d65a0b6285a2f3ad92010aa56","output_hash":"5e9f6afb8b00b1c071e64b07ffa8ee66d67f298d65a0b6285a2f3ad92010aa56"}
|
||||||
|
{"timestamp":"2026-07-10T14:33:34Z","trace_id":"trace-1783694014-789","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"1e1864543ed2100727fadf80b16bf47ed37d681f3a603bdd9342bfcaa86a5bb7","output_hash":"1e1864543ed2100727fadf80b16bf47ed37d681f3a603bdd9342bfcaa86a5bb7"}
|
||||||
|
{"timestamp":"2026-07-10T14:33:48Z","trace_id":"trace-1783694028-933","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"e08f4d05c9a0f21dbdc0edc3d759d9324cbd6ca23d3ab958edac1305ecbfeb17","output_hash":"e08f4d05c9a0f21dbdc0edc3d759d9324cbd6ca23d3ab958edac1305ecbfeb17"}
|
||||||
|
{"timestamp":"2026-07-10T14:46:33Z","trace_id":"trace-1783694793-134","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"f0becd0ba8ba760f9e11045bc17c25c826cef2fd9b5848568a6e704da48562d3","output_hash":"f0becd0ba8ba760f9e11045bc17c25c826cef2fd9b5848568a6e704da48562d3"}
|
||||||
|
{"timestamp":"2026-07-10T14:46:33Z","trace_id":"trace-1783694793-600","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"6cbc480a81d9e566f94340e479b0da7780e51f0ef93db82a9e6d808d93509c2c","output_hash":"6cbc480a81d9e566f94340e479b0da7780e51f0ef93db82a9e6d808d93509c2c"}
|
||||||
|
{"timestamp":"2026-07-10T14:46:34Z","trace_id":"trace-1783694794-1066","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"49bd44fb1dd64f1606d448efcc591f6662bb6c06de2541ce3ea6804f3d2b6c5f","output_hash":"49bd44fb1dd64f1606d448efcc591f6662bb6c06de2541ce3ea6804f3d2b6c5f"}
|
||||||
|
{"timestamp":"2026-07-10T14:46:35Z","trace_id":"trace-1783694795-1532","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"a2ffaa6bc02119947e88c0899e3efb78084e20072b5650e1d463b3e978acb644","output_hash":"a2ffaa6bc02119947e88c0899e3efb78084e20072b5650e1d463b3e978acb644"}
|
||||||
|
{"timestamp":"2026-07-10T14:46:35Z","trace_id":"trace-1783694795-1997","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"b122eccde5def8f8a3ede374073d555eeb0649060a93650ca0fdffb940760321","output_hash":"b122eccde5def8f8a3ede374073d555eeb0649060a93650ca0fdffb940760321"}
|
||||||
|
{"timestamp":"2026-07-10T14:59:15Z","trace_id":"trace-1783695555-208","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"b65685191514667998f209dd8ce72e73e83fb0c2be00e8bd3c7e7cfef02fbd7a","output_hash":"b65685191514667998f209dd8ce72e73e83fb0c2be00e8bd3c7e7cfef02fbd7a"}
|
||||||
|
{"timestamp":"2026-07-10T15:07:10Z","trace_id":"trace-1783696030-1110","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"63073e9ea949155b9fc8db84dca22a3b8a635b11ab60e45b00c5914c842473fa","output_hash":"63073e9ea949155b9fc8db84dca22a3b8a635b11ab60e45b00c5914c842473fa"}
|
||||||
|
{"timestamp":"2026-07-10T15:11:07Z","trace_id":"trace-1783696267-3617","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa","output_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa"}
|
||||||
|
{"timestamp":"2026-07-10T15:11:50Z","trace_id":"trace-1783696310-4454","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"d5e4481c6b2b996576af60207f92dc3c8d400d56909a23d41a96d491f520589f","output_hash":"d5e4481c6b2b996576af60207f92dc3c8d400d56909a23d41a96d491f520589f"}
|
||||||
|
{"timestamp":"2026-07-10T15:12:19Z","trace_id":"trace-1783696339-4956","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"d6f4b13ee10ffdf48682e7f3d43f5e4df05dff4b9d2e63b1a8585220634b5027","output_hash":"d6f4b13ee10ffdf48682e7f3d43f5e4df05dff4b9d2e63b1a8585220634b5027"}
|
||||||
|
{"timestamp":"2026-07-10T15:13:05Z","trace_id":"trace-1783696385-5687","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"9b65df7891907c5a3a9fadc9b72f5541e548f330aeffd31365a50a690a415d97","output_hash":"9b65df7891907c5a3a9fadc9b72f5541e548f330aeffd31365a50a690a415d97"}
|
||||||
|
{"timestamp":"2026-07-11T02:45:11Z","trace_id":"trace-1783737911-272","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa","output_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa"}
|
||||||
|
{"timestamp":"2026-07-11T02:54:20Z","trace_id":"trace-1783738460-1030","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa","output_hash":"8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa"}
|
||||||
|
{"timestamp":"2026-07-11T02:54:39Z","trace_id":"trace-1783738479-1761","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"d5e4481c6b2b996576af60207f92dc3c8d400d56909a23d41a96d491f520589f","output_hash":"d5e4481c6b2b996576af60207f92dc3c8d400d56909a23d41a96d491f520589f"}
|
||||||
|
{"timestamp":"2026-07-11T02:55:18Z","trace_id":"trace-1783738518-2282","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"77100d99316b67f917a2dc398f03532f93c86f9f94fc6d1f0a2ec9a128017b2b","output_hash":"77100d99316b67f917a2dc398f03532f93c86f9f94fc6d1f0a2ec9a128017b2b"}
|
||||||
|
{"timestamp":"2026-07-11T02:55:45Z","trace_id":"trace-1783738545-3066","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"a22bc04e692ed93ccf0a1564be9f47ecd8e4991ca69780760ce14a26f73178af","output_hash":"a22bc04e692ed93ccf0a1564be9f47ecd8e4991ca69780760ce14a26f73178af"}
|
||||||
|
{"timestamp":"2026-07-11T02:56:30Z","trace_id":"trace-1783738590-3520","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a","output_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a"}
|
||||||
|
{"timestamp":"2026-07-11T03:03:09Z","trace_id":"trace-1783738989-117","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a","output_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a"}
|
||||||
|
{"timestamp":"2026-07-11T03:04:01Z","trace_id":"trace-1783739041-117","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a","output_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a"}
|
||||||
|
{"timestamp":"2026-07-11T03:04:11Z","trace_id":"trace-1783739051-704","harness":"H4-security","mode":"input","status":"blocked","action":"block","risk_level":"high","input_hash":"c54aefd8623387334779587082579e91f78f55a823adbf5cf812f98a6255dc85","output_hash":"c54aefd8623387334779587082579e91f78f55a823adbf5cf812f98a6255dc85"}
|
||||||
|
{"timestamp":"2026-07-11T03:04:43Z","trace_id":"trace-1783739083-1081","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"3cb27554ac2eb202e09ec170b6a6fb028d4fd9b15a3448e999db8a88b3a7e5e4","output_hash":"3cb27554ac2eb202e09ec170b6a6fb028d4fd9b15a3448e999db8a88b3a7e5e4"}
|
||||||
|
{"timestamp":"2026-07-11T03:05:27Z","trace_id":"trace-1783739127-1189","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"d94f7cb51d952fcaffb585e76c16542aba2f774d64c6d270eab32e7888eccc40","output_hash":"d94f7cb51d952fcaffb585e76c16542aba2f774d64c6d270eab32e7888eccc40"}
|
||||||
|
{"timestamp":"2026-07-11T03:06:28Z","trace_id":"trace-1783739188-1394","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a","output_hash":"d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a"}
|
||||||
|
{"timestamp":"2026-07-11T03:07:06Z","trace_id":"trace-1783739226-1926","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"dbdf75779e5a2b0732d18da95767b4231985a6205836f12321935404b41a47c3","output_hash":"dbdf75779e5a2b0732d18da95767b4231985a6205836f12321935404b41a47c3"}
|
||||||
|
{"timestamp":"2026-07-11T03:07:54Z","trace_id":"trace-1783739274-2082","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"fd6094f85e823a0be31d54bc5dbecf5e174275ad8b85ca2aa56f58658789e7a3","output_hash":"fd6094f85e823a0be31d54bc5dbecf5e174275ad8b85ca2aa56f58658789e7a3"}
|
||||||
|
{"timestamp":"2026-07-11T03:09:42Z","trace_id":"trace-1783739382-2291","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"9e2a2bc7bccc5123fb02c5789591db77dabed477b5ffba09f2db460de423bb05","output_hash":"9e2a2bc7bccc5123fb02c5789591db77dabed477b5ffba09f2db460de423bb05"}
|
||||||
|
{"timestamp":"2026-07-11T03:13:24Z","trace_id":"trace-1783739604-121","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"63073e9ea949155b9fc8db84dca22a3b8a635b11ab60e45b00c5914c842473fa","output_hash":"63073e9ea949155b9fc8db84dca22a3b8a635b11ab60e45b00c5914c842473fa"}
|
||||||
|
{"timestamp":"2026-07-11T03:14:47Z","trace_id":"trace-1783739687-743","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"41787b8b4a629028ae972d8db1cf4ac491af928978e0469269655a140a41e20c","output_hash":"41787b8b4a629028ae972d8db1cf4ac491af928978e0469269655a140a41e20c"}
|
||||||
|
{"timestamp":"2026-07-11T03:15:44Z","trace_id":"trace-1783739744-857","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"8367afe050a5086cac52162ee740dc4f68949e6901538d86f49802ad069e1e54","output_hash":"8367afe050a5086cac52162ee740dc4f68949e6901538d86f49802ad069e1e54"}
|
||||||
|
{"timestamp":"2026-07-11T03:17:50Z","trace_id":"trace-1783739870-1068","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"744ebdf28580ca15b50dd647f69de9e8ae2288bd6267a2a792f4ca2816f856f9","output_hash":"744ebdf28580ca15b50dd647f69de9e8ae2288bd6267a2a792f4ca2816f856f9"}
|
||||||
|
|||||||
@@ -23,3 +23,9 @@
|
|||||||
{"timestamp": "2026-07-10T06:19:34Z", "trace_id": "d8796e51-f1bf-4950-b27d-5327ed69ee12", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 57864, "retry_count": 0, "input_tokens": 427, "output_tokens": 406, "total_tokens": 833, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "5da5739dfab4b282139a20d7272d0e676331eb09f86f562cc5e6d1f3b668a5ab", "output_hash": "142404dfd1bd2e31f6bef54bb495685e059a9b5c4b2e3369c8b79f8c7bec67a9"}
|
{"timestamp": "2026-07-10T06:19:34Z", "trace_id": "d8796e51-f1bf-4950-b27d-5327ed69ee12", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 57864, "retry_count": 0, "input_tokens": 427, "output_tokens": 406, "total_tokens": 833, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "5da5739dfab4b282139a20d7272d0e676331eb09f86f562cc5e6d1f3b668a5ab", "output_hash": "142404dfd1bd2e31f6bef54bb495685e059a9b5c4b2e3369c8b79f8c7bec67a9"}
|
||||||
{"timestamp": "2026-07-10T06:20:20Z", "trace_id": "b5ad414a-4662-49c5-a024-3f2bb51ada64", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 43174, "retry_count": 0, "input_tokens": 511, "output_tokens": 288, "total_tokens": 799, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "5da5739dfab4b282139a20d7272d0e676331eb09f86f562cc5e6d1f3b668a5ab", "output_hash": "d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44"}
|
{"timestamp": "2026-07-10T06:20:20Z", "trace_id": "b5ad414a-4662-49c5-a024-3f2bb51ada64", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 43174, "retry_count": 0, "input_tokens": 511, "output_tokens": 288, "total_tokens": 799, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "5da5739dfab4b282139a20d7272d0e676331eb09f86f562cc5e6d1f3b668a5ab", "output_hash": "d1c3c3a7ee70994d948443ba05bb0a9c2dd1f1852a994ab80d722730d282ae44"}
|
||||||
{"timestamp": "2026-07-10T07:21:22Z", "trace_id": "1fd5d347-f21c-4370-a60d-30b11fd8c53e", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 51212, "retry_count": 0, "input_tokens": 362, "output_tokens": 59, "total_tokens": 421, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa", "output_hash": "280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e"}
|
{"timestamp": "2026-07-10T07:21:22Z", "trace_id": "1fd5d347-f21c-4370-a60d-30b11fd8c53e", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 51212, "retry_count": 0, "input_tokens": 362, "output_tokens": 59, "total_tokens": 421, "cost_estimate": 0.0, "cost_source": "ollama_local_real_tokens", "synthesis_mode": "model", "hallucination_signals": 0, "alerts": [], "input_hash": "8aaecd06d85c7f743d3545e7b865f3053c647591f95919c1c0b003046d4757aa", "output_hash": "280cadd0be725e6496a8614b12a98836bedb5c8a38fc6b2a8afe5f44b237158e"}
|
||||||
|
{"timestamp": "2026-07-10T14:25:28Z", "trace_id": "1c93ce8a-db76-4573-b49f-07f9fc408056", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "degraded", "exit_code": 0, "latency_ms": 55732, "input_tokens": 144, "output_tokens": 943, "total_tokens": 1087, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "6a4afba59fa567c089a84e6e933c8665380c63c93f00de70e1cba2a26512f623", "output_hash": "317d789d9c23693bb1dda981d9f75e1eff9ca8fa1aa9a722115c6fef78caad23"}
|
||||||
|
{"timestamp": "2026-07-10T14:27:47Z", "trace_id": "6700500f-3f3d-40ab-92b1-70315fc42ea5", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "degraded", "exit_code": 0, "latency_ms": 51117, "input_tokens": 143, "output_tokens": 450, "total_tokens": 593, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "491375254fe83e91fad084ef998ddda780654f1ef921a2cd9148466a74fb1c9a", "output_hash": "642e21a39cd734fd6667a540da58d494fe3e3a2d4a2297b49334dc5536834c77"}
|
||||||
|
{"timestamp": "2026-07-10T14:33:48Z", "trace_id": "21b6f387-84ad-4856-a8da-102bd70c037a", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "success", "exit_code": 0, "latency_ms": 44058, "input_tokens": 142, "output_tokens": 418, "total_tokens": 560, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "5e9f6afb8b00b1c071e64b07ffa8ee66d67f298d65a0b6285a2f3ad92010aa56", "output_hash": "e08f4d05c9a0f21dbdc0edc3d759d9324cbd6ca23d3ab958edac1305ecbfeb17"}
|
||||||
|
{"timestamp": "2026-07-11T03:05:27Z", "trace_id": "832cc182-7bb8-4666-9bbc-c077a943e7f9", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "success", "exit_code": 0, "latency_ms": 85641, "input_tokens": 127, "output_tokens": 620, "total_tokens": 747, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a", "output_hash": "d94f7cb51d952fcaffb585e76c16542aba2f774d64c6d270eab32e7888eccc40"}
|
||||||
|
{"timestamp": "2026-07-11T03:07:54Z", "trace_id": "3fc2c4a0-32ab-4be3-b12f-ca83a65869c7", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "success", "exit_code": 0, "latency_ms": 85595, "input_tokens": 127, "output_tokens": 471, "total_tokens": 598, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "d2f690b77d00aa01559991486f7825c7a1ea402429c5638e8dbf2a40e7b6eb9a", "output_hash": "fd6094f85e823a0be31d54bc5dbecf5e174275ad8b85ca2aa56f58658789e7a3"}
|
||||||
|
{"timestamp": "2026-07-11T03:15:44Z", "trace_id": "d1f5f078-63dc-4f21-a4f7-c0ccab19bc3d", "harness": "H6-agentops", "agent": "goal.orchestrator", "step": "local-worker-cloud-reviewer", "status": "success", "exit_code": 0, "latency_ms": 140071, "input_tokens": 2406, "output_tokens": 1400, "total_tokens": 3806, "cost_estimate": 0.0, "cost_source": "provider_usage_logs", "input_hash": "63073e9ea949155b9fc8db84dca22a3b8a635b11ab60e45b00c5914c842473fa", "output_hash": "8367afe050a5086cac52162ee740dc4f68949e6901538d86f49802ad069e1e54"}
|
||||||
|
|||||||
@@ -13,3 +13,34 @@
|
|||||||
{"timestamp": "2026-07-10T06:20:20Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 511, "output_tokens": 288, "total_tokens": 799, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 31437, "status": "success"}
|
{"timestamp": "2026-07-10T06:20:20Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 511, "output_tokens": 288, "total_tokens": 799, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 31437, "status": "success"}
|
||||||
{"timestamp": "2026-07-10T07:20:36Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 207, "output_tokens": 2, "total_tokens": 209, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 5868, "status": "success"}
|
{"timestamp": "2026-07-10T07:20:36Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 207, "output_tokens": 2, "total_tokens": 209, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 5868, "status": "success"}
|
||||||
{"timestamp": "2026-07-10T07:21:21Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 362, "output_tokens": 59, "total_tokens": 421, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 4829, "status": "success"}
|
{"timestamp": "2026-07-10T07:21:21Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 362, "output_tokens": 59, "total_tokens": 421, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 4829, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:38:12Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 206, "output_tokens": 2, "total_tokens": 208, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 6915, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:38:31Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 213, "output_tokens": 2, "total_tokens": 215, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1525, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:39:55Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 213, "output_tokens": 2, "total_tokens": 215, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 479, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:40:24Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 424, "output_tokens": 521, "total_tokens": 945, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 28692, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:45:51Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 256, "output_tokens": 2, "total_tokens": 258, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 4818, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:46:14Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 535, "output_tokens": 448, "total_tokens": 983, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 23352, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:48:33Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 214, "output_tokens": 2, "total_tokens": 216, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1435, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:48:51Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 394, "output_tokens": 334, "total_tokens": 728, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 18226, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:49:39Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 211, "output_tokens": 2, "total_tokens": 213, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1403, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:49:57Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 394, "output_tokens": 335, "total_tokens": 729, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 18167, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:51:05Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 210, "output_tokens": 2, "total_tokens": 212, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1407, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T08:51:25Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 519, "output_tokens": 339, "total_tokens": 858, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 19083, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:24:40Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 232, "output_tokens": 2, "total_tokens": 234, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 7351, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:25:27Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 144, "output_tokens": 943, "total_tokens": 1087, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 47635, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:27:02Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 231, "output_tokens": 2, "total_tokens": 233, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 2816, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:27:46Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 143, "output_tokens": 450, "total_tokens": 593, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 43467, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:33:09Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 230, "output_tokens": 2, "total_tokens": 232, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 5224, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:33:34Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 142, "output_tokens": 418, "total_tokens": 560, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 24025, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T14:59:35Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 2544, "output_tokens": 2, "total_tokens": 2546, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 19119, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T15:07:29Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 2494, "output_tokens": 2, "total_tokens": 2496, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 18212, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T15:11:09Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 207, "output_tokens": 2, "total_tokens": 209, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1383, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T15:11:50Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 540, "output_tokens": 202, "total_tokens": 742, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 11855, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T15:12:20Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 212, "output_tokens": 2, "total_tokens": 214, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1394, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-10T15:13:05Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 595, "output_tokens": 463, "total_tokens": 1058, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 32615, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T02:54:27Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 207, "output_tokens": 2, "total_tokens": 209, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 6819, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T02:54:39Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 531, "output_tokens": 172, "total_tokens": 703, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 10793, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T02:55:20Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "classify", "role": "classify", "input_tokens": 218, "output_tokens": 2, "total_tokens": 220, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 1428, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T02:55:45Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 608, "output_tokens": 472, "total_tokens": 1080, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 25130, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T03:04:43Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 127, "output_tokens": 620, "total_tokens": 747, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 41710, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T03:07:06Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 127, "output_tokens": 471, "total_tokens": 598, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 37299, "status": "success"}
|
||||||
|
{"timestamp": "2026-07-11T03:14:47Z", "harness": "L5-provider-telemetry", "provider": "ollama", "model": "ornith:9b", "run_id": "adhoc", "step": "generate", "role": "generate", "input_tokens": 2406, "output_tokens": 1400, "total_tokens": 3806, "cost_usd": 0.0, "cost_source": "ollama_local_real_tokens", "latency_ms": 82969, "status": "success"}
|
||||||
|
|||||||
@@ -6,417 +6,417 @@ AI-SDLC (AI Software Development Life Cycle) - Applying AI to the software devel
|
|||||||
> [Dùng CASAN để làm dự án — giải thích thực tế, dễ hiểu](docs/guides/CASAN_USING_FOR_REAL_PROJECTS_VI.md).
|
> [Dùng CASAN để làm dự án — giải thích thực tế, dễ hiểu](docs/guides/CASAN_USING_FOR_REAL_PROJECTS_VI.md).
|
||||||
> CASAN core không phụ thuộc Codex, VS Code hay Claude Code; các agent được mô tả
|
> CASAN core không phụ thuộc Codex, VS Code hay Claude Code; các agent được mô tả
|
||||||
> dưới đây là flow demo/legacy có thể đặt phía sau CASAN governance.
|
> dưới đây là flow demo/legacy có thể đặt phía sau CASAN governance.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Project Objectives](#project-objectives)
|
- [Project Objectives](#project-objectives)
|
||||||
- [Dùng CASAN cho dự án thực tế](docs/guides/CASAN_USING_FOR_REAL_PROJECTS_VI.md)
|
- [Dùng CASAN cho dự án thực tế](docs/guides/CASAN_USING_FOR_REAL_PROJECTS_VI.md)
|
||||||
- [Requirements](#requirements)
|
- [Requirements](#requirements)
|
||||||
- [Input for Flow](#input-for-flow)
|
- [Input for Flow](#input-for-flow)
|
||||||
- [Output for FLow](#output-for-flow)
|
- [Output for FLow](#output-for-flow)
|
||||||
- [Full AI-SDLC Flow](#full-ai-sdlc-flow)
|
- [Full AI-SDLC Flow](#full-ai-sdlc-flow)
|
||||||
- [Flow Steps](#flow-steps)
|
- [Flow Steps](#flow-steps)
|
||||||
- [Flow Diagram](#flow-diagram)
|
- [Flow Diagram](#flow-diagram)
|
||||||
- [Legend](#legend)
|
- [Legend](#legend)
|
||||||
- [Agents](#agents)
|
- [Agents](#agents)
|
||||||
- [Spec-Kit Agents (Core Flow)](#spec-kit-agents-core-flow)
|
- [Spec-Kit Agents (Core Flow)](#spec-kit-agents-core-flow)
|
||||||
- [FPT-Defined Agents (IPA Gen + Review + Orchestrator + Test)](#fpt-defined-agents-ipa-gen--review--orchestrator--test)
|
- [FPT-Defined Agents (IPA Gen + Review + Orchestrator + Test)](#fpt-defined-agents-ipa-gen--review--orchestrator--test)
|
||||||
- [AI-SDLC Usage Guide](#ai-sdlc-usage-guide)
|
- [AI-SDLC Usage Guide](#ai-sdlc-usage-guide)
|
||||||
- [Directory Structure](#directory-structure)
|
- [Directory Structure](#directory-structure)
|
||||||
- [Directory Details](#directory-details)
|
- [Directory Details](#directory-details)
|
||||||
- [FPT Deliverable List for NES](#fpt-deliverable-list-for-nes)
|
- [FPT Deliverable List for NES](#fpt-deliverable-list-for-nes)
|
||||||
- [A. Development Deliverables](#a-development-deliverables)
|
- [A. Development Deliverables](#a-development-deliverables)
|
||||||
- [B. Process Records (Required)](#b-process-records-required)
|
- [B. Process Records (Required)](#b-process-records-required)
|
||||||
- [C. Process Design Document](#c-process-design-document)
|
- [C. Process Design Document](#c-process-design-document)
|
||||||
- [D. Specification Files](#d-specification-files)
|
- [D. Specification Files](#d-specification-files)
|
||||||
- [E. Review & Insights](#e-review--insights)
|
- [E. Review & Insights](#e-review--insights)
|
||||||
- [Optional Deliverables](#optional-deliverables)
|
- [Optional Deliverables](#optional-deliverables)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
|
|
||||||
## Project Objectives
|
## Project Objectives
|
||||||
|
|
||||||
Apply AI to the SDLC process to automate and optimize the creation of software products from initial requirements to complete source code.
|
Apply AI to the SDLC process to automate and optimize the creation of software products from initial requirements to complete source code.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- **Flow + Prompt + Template**: **Spec-Kit**
|
- **Flow + Prompt + Template**: **Spec-Kit**
|
||||||
- **AI Tool của flow demo/legacy**: **Claude Code** là assistant chính; CASAN
|
- **AI Tool của flow demo/legacy**: **Claude Code** là assistant chính; CASAN
|
||||||
harness và Control Panel có thể chạy độc lập bằng browser/CLI/CI hoặc dùng model
|
harness và Control Panel có thể chạy độc lập bằng browser/CLI/CI hoặc dùng model
|
||||||
local/OmniRoute.
|
local/OmniRoute.
|
||||||
- **AI-SDLC**: AI-integrated SDLC process **Spec-Kit Modified** (Add IPA Gen + Review Loop + Orchestrator)
|
- **AI-SDLC**: AI-integrated SDLC process **Spec-Kit Modified** (Add IPA Gen + Review Loop + Orchestrator)
|
||||||
- **IPA Template**: Following IPA (Information-technology Promotion Agency) template standards
|
- **IPA Template**: Following IPA (Information-technology Promotion Agency) template standards
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Input for Flow
|
## Input for Flow
|
||||||
|
|
||||||
- `apps/okr/domain/input/okr-requirement.md` — Raw requirements from customers
|
- `apps/okr/domain/input/okr-requirement.md` — Raw requirements from customers
|
||||||
- `docs/technical_architecture.md` — Technical stack decisions and constraints
|
- `docs/technical_architecture.md` — Technical stack decisions and constraints
|
||||||
- `apps/okr/domain/input/change-request/` — Change requests (e.g., `change-0406.md`)
|
- `apps/okr/domain/input/change-request/` — Change requests (e.g., `change-0406.md`)
|
||||||
|
|
||||||
## Output for FLow
|
## Output for FLow
|
||||||
|
|
||||||
| Output | Location | Description |
|
| Output | Location | Description |
|
||||||
|--------|----------|-------------|
|
|--------|----------|-------------|
|
||||||
| **IPA Docs** (SRS, BD, DD, Test Cases, Test Reports) | `docs/output/ipa-docs/` | Design documents generated by IPA agents (organized in `srs/`, `bd/`, `dd/`, `testcase/`, `testreport/` subdirectories) |
|
| **IPA Docs** (SRS, BD, DD, Test Cases, Test Reports) | `docs/output/ipa-docs/` | Design documents generated by IPA agents (organized in `srs/`, `bd/`, `dd/`, `testcase/`, `testreport/` subdirectories) |
|
||||||
| **AI Agent Logs** | `docs/output/output_logs/` | Execution logs from AI agents |
|
| **AI Agent Logs** | `docs/output/output_logs/` | Execution logs from AI agents |
|
||||||
| **SRS-Systems** | `docs/output/srs-systems/` | System-wide SRS (generated once during input clarification phase, not part of the main flow steps) |
|
| **SRS-Systems** | `docs/output/srs-systems/` | System-wide SRS (generated once during input clarification phase, not part of the main flow steps) |
|
||||||
| **Spec-Kit Artifacts** | `specs/[FEATURE_NAME]/` | Feature artifacts generated by Spec-Kit agents (`spec.md`, `plan.md`, `tasks.md`, contracts, checklists) |
|
| **Spec-Kit Artifacts** | `specs/[FEATURE_NAME]/` | Feature artifacts generated by Spec-Kit agents (`spec.md`, `plan.md`, `tasks.md`, contracts, checklists) |
|
||||||
| **Source Code** | `backend/` + `frontend/` | Application source code (NestJS backend + React frontend) |
|
| **Source Code** | `backend/` + `frontend/` | Application source code (NestJS backend + React frontend) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Full AI-SDLC Flow
|
## Full AI-SDLC Flow
|
||||||
|
|
||||||
The entire flow is orchestrated by **`okr.bossbuiltin`**, which executes all steps automatically from start to finish.
|
The entire flow is orchestrated by **`okr.bossbuiltin`**, which executes all steps automatically from start to finish.
|
||||||
|
|
||||||
### Flow Steps
|
### Flow Steps
|
||||||
|
|
||||||
| Step | Agent | Output | Category |
|
| Step | Agent | Output | Category |
|
||||||
|------|-------|--------|----------|
|
|------|-------|--------|----------|
|
||||||
| **STEP 1** | `okr.srs` | SRS (ソフトウェア要件定義書) | 📄 IPA Doc Gen |
|
| **STEP 1** | `okr.srs` | SRS (ソフトウェア要件定義書) | 📄 IPA Doc Gen |
|
||||||
| **STEP 2** | `okr.bd` | BD — 外部設計 (Basic Design) | 📄 IPA Doc Gen |
|
| **STEP 2** | `okr.bd` | BD — 外部設計 (Basic Design) | 📄 IPA Doc Gen |
|
||||||
| **STEP 3** | `speckit.specify` | `spec.md` | 📝 Spec-Kit |
|
| **STEP 3** | `speckit.specify` | `spec.md` | 📝 Spec-Kit |
|
||||||
| **STEP 4** | `speckit.clarify` | Resolve ambiguities (NO PAUSE) | 📝 Spec-Kit |
|
| **STEP 4** | `speckit.clarify` | Resolve ambiguities (NO PAUSE) | 📝 Spec-Kit |
|
||||||
| **STEP 5** | `okr.reviewspec` 🔄 | Spec review (auto-retry) | 🔍 Agent Review |
|
| **STEP 5** | `okr.reviewspec` 🔄 | Spec review (auto-retry) | 🔍 Agent Review |
|
||||||
| **STEP 6** | `speckit.plan` | `plan.md` + data-model + contracts | 📝 Spec-Kit |
|
| **STEP 6** | `speckit.plan` | `plan.md` + data-model + contracts | 📝 Spec-Kit |
|
||||||
| **STEP 7** | `okr.reviewplan` 🔄 | Plan review (auto-retry) | 🔍 Agent Review |
|
| **STEP 7** | `okr.reviewplan` 🔄 | Plan review (auto-retry) | 🔍 Agent Review |
|
||||||
| **STEP 8** | `okr.dd` | DD — 内部設計 (Detail Design) | 📄 IPA Doc Gen |
|
| **STEP 8** | `okr.dd` | DD — 内部設計 (Detail Design) | 📄 IPA Doc Gen |
|
||||||
| **STEP 8b** | `okr.testkit` | Test cases (`gen-testcases`) | 🧪 Test |
|
| **STEP 8b** | `okr.testkit` | Test cases (`gen-testcases`) | 🧪 Test |
|
||||||
| **STEP 9** | `speckit.tasks` | `tasks.md` | 📝 Spec-Kit |
|
| **STEP 9** | `speckit.tasks` | `tasks.md` | 📝 Spec-Kit |
|
||||||
| **STEP 10** | `speckit.implement` 🔄 | Implementation + build & fix (auto-retry) | 📝 Spec-Kit |
|
| **STEP 10** | `speckit.implement` 🔄 | Implementation + build & fix (auto-retry) | 📝 Spec-Kit |
|
||||||
| **STEP 11** | `okr.reviewcode` 🔄 | Code review + DB data check (auto-retry) | 🔍 Agent Review |
|
| **STEP 11** | `okr.reviewcode` 🔄 | Code review + DB data check (auto-retry) | 🔍 Agent Review |
|
||||||
| **STEP 12** | `okr.testkit` 🔄 | Run tests (`run-tests`) — BACK-TO-PLAN on fail | 🧪 Test |
|
| **STEP 12** | `okr.testkit` 🔄 | Run tests (`run-tests`) — BACK-TO-PLAN on fail | 🧪 Test |
|
||||||
| **STEP 13** | Boss (direct) | Build BE + connect DB + Build FE + Launch UI → `open_browser_page` | 🚀 Deploy |
|
| **STEP 13** | Boss (direct) | Build BE + connect DB + Build FE + Launch UI → `open_browser_page` | 🚀 Deploy |
|
||||||
|
|
||||||
### Flow Diagram
|
### Flow Diagram
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
│ INPUT │
|
│ INPUT │
|
||||||
│ [ Raw Requirement ] [ Clear Requirement ] [ Tech Stack ] │
|
│ [ Raw Requirement ] [ Clear Requirement ] [ Tech Stack ] │
|
||||||
└──────────────────────────────┬──────────────────────────────┘
|
└──────────────────────────────┬──────────────────────────────┘
|
||||||
│
|
│
|
||||||
┌────────────────────┴──── (one-time, pre-flow) ────┐
|
┌────────────────────┴──── (one-time, pre-flow) ────┐
|
||||||
│ okr.srsallsystem → docs/output/srs-systems/ │
|
│ okr.srsallsystem → docs/output/srs-systems/ │
|
||||||
└────────────────────┬──────────────────────────────┘
|
└────────────────────┬──────────────────────────────┘
|
||||||
│
|
│
|
||||||
╔════════════════════════════╧══════════════════════════════════╗
|
╔════════════════════════════╧══════════════════════════════════╗
|
||||||
║ okr.bossbuiltin (Orchestrator) ║
|
║ okr.bossbuiltin (Orchestrator) ║
|
||||||
║ ║
|
║ ║
|
||||||
║ ┌─── IPA Doc Gen ───────────────────────────────────────┐ ║
|
║ ┌─── IPA Doc Gen ───────────────────────────────────────┐ ║
|
||||||
║ │ STEP 1 okr.srs → SRS │ ║
|
║ │ STEP 1 okr.srs → SRS │ ║
|
||||||
║ │ STEP 2 okr.bd → BD (外部設計) │ ║
|
║ │ STEP 2 okr.bd → BD (外部設計) │ ║
|
||||||
║ └───────────────────────────────────────────────────────┘ ║
|
║ └───────────────────────────────────────────────────────┘ ║
|
||||||
║ │ ║
|
║ │ ║
|
||||||
║ ▼ ║
|
║ ▼ ║
|
||||||
║ ┌─── Spec-Kit + Review Loop ────────────────────────────┐ ║
|
║ ┌─── Spec-Kit + Review Loop ────────────────────────────┐ ║
|
||||||
║ │ STEP 3 speckit.specify → spec.md │ ║
|
║ │ STEP 3 speckit.specify → spec.md │ ║
|
||||||
║ │ STEP 4 speckit.clarify → resolve ambiguities │ ║
|
║ │ STEP 4 speckit.clarify → resolve ambiguities │ ║
|
||||||
║ │ STEP 5 okr.reviewspec 🔄 auto-retry │ ║
|
║ │ STEP 5 okr.reviewspec 🔄 auto-retry │ ║
|
||||||
║ │ │ │ ║
|
║ │ │ │ ║
|
||||||
║ │ ▼ │ ║
|
║ │ ▼ │ ║
|
||||||
║ │ STEP 6 speckit.plan → plan.md + data-model │ ║
|
║ │ STEP 6 speckit.plan → plan.md + data-model │ ║
|
||||||
║ │ STEP 7 okr.reviewplan 🔄 auto-retry │ ║
|
║ │ STEP 7 okr.reviewplan 🔄 auto-retry │ ║
|
||||||
║ └───────────────────────────────────────────────────────┘ ║
|
║ └───────────────────────────────────────────────────────┘ ║
|
||||||
║ │ ║
|
║ │ ║
|
||||||
║ ▼ ║
|
║ ▼ ║
|
||||||
║ ┌─── IPA Doc Gen (Detail) ──────────────────────────────┐ ║
|
║ ┌─── IPA Doc Gen (Detail) ──────────────────────────────┐ ║
|
||||||
║ │ STEP 8 okr.dd → DD (内部設計) │ ║
|
║ │ STEP 8 okr.dd → DD (内部設計) │ ║
|
||||||
║ │ STEP 8b okr.testkit → gen-testcases │ ║
|
║ │ STEP 8b okr.testkit → gen-testcases │ ║
|
||||||
║ └───────────────────────────────────────────────────────┘ ║
|
║ └───────────────────────────────────────────────────────┘ ║
|
||||||
║ │ ║
|
║ │ ║
|
||||||
║ ▼ ║
|
║ ▼ ║
|
||||||
║ ┌─── Implementation ───────────────────────────────────┐ ║
|
║ ┌─── Implementation ───────────────────────────────────┐ ║
|
||||||
║ │ STEP 9 speckit.tasks → tasks.md │ ║
|
║ │ STEP 9 speckit.tasks → tasks.md │ ║
|
||||||
║ │ STEP 10 speckit.implement 🔄 build & fix │ ║
|
║ │ STEP 10 speckit.implement 🔄 build & fix │ ║
|
||||||
║ │ STEP 11 okr.reviewcode 🔄 code review │ ║
|
║ │ STEP 11 okr.reviewcode 🔄 code review │ ║
|
||||||
║ │ STEP 12 okr.testkit 🔄 run-tests │ ║
|
║ │ STEP 12 okr.testkit 🔄 run-tests │ ║
|
||||||
║ │ (BACK-TO-PLAN on fail) │ ║
|
║ │ (BACK-TO-PLAN on fail) │ ║
|
||||||
║ └──────────────────────────────────────────────────────┘ ║
|
║ └──────────────────────────────────────────────────────┘ ║
|
||||||
║ │ ║
|
║ │ ║
|
||||||
║ ▼ ║
|
║ ▼ ║
|
||||||
║ ┌─── Deploy ───────────────────────────────────────────┐ ║
|
║ ┌─── Deploy ───────────────────────────────────────────┐ ║
|
||||||
║ │ STEP 13 Boss → build BE + DB + FE → open_browser │ ║
|
║ │ STEP 13 Boss → build BE + DB + FE → open_browser │ ║
|
||||||
║ └──────────────────────────────────────────────────────┘ ║
|
║ └──────────────────────────────────────────────────────┘ ║
|
||||||
║ ║
|
║ ║
|
||||||
╚══════════════════════════════════════════════════════════════╝
|
╚══════════════════════════════════════════════════════════════╝
|
||||||
```
|
```
|
||||||
|
|
||||||
### Legend
|
### Legend
|
||||||
|
|
||||||
| Symbol | Meaning |
|
| Symbol | Meaning |
|
||||||
|--------|---------|
|
|--------|---------|
|
||||||
| 🔄 | Auto-retry loop (agent retries until pass) |
|
| 🔄 | Auto-retry loop (agent retries until pass) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Agents
|
## Agents
|
||||||
|
|
||||||
### Spec-Kit Agents (Core Flow)
|
### Spec-Kit Agents (Core Flow)
|
||||||
|
|
||||||
| Agent | Description |
|
| Agent | Description |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
| `speckit.constitution` | Define project principles and constraints |
|
| `speckit.constitution` | Define project principles and constraints |
|
||||||
| `speckit.specify` | Convert requirements into feature specification (`spec.md`) |
|
| `speckit.specify` | Convert requirements into feature specification (`spec.md`) |
|
||||||
| `speckit.clarify` | Resolve ambiguous requirements (no pause) |
|
| `speckit.clarify` | Resolve ambiguous requirements (no pause) |
|
||||||
| `speckit.plan` | Create implementation plan (`plan.md` + data-model + contracts) |
|
| `speckit.plan` | Create implementation plan (`plan.md` + data-model + contracts) |
|
||||||
| `speckit.tasks` | Generate task list (`tasks.md`) |
|
| `speckit.tasks` | Generate task list (`tasks.md`) |
|
||||||
| `speckit.implement` | Implementation with auto build & fix |
|
| `speckit.implement` | Implementation with auto build & fix |
|
||||||
| `speckit.analyze` | Cross-artifact consistency and quality analysis |
|
| `speckit.analyze` | Cross-artifact consistency and quality analysis |
|
||||||
| `speckit.checklist` | Generate custom quality checklists |
|
| `speckit.checklist` | Generate custom quality checklists |
|
||||||
| `speckit.taskstoissues` | Convert tasks to GitHub issues |
|
| `speckit.taskstoissues` | Convert tasks to GitHub issues |
|
||||||
|
|
||||||
### FPT-Defined Agents (IPA Gen + Review + Orchestrator + Test)
|
### FPT-Defined Agents (IPA Gen + Review + Orchestrator + Test)
|
||||||
|
|
||||||
| Agent | Description |
|
| Agent | Description |
|
||||||
|-------|-------------|
|
|-------|-------------|
|
||||||
| `okr.bossbuiltin` | **Orchestrator** — runs all 13 steps end-to-end automatically |
|
| `okr.bossbuiltin` | **Orchestrator** — runs all 13 steps end-to-end automatically |
|
||||||
| `okr.srs` | Generate SRS (ソフトウェア要件定義書) per module → `docs/output/ipa-docs/` |
|
| `okr.srs` | Generate SRS (ソフトウェア要件定義書) per module → `docs/output/ipa-docs/` |
|
||||||
| `okr.bd` | Generate BD / 外部設計 (Basic Design) per module → `docs/output/ipa-docs/` |
|
| `okr.bd` | Generate BD / 外部設計 (Basic Design) per module → `docs/output/ipa-docs/` |
|
||||||
| `okr.dd` | Generate DD / 内部設計 (Detail Design) per module → `docs/output/ipa-docs/` |
|
| `okr.dd` | Generate DD / 内部設計 (Detail Design) per module → `docs/output/ipa-docs/` |
|
||||||
| `okr.srsallsystem` | Generate system-wide SRS (one-time, pre-flow) → `docs/output/srs-systems/` |
|
| `okr.srsallsystem` | Generate system-wide SRS (one-time, pre-flow) → `docs/output/srs-systems/` |
|
||||||
| `okr.reviewspec` | **Review** — validate `spec.md` quality and completeness |
|
| `okr.reviewspec` | **Review** — validate `spec.md` quality and completeness |
|
||||||
| `okr.reviewplan` | **Review** — validate `plan.md` conformance to spec |
|
| `okr.reviewplan` | **Review** — validate `plan.md` conformance to spec |
|
||||||
| `okr.reviewcode` | **Review** — code review + DB data check |
|
| `okr.reviewcode` | **Review** — code review + DB data check |
|
||||||
| `okr.testkit` | **Test** — generate test cases from SRS + BD + DD; run automated tests |
|
| `okr.testkit` | **Test** — generate test cases from SRS + BD + DD; run automated tests |
|
||||||
| `Flow-Agent` | General-purpose flow agent |
|
| `Flow-Agent` | General-purpose flow agent |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## AI-SDLC Usage Guide
|
## AI-SDLC Usage Guide
|
||||||
|
|
||||||
1. **Prepare Input**: Place raw requirements in `apps/okr/domain/input/okr-requirement.md` and tech stack in `docs/technical_architecture.md`
|
1. **Prepare Input**: Place raw requirements in `apps/okr/domain/input/okr-requirement.md` and tech stack in `docs/technical_architecture.md`
|
||||||
2. **Configuration**: Set up the project constitution first, keep specifications focused on what and why, and only decide technical stack where the input explicitly requires it
|
2. **Configuration**: Set up the project constitution first, keep specifications focused on what and why, and only decide technical stack where the input explicitly requires it
|
||||||
3. **(One-time) Generate System SRS**: Run `okr.srsallsystem` to generate system-wide SRS → `docs/output/srs-systems/`
|
3. **(One-time) Generate System SRS**: Run `okr.srsallsystem` to generate system-wide SRS → `docs/output/srs-systems/`
|
||||||
4. **Run AI Flow**: Invoke `okr.bossbuiltin` to execute the full 13-step flow automatically, with strict TDD enforced across specification, planning, task generation, and implementation
|
4. **Run AI Flow**: Invoke `okr.bossbuiltin` to execute the full 13-step flow automatically, with strict TDD enforced across specification, planning, task generation, and implementation
|
||||||
5. **Output**:
|
5. **Output**:
|
||||||
- `docs/output/ipa-docs/` — IPA design documents (SRS, BD, DD, Test Cases)
|
- `docs/output/ipa-docs/` — IPA design documents (SRS, BD, DD, Test Cases)
|
||||||
- `docs/output/output_logs/` — AI agent execution logs
|
- `docs/output/output_logs/` — AI agent execution logs
|
||||||
- `docs/output/srs-systems/` — System-wide SRS (generated once)
|
- `docs/output/srs-systems/` — System-wide SRS (generated once)
|
||||||
- `specs/[FEATURE_NAME]/` — Spec-Kit artifacts (`spec.md`, `plan.md`, `tasks.md`, etc.)
|
- `specs/[FEATURE_NAME]/` — Spec-Kit artifacts (`spec.md`, `plan.md`, `tasks.md`, etc.)
|
||||||
- `backend/` + `frontend/` — Source code (NestJS backend + React frontend)
|
- `backend/` + `frontend/` — Source code (NestJS backend + React frontend)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
├── .claude/
|
├── .claude/
|
||||||
│ ├── agents/ # All agent definitions (subagents)
|
│ ├── agents/ # All agent definitions (subagents)
|
||||||
│ │ ├── okr.bossbuiltin.md # Boss orchestrator agent
|
│ │ ├── okr.bossbuiltin.md # Boss orchestrator agent
|
||||||
│ │ ├── speckit.*.md # Spec-Kit agents (specify, clarify, plan, tasks, implement, analyze, checklist, taskstoissues)
|
│ │ ├── speckit.*.md # Spec-Kit agents (specify, clarify, plan, tasks, implement, analyze, checklist, taskstoissues)
|
||||||
│ │ ├── okr.*.md # FPT-defined agents (srs, bd, dd, reviewspec, reviewplan, reviewcode, srsallsystem, testkit)
|
│ │ ├── okr.*.md # FPT-defined agents (srs, bd, dd, reviewspec, reviewplan, reviewcode, srsallsystem, testkit)
|
||||||
│ │ ├── protocols/ # Shared protocols (auto-resolve, gate-retry, logging, pipeline-context, etc.)
|
│ │ ├── protocols/ # Shared protocols (auto-resolve, gate-retry, logging, pipeline-context, etc.)
|
||||||
│ │ ├── steps/ # Step definitions for orchestrator (steps-01-04, steps-05-07, etc.)
|
│ │ ├── steps/ # Step definitions for orchestrator (steps-01-04, steps-05-07, etc.)
|
||||||
│ │ └── templates/ # Agent output templates (pipeline-completion, report-templates)
|
│ │ └── templates/ # Agent output templates (pipeline-completion, report-templates)
|
||||||
│ └── commands/ # Claude Code slash commands
|
│ └── commands/ # Claude Code slash commands
|
||||||
│ ├── okr.bossbuiltin.md # Run full pipeline (/okr.bossbuiltin)
|
│ ├── okr.bossbuiltin.md # Run full pipeline (/okr.bossbuiltin)
|
||||||
│ ├── speckit.*.md # Spec-Kit slash commands
|
│ ├── speckit.*.md # Spec-Kit slash commands
|
||||||
│ └── okr.*.md # OKR agent slash commands
|
│ └── okr.*.md # OKR agent slash commands
|
||||||
│
|
│
|
||||||
├── CLAUDE.md # Global Claude Code project instructions
|
├── CLAUDE.md # Global Claude Code project instructions
|
||||||
│
|
│
|
||||||
├── .specify/ # SpecKit configuration and templates
|
├── .specify/ # SpecKit configuration and templates
|
||||||
│ ├── init-options.json # Initialization options
|
│ ├── init-options.json # Initialization options
|
||||||
│ ├── memory/
|
│ ├── memory/
|
||||||
│ │ └── constitution.md # Project-wide principles and constraints
|
│ │ └── constitution.md # Project-wide principles and constraints
|
||||||
│ ├── scripts/ # Utility scripts
|
│ ├── scripts/ # Utility scripts
|
||||||
│ │ ├── bash/ # Bash scripts
|
│ │ ├── bash/ # Bash scripts
|
||||||
│ │ └── powershell/ # PowerShell scripts
|
│ │ └── powershell/ # PowerShell scripts
|
||||||
│ └── templates/
|
│ └── templates/
|
||||||
│ ├── agent-file-template.md # Agent definition template
|
│ ├── agent-file-template.md # Agent definition template
|
||||||
│ ├── checklist-template.md # Quality checklist template
|
│ ├── checklist-template.md # Quality checklist template
|
||||||
│ ├── constitution-template.md
|
│ ├── constitution-template.md
|
||||||
│ ├── spec-template.md # Spec-Kit templates
|
│ ├── spec-template.md # Spec-Kit templates
|
||||||
│ ├── plan-template.md
|
│ ├── plan-template.md
|
||||||
│ ├── tasks-template.md
|
│ ├── tasks-template.md
|
||||||
│ ├── srs-template.md # IPA templates (SRS, BD, DD)
|
│ ├── srs-template.md # IPA templates (SRS, BD, DD)
|
||||||
│ ├── bd-ipa-template.md
|
│ ├── bd-ipa-template.md
|
||||||
│ └── dd-ipa-template.md
|
│ └── dd-ipa-template.md
|
||||||
│
|
│
|
||||||
├── docs/
|
├── docs/
|
||||||
│ ├── input/ # Input for the entire AI-SDLC flow
|
│ ├── input/ # Input for the entire AI-SDLC flow
|
||||||
│ ├── change-request/ # Change requests
|
│ ├── change-request/ # Change requests
|
||||||
│ │ └── okr-requirement.md # Raw requirements from customers
|
│ │ └── okr-requirement.md # Raw requirements from customers
|
||||||
│ ├── technical_architecture.md # Technical stack decisions and constraints
|
│ ├── technical_architecture.md # Technical stack decisions and constraints
|
||||||
│ └── output/ # Output of the AI-SDLC process
|
│ └── output/ # Output of the AI-SDLC process
|
||||||
│ ├── ipa-docs/ # IPA documents
|
│ ├── ipa-docs/ # IPA documents
|
||||||
│ │ ├── srs/ # SRS documents per module
|
│ │ ├── srs/ # SRS documents per module
|
||||||
│ │ ├── bd/ # BD documents per module
|
│ │ ├── bd/ # BD documents per module
|
||||||
│ │ ├── dd/ # DD documents per module
|
│ │ ├── dd/ # DD documents per module
|
||||||
│ │ ├── testcase/ # Test case documents per module
|
│ │ ├── testcase/ # Test case documents per module
|
||||||
│ │ └── testreport/ # Test report documents per module
|
│ │ └── testreport/ # Test report documents per module
|
||||||
│ ├── output_logs/ # AI agent execution logs (per feature)
|
│ ├── output_logs/ # AI agent execution logs (per feature)
|
||||||
│ └── srs-systems/ # System-wide SRS (generated once, pre-flow)
|
│ └── srs-systems/ # System-wide SRS (generated once, pre-flow)
|
||||||
│
|
│
|
||||||
├── specs/ # Spec-Kit feature artifacts (per feature)
|
├── specs/ # Spec-Kit feature artifacts (per feature)
|
||||||
│ ├── 001-access-authentication/
|
│ ├── 001-access-authentication/
|
||||||
│ ├── 002-workspace-dashboard/
|
│ ├── 002-workspace-dashboard/
|
||||||
│ ├── 003-objective-keyresult/
|
│ ├── 003-objective-keyresult/
|
||||||
│ └── 004-review-collaboration/
|
│ └── 004-review-collaboration/
|
||||||
│
|
│
|
||||||
├── e2e/ # End-to-end tests (Playwright)
|
├── e2e/ # End-to-end tests (Playwright)
|
||||||
│ └── auth/ # Auth E2E tests
|
│ └── auth/ # Auth E2E tests
|
||||||
│
|
│
|
||||||
├── frontend/ # React + Vite SPA (source code)
|
├── frontend/ # React + Vite SPA (source code)
|
||||||
│
|
│
|
||||||
├── backend/ # NestJS API service (source code)
|
├── backend/ # NestJS API service (source code)
|
||||||
│
|
│
|
||||||
├── docker/ # Docker utilities
|
├── docker/ # Docker utilities
|
||||||
└── docker-compose.yml # Docker Compose orchestration
|
└── docker-compose.yml # Docker Compose orchestration
|
||||||
```
|
```
|
||||||
|
|
||||||
### Directory Details
|
### Directory Details
|
||||||
|
|
||||||
#### `.claude/agents/`
|
#### `.claude/agents/`
|
||||||
Contains all agent definition files used by Claude Code. This includes both **Spec-Kit agents** (core flow: `speckit.specify`, `speckit.clarify`, `speckit.plan`, `speckit.tasks`, `speckit.implement`, plus utility agents `speckit.analyze`, `speckit.checklist`, `speckit.taskstoissues`) and **FPT-defined agents** (`okr.*`):
|
Contains all agent definition files used by Claude Code. This includes both **Spec-Kit agents** (core flow: `speckit.specify`, `speckit.clarify`, `speckit.plan`, `speckit.tasks`, `speckit.implement`, plus utility agents `speckit.analyze`, `speckit.checklist`, `speckit.taskstoissues`) and **FPT-defined agents** (`okr.*`):
|
||||||
- **IPA Doc Gen agents** — `okr.srs`, `okr.bd`, `okr.dd`: generate IPA-standard design documents (SRS, BD, DD) per module, output to `docs/output/ipa-docs/`.
|
- **IPA Doc Gen agents** — `okr.srs`, `okr.bd`, `okr.dd`: generate IPA-standard design documents (SRS, BD, DD) per module, output to `docs/output/ipa-docs/`.
|
||||||
- **Review agents** — `okr.reviewspec`, `okr.reviewplan`, `okr.reviewcode`: validate the quality of Spec-Kit artifacts (`spec.md`, `plan.md`, source code) with auto-retry loops.
|
- **Review agents** — `okr.reviewspec`, `okr.reviewplan`, `okr.reviewcode`: validate the quality of Spec-Kit artifacts (`spec.md`, `plan.md`, source code) with auto-retry loops.
|
||||||
- **Orchestrator** — `okr.bossbuiltin`: runs the full 13-step flow end-to-end automatically.
|
- **Orchestrator** — `okr.bossbuiltin`: runs the full 13-step flow end-to-end automatically.
|
||||||
- **Test agent** — `okr.testkit`: generates test cases from SRS + BD + DD and executes automated tests (Jest / Playwright).
|
- **Test agent** — `okr.testkit`: generates test cases from SRS + BD + DD and executes automated tests (Jest / Playwright).
|
||||||
- **Subdirectories** — `protocols/` (shared protocols for auto-resolve, gate-retry, logging, etc.), `steps/` (orchestrator step definitions), `templates/` (output report templates).
|
- **Subdirectories** — `protocols/` (shared protocols for auto-resolve, gate-retry, logging, etc.), `steps/` (orchestrator step definitions), `templates/` (output report templates).
|
||||||
|
|
||||||
#### `.claude/commands/`
|
#### `.claude/commands/`
|
||||||
Claude Code slash commands that invoke the corresponding agents. Type `/speckit.specify`, `/okr.bossbuiltin`, etc. in Claude Code to trigger the pipeline.
|
Claude Code slash commands that invoke the corresponding agents. Type `/speckit.specify`, `/okr.bossbuiltin`, etc. in Claude Code to trigger the pipeline.
|
||||||
|
|
||||||
#### `.specify/`
|
#### `.specify/`
|
||||||
Spec-Kit configuration directory. Stores project-wide principles, scripts, and all templates:
|
Spec-Kit configuration directory. Stores project-wide principles, scripts, and all templates:
|
||||||
- **`init-options.json`** — Initialization options for Spec-Kit setup.
|
- **`init-options.json`** — Initialization options for Spec-Kit setup.
|
||||||
- **`memory/constitution.md`** — The project constitution: shared principles, constraints, and conventions that apply to every feature across the entire project.
|
- **`memory/constitution.md`** — The project constitution: shared principles, constraints, and conventions that apply to every feature across the entire project.
|
||||||
- **`scripts/`** — Utility scripts in `bash/` and `powershell/` for automation tasks.
|
- **`scripts/`** — Utility scripts in `bash/` and `powershell/` for automation tasks.
|
||||||
- **`templates/`** — Format templates used by agents to generate artifacts. Includes Spec-Kit templates (`spec-template.md`, `plan-template.md`, `tasks-template.md`, `constitution-template.md`, `checklist-template.md`, `agent-file-template.md`) and IPA templates (`srs-template.md`, `bd-ipa-template.md`, `dd-ipa-template.md`).
|
- **`templates/`** — Format templates used by agents to generate artifacts. Includes Spec-Kit templates (`spec-template.md`, `plan-template.md`, `tasks-template.md`, `constitution-template.md`, `checklist-template.md`, `agent-file-template.md`) and IPA templates (`srs-template.md`, `bd-ipa-template.md`, `dd-ipa-template.md`).
|
||||||
|
|
||||||
#### `apps/okr/domain/input/`
|
#### `apps/okr/domain/input/`
|
||||||
Input data for the AI-SDLC flow:
|
Input data for the AI-SDLC flow:
|
||||||
- **`okr-requirement.md`** — Raw requirement documents from the customer.
|
- **`okr-requirement.md`** — Raw requirement documents from the customer.
|
||||||
|
|
||||||
#### `docs/technical_architecture.md`
|
#### `docs/technical_architecture.md`
|
||||||
Technical stack decisions and constraints (languages, frameworks, infrastructure).
|
Technical stack decisions and constraints (languages, frameworks, infrastructure).
|
||||||
|
|
||||||
#### `apps/okr/domain/input/change-request/`
|
#### `apps/okr/domain/input/change-request/`
|
||||||
Change requests applied during the project lifecycle (e.g., `change-0406.md`).
|
Change requests applied during the project lifecycle (e.g., `change-0406.md`).
|
||||||
|
|
||||||
#### `docs/output/`
|
#### `docs/output/`
|
||||||
All artifacts produced by the AI-SDLC process:
|
All artifacts produced by the AI-SDLC process:
|
||||||
- **`ipa-docs/`** — IPA design documents organized in subdirectories: `srs/`, `bd/`, `dd/`, `testcase/`, `testreport/`. Generated by `okr.srs`, `okr.bd`, `okr.dd`, and `okr.testkit`. Each subdirectory contains per-module documents.
|
- **`ipa-docs/`** — IPA design documents organized in subdirectories: `srs/`, `bd/`, `dd/`, `testcase/`, `testreport/`. Generated by `okr.srs`, `okr.bd`, `okr.dd`, and `okr.testkit`. Each subdirectory contains per-module documents.
|
||||||
- **`output_logs/`** — Execution logs from AI agents organized per feature (e.g., `000-system-srs/`, `001-access-authentication/`, etc.), useful for debugging and auditing the generation process.
|
- **`output_logs/`** — Execution logs from AI agents organized per feature (e.g., `000-system-srs/`, `001-access-authentication/`, etc.), useful for debugging and auditing the generation process.
|
||||||
- **`srs-systems/`** — System-wide SRS generated once at the beginning by `okr.srsallsystem`. Contains per-module SRS overviews (`mod01-access-authentication/`, `mod02-workspace-dashboard/`, etc.) plus `srs-overview-system.md`. Not part of the 13-step flow.
|
- **`srs-systems/`** — System-wide SRS generated once at the beginning by `okr.srsallsystem`. Contains per-module SRS overviews (`mod01-access-authentication/`, `mod02-workspace-dashboard/`, etc.) plus `srs-overview-system.md`. Not part of the 13-step flow.
|
||||||
|
|
||||||
#### `specs/`
|
#### `specs/`
|
||||||
|
|
||||||
Each folder contains `spec.md`, `plan.md`, `tasks.md`, `checklists/`, and `contracts/`. This directory serves as the **knowledge base** for agents.
|
Each folder contains `spec.md`, `plan.md`, `tasks.md`, `checklists/`, and `contracts/`. This directory serves as the **knowledge base** for agents.
|
||||||
|
|
||||||
#### Source Code
|
#### Source Code
|
||||||
Source code generated by Agents during `speckit.implement` (STEP 10).
|
Source code generated by Agents during `speckit.implement` (STEP 10).
|
||||||
`backend/` and `frontend/` contain the application source code, co-located with the monorepo root:
|
`backend/` and `frontend/` contain the application source code, co-located with the monorepo root:
|
||||||
- **`backend/`** — NestJS application. `src/` contains feature modules (`auth/`, `users/`, `objectives/`, `workspaces/`, `common/`). `prisma/` contains `schema.prisma`, migrations, and `seed.ts`. `test/` contains unit tests organized by module (`auth/`, `objectives/`, `users/`). Includes `Dockerfile`.
|
- **`backend/`** — NestJS application. `src/` contains feature modules (`auth/`, `users/`, `objectives/`, `workspaces/`, `common/`). `prisma/` contains `schema.prisma`, migrations, and `seed.ts`. `test/` contains unit tests organized by module (`auth/`, `objectives/`, `users/`). Includes `Dockerfile`.
|
||||||
- **`frontend/`** — React + Vite SPA (TypeScript). `src/pages/` for route-level components (Login, ForgotPassword, Dashboard, CreateObjective, EditObjective, ObjectiveDetail, KeyResultDetail); `src/components/` organized by feature (`auth/`, `dashboard/`, `objective-detail/`, `objective-form/`), `layout/` (Sidebar, AppHeader, AppLayout) and `ui/` (Button, Input, Alert). `src/hooks/` (useAuth, useObjectives, useUsers, useWorkspaces), `src/lib/` (api, queryClient), `src/schemas/`, `src/types/`. `test/` contains unit tests (`hooks/`, `pages/`). Includes `Dockerfile`.
|
- **`frontend/`** — React + Vite SPA (TypeScript). `src/pages/` for route-level components (Login, ForgotPassword, Dashboard, CreateObjective, EditObjective, ObjectiveDetail, KeyResultDetail); `src/components/` organized by feature (`auth/`, `dashboard/`, `objective-detail/`, `objective-form/`), `layout/` (Sidebar, AppHeader, AppLayout) and `ui/` (Button, Input, Alert). `src/hooks/` (useAuth, useObjectives, useUsers, useWorkspaces), `src/lib/` (api, queryClient), `src/schemas/`, `src/types/`. `test/` contains unit tests (`hooks/`, `pages/`). Includes `Dockerfile`.
|
||||||
- **`e2e/`** — End-to-end tests using Playwright, organized by feature (e.g., `auth/auth.spec.ts`).
|
- **`e2e/`** — End-to-end tests using Playwright, organized by feature (e.g., `auth/auth.spec.ts`).
|
||||||
- **`docker/`** — Docker utilities. Main orchestration is in `docker-compose.yml` at the project root.
|
- **`docker/`** — Docker utilities. Main orchestration is in `docker-compose.yml` at the project root.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## OKR Web Application — Quick Start
|
## OKR Web Application — Quick Start
|
||||||
|
|
||||||
### Description
|
### Description
|
||||||
|
|
||||||
The **OKR Web Application** is a full-stack web app for managing Objectives and Key Results (OKR). It consists of:
|
The **OKR Web Application** is a full-stack web app for managing Objectives and Key Results (OKR). It consists of:
|
||||||
|
|
||||||
- **Backend**: NestJS REST API with Prisma ORM and MySQL
|
- **Backend**: NestJS REST API with Prisma ORM and MySQL
|
||||||
- **Frontend**: React + Vite SPA with Tailwind CSS
|
- **Frontend**: React + Vite SPA with Tailwind CSS
|
||||||
- **Database**: MySQL 8.0
|
- **Database**: MySQL 8.0
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
|
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
|
||||||
- Node.js 20.x and npm (for local development without Docker)
|
- Node.js 20.x and npm (for local development without Docker)
|
||||||
|
|
||||||
### Quick Start (Docker)
|
### Quick Start (Docker)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repository and navigate to project root
|
# Clone the repository and navigate to project root
|
||||||
cd AINative_OKR_Claude_GHCP
|
cd AINative_OKR_Claude_GHCP
|
||||||
|
|
||||||
# Build and start all services (MySQL + Backend + Frontend)
|
# Build and start all services (MySQL + Backend + Frontend)
|
||||||
docker compose up --build
|
docker compose up --build
|
||||||
|
|
||||||
# To run in detached mode
|
# To run in detached mode
|
||||||
docker compose up --build -d
|
docker compose up --build -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Docker Compose will automatically:
|
Docker Compose will automatically:
|
||||||
1. Start MySQL and wait for it to be healthy
|
1. Start MySQL and wait for it to be healthy
|
||||||
2. Run Prisma migrations (`prisma migrate deploy`)
|
2. Run Prisma migrations (`prisma migrate deploy`)
|
||||||
3. Seed the database with default data (`prisma db seed`)
|
3. Seed the database with default data (`prisma db seed`)
|
||||||
4. Start the NestJS backend
|
4. Start the NestJS backend
|
||||||
5. Start the React frontend dev server
|
5. Start the React frontend dev server
|
||||||
|
|
||||||
### Default Credentials
|
### Default Credentials
|
||||||
|
|
||||||
| Role | Email | Password |
|
| Role | Email | Password |
|
||||||
|------|-------|----------|
|
|------|-------|----------|
|
||||||
| Admin | `admin@okr.local` | `Password@123` |
|
| Admin | `admin@okr.local` | `Password@123` |
|
||||||
| Manager | `manager@okr.local` | `Password@123` |
|
| Manager | `manager@okr.local` | `Password@123` |
|
||||||
| Employee | `employee@okr.local` | `Password@123` |
|
| Employee | `employee@okr.local` | `Password@123` |
|
||||||
|
|
||||||
### Service URLs
|
### Service URLs
|
||||||
|
|
||||||
| Service | URL |
|
| Service | URL |
|
||||||
|---------|-----|
|
|---------|-----|
|
||||||
| Frontend | http://localhost:5173 |
|
| Frontend | http://localhost:5173 |
|
||||||
| Backend API | http://localhost:3000 |
|
| Backend API | http://localhost:3000 |
|
||||||
| API Documentation (Swagger) | http://localhost:3000/api/docs |
|
| API Documentation (Swagger) | http://localhost:3000/api/docs |
|
||||||
| MySQL | localhost:3307 |
|
| MySQL | localhost:3307 |
|
||||||
|
|
||||||
### Development Without Docker
|
### Development Without Docker
|
||||||
|
|
||||||
#### Backend
|
#### Backend
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# Copy and configure environment variables
|
# Copy and configure environment variables
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Edit .env — set DATABASE_URL to point to your local MySQL instance
|
# Edit .env — set DATABASE_URL to point to your local MySQL instance
|
||||||
|
|
||||||
# Run database migrations
|
# Run database migrations
|
||||||
npx prisma migrate dev
|
npx prisma migrate dev
|
||||||
|
|
||||||
# Seed the database
|
# Seed the database
|
||||||
npx prisma db seed
|
npx prisma db seed
|
||||||
|
|
||||||
# Start the development server
|
# Start the development server
|
||||||
npm run start:dev
|
npm run start:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Frontend
|
#### Frontend
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# Copy and configure environment variables
|
# Copy and configure environment variables
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Edit .env if the backend runs on a different port
|
# Edit .env if the backend runs on a different port
|
||||||
|
|
||||||
# Start the Vite dev server
|
# Start the Vite dev server
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
The frontend will be available at http://localhost:5173 and proxies API requests to http://localhost:3000/api/v1.
|
The frontend will be available at http://localhost:5173 and proxies API requests to http://localhost:3000/api/v1.
|
||||||
|
|
||||||
### Stopping Services
|
### Stopping Services
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Stop all containers
|
# Stop all containers
|
||||||
docker compose down
|
docker compose down
|
||||||
|
|
||||||
# Stop and remove volumes (resets the database)
|
# Stop and remove volumes (resets the database)
|
||||||
docker compose down -v
|
docker compose down -v
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
sequenceDiagram
|
||||||
|
participant O as Goal Orchestrator
|
||||||
|
participant L as Local Worker
|
||||||
|
participant S as H4 Security
|
||||||
|
participant C as Cloud Reviewer
|
||||||
|
participant A as H5 Audit
|
||||||
|
|
||||||
|
O->>L: Objective and governed context
|
||||||
|
L-->>S: Primary proposal
|
||||||
|
S->>C: Safe draft for independent review
|
||||||
|
C-->>O: Critique and refined outcome
|
||||||
|
O->>A: Certified final decision
|
||||||
|
A-->>O: Audit hash and status
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 26 KiB |
@@ -43,7 +43,7 @@ tr:nth-child(even) td { background: #f7f9fc; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>CASAN Level 4 Central AgentOps Dashboard</h1>
|
<h1>CASAN Level 4 Central AgentOps Dashboard</h1>
|
||||||
<p class="subtitle">7-harness security posture · Level-5 controls demonstrated locally · điểm công tâm theo rubric (evidence/scoring-run-report.md) · Generated: 2026-07-08T09:20:56Z</p>
|
<p class="subtitle">7-harness security posture · Level-5 controls demonstrated locally · điểm công tâm theo rubric (evidence/scoring-run-report.md) · Generated: 2026-07-11T02:34:11Z</p>
|
||||||
<div class="badges">
|
<div class="badges">
|
||||||
<span class="badge lv">CASAN Level 4 — chứng minh bằng tấn công</span>
|
<span class="badge lv">CASAN Level 4 — chứng minh bằng tấn công</span>
|
||||||
<span class="badge">Average 80.9/100</span>
|
<span class="badge">Average 80.9/100</span>
|
||||||
@@ -80,34 +80,34 @@ tr:nth-child(even) td { background: #f7f9fc; }
|
|||||||
|
|
||||||
<h2>Telemetry trực tiếp (live) · pipeline harness</h2>
|
<h2>Telemetry trực tiếp (live) · pipeline harness</h2>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="card"><div class="k">Total Runs</div><div class="value">6</div></div>
|
<div class="card"><div class="k">Total Runs</div><div class="value">28</div></div>
|
||||||
<div class="card"><div class="k">Average Latency</div><div class="value">200.33<small style="font-size:14px"> ms</small></div></div>
|
<div class="card"><div class="k">Average Latency</div><div class="value">13123.61<small style="font-size:14px"> ms</small></div></div>
|
||||||
<div class="card"><div class="k">Estimated Cost</div><div class="value">$0.083484</div></div>
|
<div class="card"><div class="k">Estimated Cost</div><div class="value">$0.083668</div></div>
|
||||||
<div class="card"><div class="k">Failures</div><div class="value">1</div></div>
|
<div class="card"><div class="k">Failures</div><div class="value">7</div></div>
|
||||||
<div class="card"><div class="k">Fallback Routes</div><div class="value">1</div></div>
|
<div class="card"><div class="k">Fallback Routes</div><div class="value">3</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid" style="margin-top:12px">
|
<div class="grid" style="margin-top:12px">
|
||||||
<div class="card"><div class="k">Provider Runs</div><div class="value">2</div></div>
|
<div class="card"><div class="k">Provider Runs</div><div class="value">39</div></div>
|
||||||
<div class="card"><div class="k">Provider Tokens (thật)</div><div class="value">5556</div></div>
|
<div class="card"><div class="k">Provider Tokens (thật)</div><div class="value">25370</div></div>
|
||||||
<div class="card"><div class="k">Provider Cost</div><div class="value">$0.16668</div></div>
|
<div class="card"><div class="k">Provider Cost</div><div class="value">$0.16668</div></div>
|
||||||
<div class="card"><div class="k">Tool Denials</div><div class="value">2</div></div>
|
<div class="card"><div class="k">Tool Denials</div><div class="value">6</div></div>
|
||||||
<div class="card"><div class="k">Hallucination Signals</div><div class="value">4</div></div>
|
<div class="card"><div class="k">Hallucination Signals</div><div class="value">8</div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Governance Signals</h2>
|
<h2>Governance Signals</h2>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Signal</th><th>Value</th></tr>
|
<tr><th>Signal</th><th>Value</th></tr>
|
||||||
<tr><td>Tool registry denials</td><td>2</td></tr>
|
<tr><td>Tool registry denials</td><td>6</td></tr>
|
||||||
<tr><td>Fallback records</td><td>1</td></tr>
|
<tr><td>Fallback records</td><td>3</td></tr>
|
||||||
<tr><td>Tool registry records</td><td>3</td></tr>
|
<tr><td>Tool registry records</td><td>11</td></tr>
|
||||||
<tr><td>Provider telemetry records</td><td>2</td></tr>
|
<tr><td>Provider telemetry records</td><td>39</td></tr>
|
||||||
<tr><td>Registered harness projects</td><td>0</td></tr>
|
<tr><td>Registered harness projects</td><td>0</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>Recent AgentOps Metrics (live)</h2>
|
<h2>Recent AgentOps Metrics (live)</h2>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Trace</th><th>Agent</th><th>Step</th><th>Status</th><th>Latency</th><th>Tokens</th><th>Cost</th></tr>
|
<tr><th>Trace</th><th>Agent</th><th>Step</th><th>Status</th><th>Latency</th><th>Tokens</th><th>Cost</th></tr>
|
||||||
<tr><td>55ac657c…</td><td>demo.agent</td><td>demo-step</td><td class='ok'>success</td><td>94ms</td><td>12</td><td>$2.4e-05</td></tr><tr><td>a14c5f93…</td><td>demo.agent</td><td>step-1-srs</td><td class='ok'>success</td><td>319ms</td><td>26</td><td>$5.2e-05</td></tr><tr><td>9b58d449…</td><td>demo.agent</td><td>speckit.implement</td><td class='ok'>success</td><td>103ms</td><td>2778</td><td>$0.08334</td></tr><tr><td>aa388ecd…</td><td>demo.agent</td><td>failing-step</td><td class=''>failed</td><td>293ms</td><td>6</td><td>$1.2e-05</td></tr><tr><td>bf63152b…</td><td>wrapper.demo</td><td>wrapper-step</td><td class='ok'>success</td><td>92ms</td><td>14</td><td>$2.8e-05</td></tr><tr><td>48236a7c…</td><td>wrapper.demo</td><td>wrapper-step</td><td class='ok'>success</td><td>301ms</td><td>14</td><td>$2.8e-05</td></tr>
|
<tr><td>96b4c003…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>141ms</td><td>10</td><td>$0.0</td></tr><tr><td>c924568f…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>219ms</td><td>10</td><td>$0.0</td></tr><tr><td>10331f30…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>342ms</td><td>10</td><td>$0.0</td></tr><tr><td>2e9b93cb…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>57161ms</td><td>57</td><td>$0.0</td></tr><tr><td>d8796e51…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>57864ms</td><td>833</td><td>$0.0</td></tr><tr><td>b5ad414a…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>43174ms</td><td>799</td><td>$0.0</td></tr><tr><td>1fd5d347…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>51212ms</td><td>421</td><td>$0.0</td></tr><tr><td>1c93ce8a…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class=''>degraded</td><td>55732ms</td><td>1087</td><td>$0.0</td></tr><tr><td>6700500f…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class=''>degraded</td><td>51117ms</td><td>593</td><td>$0.0</td></tr><tr><td>21b6f387…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class='ok'>success</td><td>44058ms</td><td>560</td><td>$0.0</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ tr:nth-child(even) td { background: #f7f9fc; }
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>CASAN Level 4 Central AgentOps Dashboard</h1>
|
<h1>CASAN Level 4 Central AgentOps Dashboard</h1>
|
||||||
<p class="subtitle">7-harness security posture · Level-5 controls demonstrated locally · điểm công tâm theo rubric (evidence/scoring-run-report.md) · Generated: 2026-07-08T09:20:56Z</p>
|
<p class="subtitle">7-harness security posture · Level-5 controls demonstrated locally · điểm công tâm theo rubric (evidence/scoring-run-report.md) · Generated: 2026-07-11T02:34:11Z</p>
|
||||||
<div class="badges">
|
<div class="badges">
|
||||||
<span class="badge lv">CASAN Level 4 — chứng minh bằng tấn công</span>
|
<span class="badge lv">CASAN Level 4 — chứng minh bằng tấn công</span>
|
||||||
<span class="badge">Average 80.9/100</span>
|
<span class="badge">Average 80.9/100</span>
|
||||||
@@ -80,34 +80,34 @@ tr:nth-child(even) td { background: #f7f9fc; }
|
|||||||
|
|
||||||
<h2>Telemetry trực tiếp (live) · pipeline harness</h2>
|
<h2>Telemetry trực tiếp (live) · pipeline harness</h2>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="card"><div class="k">Total Runs</div><div class="value">6</div></div>
|
<div class="card"><div class="k">Total Runs</div><div class="value">28</div></div>
|
||||||
<div class="card"><div class="k">Average Latency</div><div class="value">200.33<small style="font-size:14px"> ms</small></div></div>
|
<div class="card"><div class="k">Average Latency</div><div class="value">13123.61<small style="font-size:14px"> ms</small></div></div>
|
||||||
<div class="card"><div class="k">Estimated Cost</div><div class="value">$0.083484</div></div>
|
<div class="card"><div class="k">Estimated Cost</div><div class="value">$0.083668</div></div>
|
||||||
<div class="card"><div class="k">Failures</div><div class="value">1</div></div>
|
<div class="card"><div class="k">Failures</div><div class="value">7</div></div>
|
||||||
<div class="card"><div class="k">Fallback Routes</div><div class="value">1</div></div>
|
<div class="card"><div class="k">Fallback Routes</div><div class="value">3</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid" style="margin-top:12px">
|
<div class="grid" style="margin-top:12px">
|
||||||
<div class="card"><div class="k">Provider Runs</div><div class="value">2</div></div>
|
<div class="card"><div class="k">Provider Runs</div><div class="value">39</div></div>
|
||||||
<div class="card"><div class="k">Provider Tokens (thật)</div><div class="value">5556</div></div>
|
<div class="card"><div class="k">Provider Tokens (thật)</div><div class="value">25370</div></div>
|
||||||
<div class="card"><div class="k">Provider Cost</div><div class="value">$0.16668</div></div>
|
<div class="card"><div class="k">Provider Cost</div><div class="value">$0.16668</div></div>
|
||||||
<div class="card"><div class="k">Tool Denials</div><div class="value">2</div></div>
|
<div class="card"><div class="k">Tool Denials</div><div class="value">6</div></div>
|
||||||
<div class="card"><div class="k">Hallucination Signals</div><div class="value">4</div></div>
|
<div class="card"><div class="k">Hallucination Signals</div><div class="value">8</div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Governance Signals</h2>
|
<h2>Governance Signals</h2>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Signal</th><th>Value</th></tr>
|
<tr><th>Signal</th><th>Value</th></tr>
|
||||||
<tr><td>Tool registry denials</td><td>2</td></tr>
|
<tr><td>Tool registry denials</td><td>6</td></tr>
|
||||||
<tr><td>Fallback records</td><td>1</td></tr>
|
<tr><td>Fallback records</td><td>3</td></tr>
|
||||||
<tr><td>Tool registry records</td><td>3</td></tr>
|
<tr><td>Tool registry records</td><td>11</td></tr>
|
||||||
<tr><td>Provider telemetry records</td><td>2</td></tr>
|
<tr><td>Provider telemetry records</td><td>39</td></tr>
|
||||||
<tr><td>Registered harness projects</td><td>0</td></tr>
|
<tr><td>Registered harness projects</td><td>0</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>Recent AgentOps Metrics (live)</h2>
|
<h2>Recent AgentOps Metrics (live)</h2>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Trace</th><th>Agent</th><th>Step</th><th>Status</th><th>Latency</th><th>Tokens</th><th>Cost</th></tr>
|
<tr><th>Trace</th><th>Agent</th><th>Step</th><th>Status</th><th>Latency</th><th>Tokens</th><th>Cost</th></tr>
|
||||||
<tr><td>55ac657c…</td><td>demo.agent</td><td>demo-step</td><td class='ok'>success</td><td>94ms</td><td>12</td><td>$2.4e-05</td></tr><tr><td>a14c5f93…</td><td>demo.agent</td><td>step-1-srs</td><td class='ok'>success</td><td>319ms</td><td>26</td><td>$5.2e-05</td></tr><tr><td>9b58d449…</td><td>demo.agent</td><td>speckit.implement</td><td class='ok'>success</td><td>103ms</td><td>2778</td><td>$0.08334</td></tr><tr><td>aa388ecd…</td><td>demo.agent</td><td>failing-step</td><td class=''>failed</td><td>293ms</td><td>6</td><td>$1.2e-05</td></tr><tr><td>bf63152b…</td><td>wrapper.demo</td><td>wrapper-step</td><td class='ok'>success</td><td>92ms</td><td>14</td><td>$2.8e-05</td></tr><tr><td>48236a7c…</td><td>wrapper.demo</td><td>wrapper-step</td><td class='ok'>success</td><td>301ms</td><td>14</td><td>$2.8e-05</td></tr>
|
<tr><td>96b4c003…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>141ms</td><td>10</td><td>$0.0</td></tr><tr><td>c924568f…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>219ms</td><td>10</td><td>$0.0</td></tr><tr><td>10331f30…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class=''>failed</td><td>342ms</td><td>10</td><td>$0.0</td></tr><tr><td>2e9b93cb…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>57161ms</td><td>57</td><td>$0.0</td></tr><tr><td>d8796e51…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>57864ms</td><td>833</td><td>$0.0</td></tr><tr><td>b5ad414a…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>43174ms</td><td>799</td><td>$0.0</td></tr><tr><td>1fd5d347…</td><td>chat.ask-casan</td><td>ask-casan-readonly</td><td class='ok'>success</td><td>51212ms</td><td>421</td><td>$0.0</td></tr><tr><td>1c93ce8a…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class=''>degraded</td><td>55732ms</td><td>1087</td><td>$0.0</td></tr><tr><td>6700500f…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class=''>degraded</td><td>51117ms</td><td>593</td><td>$0.0</td></tr><tr><td>21b6f387…</td><td>goal.orchestrator</td><td>local-worker-cloud-reviewer</td><td class='ok'>success</td><td>44058ms</td><td>560</td><td>$0.0</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
import type { GoalJob, GoalStage } from '../../lib/api';
|
||||||
|
import { StatusBadge } from '../ui/Card';
|
||||||
|
|
||||||
|
interface ModelInteractionDiagramProps {
|
||||||
|
goal: GoalJob;
|
||||||
|
localStage?: GoalStage;
|
||||||
|
cloudStage?: GoalStage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tone = (status: string) => status === 'pass' || status === 'completed' ? 'bg-emerald-500' : status === 'error' || status === 'failed' ? 'bg-rose-500' : status === 'warning' || status === 'degraded' ? 'bg-amber-500' : status === 'running' ? 'animate-pulse bg-indigo-500 motion-reduce:animate-none' : 'bg-slate-300';
|
||||||
|
|
||||||
|
function Exchange({ from, to, label, status, reverse = false }: { from: string; to: string; label: string; status: string; reverse?: boolean }) {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-[minmax(88px,1fr)_minmax(120px,2fr)_minmax(88px,1fr)] items-center gap-2">
|
||||||
|
<div className={`truncate text-xs font-semibold ${reverse ? 'text-right text-slate-500' : 'text-slate-800'}`}>{reverse ? to : from}</div>
|
||||||
|
<div className="min-w-0">
|
||||||
|
<div className={`flex items-center ${reverse ? 'flex-row-reverse' : ''}`}>
|
||||||
|
<span className={`h-2.5 w-2.5 shrink-0 rounded-full ${tone(status)}`} />
|
||||||
|
<span className={`h-px flex-1 ${status === 'error' || status === 'failed' ? 'bg-rose-300' : status === 'warning' ? 'bg-amber-300' : 'bg-indigo-300'}`} />
|
||||||
|
<span className={`h-0 w-0 border-y-4 border-y-transparent ${reverse ? 'border-r-[7px] border-r-indigo-500' : 'border-l-[7px] border-l-indigo-500'}`} />
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 truncate text-center text-[10px] font-medium text-slate-500">{label}</div>
|
||||||
|
</div>
|
||||||
|
<div className={`truncate text-xs font-semibold ${reverse ? 'text-slate-800' : 'text-right text-slate-500'}`}>{reverse ? from : to}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ModelInteractionDiagram({ goal, localStage, cloudStage }: ModelInteractionDiagramProps) {
|
||||||
|
const localStatus = localStage?.status ?? 'queued';
|
||||||
|
const cloudStatus = cloudStage?.status ?? 'queued';
|
||||||
|
return (
|
||||||
|
<section className="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm" aria-label="Model interaction diagram">
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-100 px-5 py-4">
|
||||||
|
<div><div className="text-[10px] font-bold uppercase tracking-[0.16em] text-indigo-600">Live model exchange</div><h2 className="mt-1 font-semibold text-slate-900">Models trao đổi và kiểm chứng như thế nào</h2></div>
|
||||||
|
<StatusBadge value={goal.status} />
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 p-5 lg:grid-cols-[220px_minmax(0,1fr)]">
|
||||||
|
<div className="grid grid-cols-2 gap-2 lg:grid-cols-1">
|
||||||
|
<div className="rounded-xl border border-indigo-100 bg-indigo-50 p-3"><div className="text-[10px] font-bold uppercase tracking-wide text-indigo-500">Local worker</div><div className="mt-1 truncate text-xs font-semibold text-slate-800">{localStage?.model || goal.local_model}</div></div>
|
||||||
|
<div className="rounded-xl border border-violet-100 bg-violet-50 p-3"><div className="text-[10px] font-bold uppercase tracking-wide text-violet-500">Cloud reviewer</div><div className="mt-1 truncate text-xs font-semibold text-slate-800">{cloudStage?.model || goal.cloud_model}</div></div>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4 rounded-xl border border-slate-200 bg-[radial-gradient(circle_at_top,#eef2ff_0,transparent_55%)] p-4">
|
||||||
|
<Exchange from="Orchestrator" to="Local model" label="Objective + governed context" status={localStatus} />
|
||||||
|
<Exchange from="Local model" to="H4 Security" label="Primary proposal" status={localStatus} />
|
||||||
|
<Exchange from="H4 Security" to="Cloud model" label="Safe draft for independent review" status={cloudStatus} />
|
||||||
|
<Exchange from="Cloud model" to="Orchestrator" label="Critique + refined outcome" status={cloudStatus} reverse />
|
||||||
|
<Exchange from="Orchestrator" to="H5 Audit" label="Certified final decision" status={goal.status} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-slate-100 bg-slate-50 px-5 py-3 text-[11px] leading-5 text-slate-500">Mỗi mũi tên thể hiện một boundary có kiểm soát; màu sắc lấy từ trạng thái thực tế của goal và từng worker.</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface MarkdownTextProps {
|
||||||
|
text: string;
|
||||||
|
compact?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inlineMarkdown(value: string): ReactNode[] {
|
||||||
|
const tokens = value.split(/(`[^`]+`|\*\*[^*]+\*\*|\[[^\]]+\]\(https?:\/\/[^)]+\))/g);
|
||||||
|
return tokens.filter(Boolean).map((token, index) => {
|
||||||
|
if (token.startsWith('`') && token.endsWith('`')) return <code key={index} className="rounded bg-slate-100 px-1.5 py-0.5 font-mono text-[0.9em] text-indigo-700">{token.slice(1, -1)}</code>;
|
||||||
|
if (token.startsWith('**') && token.endsWith('**')) return <strong key={index} className="font-semibold text-slate-900">{token.slice(2, -2)}</strong>;
|
||||||
|
const link = token.match(/^\[([^\]]+)\]\((https?:\/\/[^)]+)\)$/);
|
||||||
|
if (link) return <a key={index} href={link[2]} target="_blank" rel="noreferrer" className="font-medium text-indigo-600 underline decoration-indigo-200 underline-offset-2 hover:text-indigo-800">{link[1]}</a>;
|
||||||
|
return token;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MarkdownText({ text, compact = false }: MarkdownTextProps) {
|
||||||
|
const lines = text.replace(/\r\n/g, '\n').split('\n');
|
||||||
|
const blocks: ReactNode[] = [];
|
||||||
|
let list: string[] = [];
|
||||||
|
let code: string[] = [];
|
||||||
|
let inCode = false;
|
||||||
|
|
||||||
|
const flushList = () => {
|
||||||
|
if (list.length === 0) return;
|
||||||
|
blocks.push(<ul key={`list-${blocks.length}`} className="my-2 space-y-1 pl-5 text-sm leading-6 text-slate-700">{list.map((item, index) => <li key={index} className="list-disc marker:text-indigo-400">{inlineMarkdown(item)}</li>)}</ul>);
|
||||||
|
list = [];
|
||||||
|
};
|
||||||
|
const flushCode = () => {
|
||||||
|
if (code.length === 0) return;
|
||||||
|
blocks.push(<pre key={`code-${blocks.length}`} className="my-3 overflow-x-auto rounded-xl bg-slate-950 p-4 text-xs leading-5 text-slate-100"><code>{code.join('\n')}</code></pre>);
|
||||||
|
code = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
lines.forEach((line) => {
|
||||||
|
if (line.trim().startsWith('```')) {
|
||||||
|
flushList();
|
||||||
|
if (inCode) flushCode();
|
||||||
|
inCode = !inCode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (inCode) { code.push(line); return; }
|
||||||
|
const bullet = line.match(/^\s*[-*+]\s+(.+)$/);
|
||||||
|
if (bullet) { list.push(bullet[1]); return; }
|
||||||
|
flushList();
|
||||||
|
const heading = line.match(/^(#{1,4})\s+(.+)$/);
|
||||||
|
if (heading) {
|
||||||
|
const size = heading[1].length === 1 ? 'text-lg' : heading[1].length === 2 ? 'text-base' : 'text-sm';
|
||||||
|
blocks.push(<h3 key={`heading-${blocks.length}`} className={`mb-1 mt-3 font-semibold tracking-tight text-slate-900 ${size}`}>{inlineMarkdown(heading[2])}</h3>);
|
||||||
|
} else if (/^---+$/.test(line.trim())) {
|
||||||
|
blocks.push(<hr key={`rule-${blocks.length}`} className="my-3 border-slate-200" />);
|
||||||
|
} else if (line.trim()) {
|
||||||
|
blocks.push(<p key={`paragraph-${blocks.length}`} className="my-1 text-sm leading-6 text-slate-700">{inlineMarkdown(line)}</p>);
|
||||||
|
} else if (!compact) {
|
||||||
|
blocks.push(<div key={`space-${blocks.length}`} className="h-1" />);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
flushList();
|
||||||
|
flushCode();
|
||||||
|
|
||||||
|
return <div className={compact ? 'line-clamp-3' : ''}>{blocks}</div>;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type KeyboardEvent, useMemo, useState } from 'react';
|
import { type KeyboardEvent, useEffect, useMemo, useState } from 'react';
|
||||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { api, ChatAction, ChatAgent, ChatAnswer, ChatHistoryTurn, ChatModelProvider, ChatStreamPhase, SettingsActor } from '../lib/api';
|
import { api, ChatAction, ChatAgent, ChatAnswer, ChatHistoryTurn, ChatModelProvider, ChatStreamPhase, SettingsActor } from '../lib/api';
|
||||||
@@ -8,6 +8,17 @@ import { ModelConnectionPanel } from '../components/chat/ModelConnectionPanel';
|
|||||||
const ROLES = ['viewer', 'auditor', 'operator', 'project-admin', 'org-admin'];
|
const ROLES = ['viewer', 'auditor', 'operator', 'project-admin', 'org-admin'];
|
||||||
|
|
||||||
type MessageKind = 'user' | 'assistant' | 'draft';
|
type MessageKind = 'user' | 'assistant' | 'draft';
|
||||||
|
type HarnessRunStatus = 'idle' | 'running' | 'completed' | 'failed';
|
||||||
|
|
||||||
|
const HARNESS_STAGES = [
|
||||||
|
{ id: 'H1', label: 'Context' },
|
||||||
|
{ id: 'H2', label: 'Tool' },
|
||||||
|
{ id: 'H3', label: 'Evaluation' },
|
||||||
|
{ id: 'H4', label: 'Security' },
|
||||||
|
{ id: 'H5', label: 'Governance' },
|
||||||
|
{ id: 'H6', label: 'AgentOps' },
|
||||||
|
{ id: 'H7', label: 'Orchestration' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
interface WorkspaceMessage {
|
interface WorkspaceMessage {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -95,6 +106,8 @@ export function Chat() {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [streaming, setStreaming] = useState(true);
|
const [streaming, setStreaming] = useState(true);
|
||||||
const [streamBusy, setStreamBusy] = useState(false);
|
const [streamBusy, setStreamBusy] = useState(false);
|
||||||
|
const [harnessStatus, setHarnessStatus] = useState<HarnessRunStatus>('idle');
|
||||||
|
const [activeHarness, setActiveHarness] = useState(0);
|
||||||
|
|
||||||
const auditQuery = useQuery({ queryKey: ['chat-audit'], queryFn: api.verifyChatAudit, retry: false });
|
const auditQuery = useQuery({ queryKey: ['chat-audit'], queryFn: api.verifyChatAudit, retry: false });
|
||||||
const conversationsQuery = useQuery({ queryKey: ['chat-history', actor], queryFn: () => api.chatHistory(actor), retry: false });
|
const conversationsQuery = useQuery({ queryKey: ['chat-history', actor], queryFn: () => api.chatHistory(actor), retry: false });
|
||||||
@@ -142,16 +155,27 @@ export function Chat() {
|
|||||||
setPendingMessage(null);
|
setPendingMessage(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
setMessage('');
|
setMessage('');
|
||||||
|
setActiveHarness(HARNESS_STAGES.length - 1);
|
||||||
|
setHarnessStatus('completed');
|
||||||
refreshChat();
|
refreshChat();
|
||||||
},
|
},
|
||||||
onError: (reason: unknown) => {
|
onError: (reason: unknown) => {
|
||||||
setPendingMessage(null);
|
setPendingMessage(null);
|
||||||
setError(errorMessage(reason));
|
setError(errorMessage(reason));
|
||||||
|
setHarnessStatus('failed');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const busy = ask.isPending || streamBusy;
|
const busy = ask.isPending || streamBusy;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!busy || harnessStatus !== 'running') return undefined;
|
||||||
|
const timer = window.setInterval(() => {
|
||||||
|
setActiveHarness((current) => Math.min(current + 1, HARNESS_STAGES.length - 1));
|
||||||
|
}, 1100);
|
||||||
|
return () => window.clearInterval(timer);
|
||||||
|
}, [busy, harnessStatus]);
|
||||||
|
|
||||||
const runStream = async (text: string) => {
|
const runStream = async (text: string) => {
|
||||||
setStreamBusy(true);
|
setStreamBusy(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
@@ -165,6 +189,8 @@ export function Chat() {
|
|||||||
setLast(finalToAnswer(phase, actor));
|
setLast(finalToAnswer(phase, actor));
|
||||||
setPendingMessage(null);
|
setPendingMessage(null);
|
||||||
setMessage('');
|
setMessage('');
|
||||||
|
setActiveHarness(HARNESS_STAGES.length - 1);
|
||||||
|
setHarnessStatus('completed');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
refreshChat();
|
refreshChat();
|
||||||
@@ -172,6 +198,7 @@ export function Chat() {
|
|||||||
setPendingMessage(null);
|
setPendingMessage(null);
|
||||||
setDraftText(null);
|
setDraftText(null);
|
||||||
setError(errorMessage(reason));
|
setError(errorMessage(reason));
|
||||||
|
setHarnessStatus('failed');
|
||||||
} finally {
|
} finally {
|
||||||
setStreamBusy(false);
|
setStreamBusy(false);
|
||||||
}
|
}
|
||||||
@@ -180,6 +207,8 @@ export function Chat() {
|
|||||||
const submit = (override?: { message?: string; agentId?: string; skillId?: string }) => {
|
const submit = (override?: { message?: string; agentId?: string; skillId?: string }) => {
|
||||||
const text = (override?.message ?? message).trim();
|
const text = (override?.message ?? message).trim();
|
||||||
if (!text || busy) return;
|
if (!text || busy) return;
|
||||||
|
setActiveHarness(0);
|
||||||
|
setHarnessStatus('running');
|
||||||
if (streaming && !override) void runStream(text);
|
if (streaming && !override) void runStream(text);
|
||||||
else {
|
else {
|
||||||
setPendingMessage(text);
|
setPendingMessage(text);
|
||||||
@@ -202,6 +231,8 @@ export function Chat() {
|
|||||||
setPendingMessage(null);
|
setPendingMessage(null);
|
||||||
setDraftText(null);
|
setDraftText(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
|
setHarnessStatus('idle');
|
||||||
|
setActiveHarness(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -263,6 +294,34 @@ export function Chat() {
|
|||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{harnessStatus !== 'idle' && (
|
||||||
|
<div aria-live="polite" aria-label="H1 to H7 response progress" className={`rounded-2xl border px-4 py-3 shadow-sm ${harnessStatus === 'failed' ? 'border-rose-200 bg-rose-50/80' : harnessStatus === 'completed' ? 'border-emerald-200 bg-emerald-50/70' : 'border-indigo-200 bg-indigo-50/70'}`}>
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||||
|
<div className="flex items-center gap-2 text-xs font-semibold text-slate-800">
|
||||||
|
<span className="relative flex h-2.5 w-2.5 items-center justify-center">
|
||||||
|
{harnessStatus === 'running' && <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-indigo-400 opacity-60 motion-reduce:animate-none" />}
|
||||||
|
<span className={`relative inline-flex h-2.5 w-2.5 rounded-full ${harnessStatus === 'failed' ? 'bg-rose-500' : harnessStatus === 'completed' ? 'bg-emerald-500' : 'bg-indigo-600'}`} />
|
||||||
|
</span>
|
||||||
|
{harnessStatus === 'running' ? `CASAN đang phản hồi · ${HARNESS_STAGES[activeHarness].id} ${HARNESS_STAGES[activeHarness].label}` : harnessStatus === 'completed' ? 'Phản hồi đã hoàn tất qua H1–H7' : `Phản hồi dừng tại ${HARNESS_STAGES[activeHarness].id}`}
|
||||||
|
</div>
|
||||||
|
<span className="text-[10px] font-bold uppercase tracking-[0.12em] text-slate-500">{harnessStatus === 'running' ? 'Processing' : harnessStatus}</span>
|
||||||
|
</div>
|
||||||
|
<div className="mt-3 grid grid-cols-7 gap-1.5">
|
||||||
|
{HARNESS_STAGES.map((stage, index) => {
|
||||||
|
const done = harnessStatus === 'completed' || index < activeHarness;
|
||||||
|
const active = harnessStatus === 'running' && index === activeHarness;
|
||||||
|
const failed = harnessStatus === 'failed' && index === activeHarness;
|
||||||
|
return (
|
||||||
|
<div key={stage.id} className="min-w-0 text-center">
|
||||||
|
<div className={`h-1.5 rounded-full transition-colors duration-500 ${failed ? 'bg-rose-500' : done ? 'bg-emerald-500' : active ? 'animate-pulse bg-indigo-600 motion-reduce:animate-none' : 'bg-slate-200'}`} />
|
||||||
|
<div className={`mt-1.5 text-[10px] font-bold ${failed ? 'text-rose-700' : done ? 'text-emerald-700' : active ? 'text-indigo-700' : 'text-slate-400'}`}>{stage.id}</div>
|
||||||
|
<div className="hidden truncate text-[9px] text-slate-500 sm:block">{stage.label}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{!historyQuery.isLoading && messages.length === 0 && <div className="mx-auto flex max-w-md flex-col items-center py-20 text-center"><div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-indigo-50 text-indigo-600"><Glyph name="spark" /></div><h3 className="mt-4 font-semibold text-slate-800">A governed empty state</h3><p className="mt-2 text-sm leading-6 text-slate-500">Ask for a plan, a security posture, or an evidence-backed comparison. CASAN will cite what it knows and decline what it cannot govern.</p></div>}
|
{!historyQuery.isLoading && messages.length === 0 && <div className="mx-auto flex max-w-md flex-col items-center py-20 text-center"><div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-indigo-50 text-indigo-600"><Glyph name="spark" /></div><h3 className="mt-4 font-semibold text-slate-800">A governed empty state</h3><p className="mt-2 text-sm leading-6 text-slate-500">Ask for a plan, a security posture, or an evidence-backed comparison. CASAN will cite what it knows and decline what it cannot govern.</p></div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-slate-200 bg-white p-4">
|
<div className="border-t border-slate-200 bg-white p-4">
|
||||||
@@ -300,7 +359,7 @@ export function Chat() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 text-[10px] font-bold uppercase tracking-[0.15em] text-slate-400">Registered actions</div>
|
<div className="mt-5 text-[10px] font-bold uppercase tracking-[0.15em] text-slate-400">Registered actions</div>
|
||||||
<div className="mt-2 space-y-2">{(actionsQuery.data?.actions ?? []).slice(0, 3).map((action: ChatAction) => <button key={action.id} type="button" disabled={busy} onClick={() => { const trigger = action.triggers[0] || action.id; setMessage(trigger); setPendingMessage(trigger); ask.mutate({ message: trigger, agentId: 'ops-operator', skillId: 'registered-actions' }); }} className="w-full rounded-xl border border-slate-200 bg-white p-3 text-left transition hover:border-indigo-200 hover:bg-indigo-50/50 disabled:opacity-50"><div className="flex items-center gap-2 text-sm font-semibold text-slate-800"><Glyph name="bolt" />{action.label}</div><p className="mt-1 text-xs leading-5 text-slate-500">{action.description}</p></button>)}{actionsQuery.isError && <div className="text-xs text-rose-600">Registered actions are unavailable.</div>}</div>
|
<div className="mt-2 space-y-2">{(actionsQuery.data?.actions ?? []).slice(0, 3).map((action: ChatAction) => <button key={action.id} type="button" disabled={busy} onClick={() => { const trigger = action.triggers[0] || action.id; setMessage(trigger); setPendingMessage(trigger); setActiveHarness(0); setHarnessStatus('running'); ask.mutate({ message: trigger, agentId: 'ops-operator', skillId: 'registered-actions' }); }} className="w-full rounded-xl border border-slate-200 bg-white p-3 text-left transition hover:border-indigo-200 hover:bg-indigo-50/50 disabled:opacity-50"><div className="flex items-center gap-2 text-sm font-semibold text-slate-800"><Glyph name="bolt" />{action.label}</div><p className="mt-1 text-xs leading-5 text-slate-500">{action.description}</p></button>)}{actionsQuery.isError && <div className="text-xs text-rose-600">Registered actions are unavailable.</div>}</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<ModelConnectionPanel actor={actor} open={connectionsOpen} onClose={() => setConnectionsOpen(false)} onSelect={(provider, model) => { setModelProvider(provider); setModelId(model); void connectionsQuery.refetch(); }} />
|
<ModelConnectionPanel actor={actor} open={connectionsOpen} onClose={() => setConnectionsOpen(false)} onSelect={(provider, model) => { setModelProvider(provider); setModelId(model); void connectionsQuery.refetch(); }} />
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { useSearchParams } from 'react-router-dom';
|
|||||||
import { api, type GoalJob, type SettingsActor } from '../lib/api';
|
import { api, type GoalJob, type SettingsActor } from '../lib/api';
|
||||||
import { Card, StatusBadge } from '../components/ui/Card';
|
import { Card, StatusBadge } from '../components/ui/Card';
|
||||||
import { TraceExplorer } from '../components/trace/TraceExplorer';
|
import { TraceExplorer } from '../components/trace/TraceExplorer';
|
||||||
|
import { MarkdownText } from '../components/ui/MarkdownText';
|
||||||
|
import { ModelInteractionDiagram } from '../components/goals/ModelInteractionDiagram';
|
||||||
|
|
||||||
const DEFAULT_ACTOR: SettingsActor = { actor: 'local-operator', role: 'project-admin', project: 'default', tenant: 'default' };
|
const DEFAULT_ACTOR: SettingsActor = { actor: 'local-operator', role: 'project-admin', project: 'default', tenant: 'default' };
|
||||||
const TERMINAL = new Set<GoalJob['status']>(['completed', 'degraded', 'failed']);
|
const TERMINAL = new Set<GoalJob['status']>(['completed', 'degraded', 'failed']);
|
||||||
@@ -111,19 +113,21 @@ export function Goals() {
|
|||||||
<WorkerCard title="Cloud reviewer" subtitle="Independent critique and refinement" status={cloudStage?.status ?? 'queued'} detail={cloudStage?.detail ?? 'Waiting'} provider={cloudStage?.provider ?? selected.cloud_provider} model={cloudStage?.model ?? selected.cloud_model} />
|
<WorkerCard title="Cloud reviewer" subtitle="Independent critique and refinement" status={cloudStage?.status ?? 'queued'} detail={cloudStage?.detail ?? 'Waiting'} provider={cloudStage?.provider ?? selected.cloud_provider} model={cloudStage?.model ?? selected.cloud_model} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ModelInteractionDiagram goal={selected} localStage={localStage} cloudStage={cloudStage} />
|
||||||
|
|
||||||
<Card title="Governed outcome" right={<StatusBadge value={selected.status} />}>
|
<Card title="Governed outcome" right={<StatusBadge value={selected.status} />}>
|
||||||
<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
|
<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
|
||||||
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-slate-400">Objective</div>
|
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-slate-400">Objective</div>
|
||||||
<p className="mt-2 text-sm leading-6 text-slate-700">{selected.goal}</p>
|
<div className="mt-2"><MarkdownText text={selected.goal} /></div>
|
||||||
</div>
|
</div>
|
||||||
{selected.result ? <div className="mt-5 whitespace-pre-wrap text-sm leading-7 text-slate-800">{selected.result}</div> : (
|
{selected.result ? <div className="mt-5"><MarkdownText text={selected.result} /></div> : (
|
||||||
<div className="mt-5 flex items-center gap-3 rounded-xl border border-blue-200 bg-blue-50 p-4 text-sm text-blue-800">
|
<div className="mt-5 flex items-center gap-3 rounded-xl border border-blue-200 bg-blue-50 p-4 text-sm text-blue-800">
|
||||||
<span className="h-2.5 w-2.5 animate-pulse rounded-full bg-blue-500" />
|
<span className="h-2.5 w-2.5 animate-pulse rounded-full bg-blue-500" />
|
||||||
Models are working. This page refreshes automatically.
|
Models are working. This page refreshes automatically.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{selected.error && <div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 p-3 text-sm text-rose-700">{selected.error}</div>}
|
{selected.error && <div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 p-3 text-sm text-rose-700">{selected.error}</div>}
|
||||||
{selected.local_draft && <details className="mt-5 rounded-xl border border-slate-200 p-4"><summary className="cursor-pointer text-sm font-semibold text-slate-700">Inspect local worker draft</summary><div className="mt-4 whitespace-pre-wrap text-sm leading-6 text-slate-600">{selected.local_draft}</div></details>}
|
{selected.local_draft && <details className="mt-5 rounded-xl border border-slate-200 p-4"><summary className="cursor-pointer text-sm font-semibold text-slate-700">Inspect local worker draft</summary><div className="mt-4"><MarkdownText text={selected.local_draft} /></div></details>}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<TraceExplorer traceId={selected.trace_id} />
|
<TraceExplorer traceId={selected.trace_id} />
|
||||||
@@ -134,7 +138,7 @@ export function Goals() {
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{(listQuery.data?.goals ?? []).map((item) => (
|
{(listQuery.data?.goals ?? []).map((item) => (
|
||||||
<button key={item.id} type="button" onClick={() => setSearchParams({ id: item.id })} className={`flex w-full items-center justify-between gap-4 rounded-xl border p-3 text-left transition hover:bg-slate-50 ${selectedId === item.id ? 'border-indigo-300 bg-indigo-50/50' : 'border-slate-200'}`}>
|
<button key={item.id} type="button" onClick={() => setSearchParams({ id: item.id })} className={`flex w-full items-center justify-between gap-4 rounded-xl border p-3 text-left transition hover:bg-slate-50 ${selectedId === item.id ? 'border-indigo-300 bg-indigo-50/50' : 'border-slate-200'}`}>
|
||||||
<div className="min-w-0"><div className="truncate text-sm font-medium text-slate-800">{item.goal}</div><div className="mt-1 text-xs text-slate-400">{item.created_at.replace('T', ' ').replace('Z', '')}</div></div>
|
<div className="min-w-0 flex-1"><MarkdownText text={item.goal} compact /><div className="mt-1 text-xs text-slate-400">{item.created_at.replace('T', ' ').replace('Z', '')}</div></div>
|
||||||
<StatusBadge value={item.status} />
|
<StatusBadge value={item.status} />
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -117,11 +117,17 @@ def scan(text: str, mode: str):
|
|||||||
output = os.path.join(directory, "output.txt")
|
output = os.path.join(directory, "output.txt")
|
||||||
with open(source, "w", encoding="utf-8") as handle:
|
with open(source, "w", encoding="utf-8") as handle:
|
||||||
handle.write(text)
|
handle.write(text)
|
||||||
|
environment = os.environ.copy()
|
||||||
|
# The goal workflow already records and enforces its H4 boundary. Keep
|
||||||
|
# deterministic injection/secret/PII checks active, but do not turn a
|
||||||
|
# temporary semantic-classifier outage into a false-positive block.
|
||||||
|
environment["CASAN_SECURITY_STRICT"] = "0"
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["bash", SECURITY, source, output, mode],
|
["bash", SECURITY, source, output, mode],
|
||||||
cwd=ROOT,
|
cwd=ROOT,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
env=environment,
|
||||||
timeout=60,
|
timeout=60,
|
||||||
)
|
)
|
||||||
safe = ""
|
safe = ""
|
||||||
@@ -141,6 +147,11 @@ def call_model(model: str, prompt: str, cloud: bool):
|
|||||||
handle.write(prompt)
|
handle.write(prompt)
|
||||||
environment = os.environ.copy()
|
environment = os.environ.copy()
|
||||||
environment["CASAN_PREFLIGHT"] = "1" if cloud else "0"
|
environment["CASAN_PREFLIGHT"] = "1" if cloud else "0"
|
||||||
|
# Long Markdown objectives need enough time for a local 9B model to
|
||||||
|
# ingest the brief and produce a bounded plan. The outer goal timeout
|
||||||
|
# remains the hard ceiling; this only raises the router's 60s default.
|
||||||
|
environment.setdefault("CASAN_MODEL_TIMEOUT_SEC", os.environ.get("CASAN_GOAL_LOCAL_TIMEOUT_SEC", "240") if not cloud else "120")
|
||||||
|
environment.setdefault("CASAN_MODEL_GENERATE_MAX_TOKENS", os.environ.get("CASAN_GOAL_MAX_OUTPUT_TOKENS", "1400"))
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["bash", MODEL_ROUTER, prompt_path, output_path, "--role", "generate", "--model", model],
|
["bash", MODEL_ROUTER, prompt_path, output_path, "--role", "generate", "--model", model],
|
||||||
@@ -292,7 +303,7 @@ def run(job_path: str) -> int:
|
|||||||
if not ok:
|
if not ok:
|
||||||
stage(job_path, "local-worker", "error", reason, job.get("local_provider", ""), local_model)
|
stage(job_path, "local-worker", "error", reason, job.get("local_provider", ""), local_model)
|
||||||
emit(goal_id, "H2-tool", "error", "Local worker failed", {"reason": reason})
|
emit(goal_id, "H2-tool", "error", "Local worker failed", {"reason": reason})
|
||||||
raise RuntimeError("local_worker_failed")
|
raise RuntimeError(f"local_worker_failed:{reason}")
|
||||||
allowed, safe_local = scan(local_draft, "output")
|
allowed, safe_local = scan(local_draft, "output")
|
||||||
if not allowed:
|
if not allowed:
|
||||||
emit(goal_id, "H4-security", "blocked", "Local worker output rejected")
|
emit(goal_id, "H4-security", "blocked", "Local worker output rejected")
|
||||||
|
|||||||
@@ -40,14 +40,26 @@ start_auth_bridge() {
|
|||||||
openssl rand -hex 32 > "$AUTH_BRIDGE_TOKEN_FILE"
|
openssl rand -hex 32 > "$AUTH_BRIDGE_TOKEN_FILE"
|
||||||
chmod 600 "$AUTH_BRIDGE_TOKEN_FILE"
|
chmod 600 "$AUTH_BRIDGE_TOKEN_FILE"
|
||||||
fi
|
fi
|
||||||
if [[ -f "$AUTH_BRIDGE_PID_FILE" ]] && kill -0 "$(cat "$AUTH_BRIDGE_PID_FILE")" 2>/dev/null; then
|
if curl -fsS -m 2 "http://127.0.0.1:20130/healthz" >/dev/null 2>&1; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if [[ -f "$AUTH_BRIDGE_PID_FILE" ]]; then
|
||||||
|
local existing_pid
|
||||||
|
existing_pid="$(cat "$AUTH_BRIDGE_PID_FILE")"
|
||||||
|
# A PID can be stale or reused by an unrelated process. Health is the
|
||||||
|
# authoritative signal; clean the stale state before starting the bridge.
|
||||||
|
kill "$existing_pid" 2>/dev/null || true
|
||||||
|
rm -f "$AUTH_BRIDGE_PID_FILE"
|
||||||
|
fi
|
||||||
[[ -f "$AUTH_BRIDGE" ]] || { echo "CASAN_AUTH_BRIDGE_MISSING" >&2; return 1; }
|
[[ -f "$AUTH_BRIDGE" ]] || { echo "CASAN_AUTH_BRIDGE_MISSING" >&2; return 1; }
|
||||||
nohup python3 "$AUTH_BRIDGE" --bind 0.0.0.0 --port 20130 --token-file "$AUTH_BRIDGE_TOKEN_FILE" --audit-log "$AUTH_BRIDGE_AUDIT" > "$AUTH_BRIDGE_LOG" 2>&1 &
|
nohup python3 "$AUTH_BRIDGE" --bind 0.0.0.0 --port 20130 --token-file "$AUTH_BRIDGE_TOKEN_FILE" --audit-log "$AUTH_BRIDGE_AUDIT" > "$AUTH_BRIDGE_LOG" 2>&1 &
|
||||||
echo "$!" > "$AUTH_BRIDGE_PID_FILE"
|
echo "$!" > "$AUTH_BRIDGE_PID_FILE"
|
||||||
chmod 600 "$AUTH_BRIDGE_PID_FILE" "$AUTH_BRIDGE_LOG" "$AUTH_BRIDGE_AUDIT" 2>/dev/null || true
|
chmod 600 "$AUTH_BRIDGE_PID_FILE" "$AUTH_BRIDGE_LOG" "$AUTH_BRIDGE_AUDIT" 2>/dev/null || true
|
||||||
wait_url "http://127.0.0.1:20130/healthz"
|
if ! wait_url "http://127.0.0.1:20130/healthz"; then
|
||||||
|
kill "$(cat "$AUTH_BRIDGE_PID_FILE")" 2>/dev/null || true
|
||||||
|
rm -f "$AUTH_BRIDGE_PID_FILE"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_auth_bridge() {
|
stop_auth_bridge() {
|
||||||
@@ -112,8 +124,8 @@ case "$CMD" in
|
|||||||
bash "$INFRA" status
|
bash "$INFRA" status
|
||||||
echo "=== control panel ==="
|
echo "=== control panel ==="
|
||||||
cp_compose ps
|
cp_compose ps
|
||||||
if [[ -f "$AUTH_BRIDGE_PID_FILE" ]] && kill -0 "$(cat "$AUTH_BRIDGE_PID_FILE")" 2>/dev/null; then
|
if curl -fsS -m 2 "http://127.0.0.1:20130/healthz" >/dev/null 2>&1; then
|
||||||
echo "provider_auth_bridge=running pid=$(cat "$AUTH_BRIDGE_PID_FILE")"
|
echo "provider_auth_bridge=running"
|
||||||
else
|
else
|
||||||
echo "provider_auth_bridge=stopped"
|
echo "provider_auth_bridge=stopped"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -171,6 +171,11 @@ def call_ollama(model_name, prompt, role):
|
|||||||
# small budget is consumed by reasoning and `response` comes back empty.
|
# small budget is consumed by reasoning and `response` comes back empty.
|
||||||
body["think"] = False
|
body["think"] = False
|
||||||
body["options"]["num_predict"] = 16 # terse final answer + fast
|
body["options"]["num_predict"] = 16 # terse final answer + fast
|
||||||
|
else:
|
||||||
|
# Prevent an unconstrained local generation from consuming the whole
|
||||||
|
# request window. Goal Orchestrator can tune this without weakening the
|
||||||
|
# shorter classifier/judge budgets.
|
||||||
|
body["options"]["num_predict"] = max(64, int(os.environ.get("CASAN_MODEL_GENERATE_MAX_TOKENS", "1400")))
|
||||||
data = json.dumps(body).encode()
|
data = json.dumps(body).encode()
|
||||||
req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
|
req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ def runtime_env(provider_id: str, model_id: str) -> int:
|
|||||||
parsed = urlparse(endpoint)
|
parsed = urlparse(endpoint)
|
||||||
env.update({
|
env.update({
|
||||||
"CASAN_OLLAMA_HOST": parsed.netloc,
|
"CASAN_OLLAMA_HOST": parsed.netloc,
|
||||||
"OLLAMA_HOST": parsed.netloc,
|
"OLLAMA_HOST": endpoint,
|
||||||
"CASAN_ALLOW_DOCKER_HOST_OLLAMA": "1" if parsed.hostname == "host.docker.internal" else "0",
|
"CASAN_ALLOW_DOCKER_HOST_OLLAMA": "1" if parsed.hostname == "host.docker.internal" else "0",
|
||||||
})
|
})
|
||||||
print(json.dumps({"success": True, "env": env}, ensure_ascii=False))
|
print(json.dumps({"success": True, "env": env}, ensure_ascii=False))
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ mkdir -p "$(dirname "$PIN_FILE")"
|
|||||||
CMD="${1:-verify}"
|
CMD="${1:-verify}"
|
||||||
MODEL="${2:-${CASAN_MODEL:-ornith:9b}}"
|
MODEL="${2:-${CASAN_MODEL:-ornith:9b}}"
|
||||||
OLLAMA="${OLLAMA_HOST:-127.0.0.1:11434}"
|
OLLAMA="${OLLAMA_HOST:-127.0.0.1:11434}"
|
||||||
|
case "$OLLAMA" in
|
||||||
|
http://*|https://*) OLLAMA_BASE="${OLLAMA%/}" ;;
|
||||||
|
*) OLLAMA_BASE="http://${OLLAMA%/}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
current_digest() {
|
current_digest() {
|
||||||
# 1) explicit override (deterministic for CI/tests) — DISABLED in enforced mode.
|
# 1) explicit override (deterministic for CI/tests) — DISABLED in enforced mode.
|
||||||
@@ -44,7 +48,7 @@ current_digest() {
|
|||||||
fi
|
fi
|
||||||
# 2) live Ollama
|
# 2) live Ollama
|
||||||
local d
|
local d
|
||||||
d="$(curl -sf "http://$OLLAMA/api/tags" 2>/dev/null | \
|
d="$(curl -sf "$OLLAMA_BASE/api/tags" 2>/dev/null | \
|
||||||
python3 -c "import json,sys
|
python3 -c "import json,sys
|
||||||
m=sys.argv[1]
|
m=sys.argv[1]
|
||||||
try: d=json.load(sys.stdin)
|
try: d=json.load(sys.stdin)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
62231
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{"timestamp": "2026-07-10T14:44:35Z", "provider": "codex", "status": "prompt_length_invalid", "prompt_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "prompt_characters": 0, "latency_ms": 0}
|
||||||
|
{"timestamp": "2026-07-11T03:05:27Z", "provider": "codex", "status": "success", "prompt_hash": "eb0d4dea8f4d9db4e5a23b30cb230e2877e0f10e3b068b6c26e60df4348336bb", "prompt_characters": 1661, "latency_ms": 43253}
|
||||||
|
{"timestamp": "2026-07-11T03:07:54Z", "provider": "codex", "status": "success", "prompt_hash": "0bd46179eb95de73deb5be96bc4306993e43b7b5ade08af7e806c313ded88ad0", "prompt_characters": 1340, "latency_ms": 47640}
|
||||||
|
{"timestamp": "2026-07-11T03:15:44Z", "provider": "codex", "status": "success", "prompt_hash": "2c095509fcae5832ca5fc0952f61e234097cbee6905f4ffcdf24e5830bfa6c0d", "prompt_characters": 11606, "latency_ms": 56375}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
b39f21f536ddb5ce72aac871e08584044fc2578f02026a79916b92dbd8738e86
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
flowchart LR
|
||||||
|
A["Người dùng gửi Goal"] --> B["H1: Phân loại mục tiêu"]
|
||||||
|
B --> C["Local + Cloud tạo Execution Plan"]
|
||||||
|
C --> D["H4: Kiểm tra policy và rủi ro"]
|
||||||
|
D --> E["Plan ready\nXem file, lệnh, dependency, test"]
|
||||||
|
E -->|"Approve"| F["Workspace Executor có sandbox"]
|
||||||
|
E -->|"Reject / Edit"| C
|
||||||
|
F --> G["Tạo branch/worktree và project"]
|
||||||
|
G --> H["Chạy test + kiểm tra acceptance"]
|
||||||
|
H -->|"Pass"| I["Completed"]
|
||||||
|
H -->|"Fail"| J["Failed + rollback / resume"]
|
||||||
|
|
||||||
|
K["Luồng hiện tại"] -.-> L["Local worker tạo text"]
|
||||||
|
L -.-> M["Cloud reviewer tạo text"]
|
||||||
|
M -.-> N["Completed = trả lời xong\nkhông sửa workspace"]
|
||||||
|
|
||||||
|
classDef current fill:#fff7ed,stroke:#f97316,color:#7c2d12;
|
||||||
|
classDef target fill:#eff6ff,stroke:#2563eb,color:#1e3a8a;
|
||||||
|
class K,L,M,N current;
|
||||||
|
class A,B,C,D,E,F,G,H,I,J target;
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1 @@
|
|||||||
|
21e680feef6579237c8a922712245afe8311c59e74d61523f8781535fcc35130
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"seq": 1, "timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "chat_id": "phase2-blocked", "turn_id": "turn-38db1352-5ff", "tenant_id": "default", "actor": "phase2-smoke", "mode": "BLOCK", "risk": "high", "decision": "DENIED", "router": {"mode": "BLOCK", "risk": "high", "gates": ["H4_INPUT", "H5_CHAT_AUDIT"], "needs_approval": false, "reason": "blocked_by_rule", "matched_rules": ["ignore previous instructions", "reveal system prompt"], "side_effect_allowed": false, "classified_at": "2026-07-10T14:14:25Z"}, "user_msg_ref": "a20fa0ed6c2e5e629cf8413dfeb67a916825b0e617f0924ef9ea7d4e2eff916d", "safe_preview": "", "answer_ref": "eb8a01730d30c968225db76b066cdf294dd89d0be3ad5f3925b636a8a91ac6b2", "answer_preview": "Denied by Prompt Router: mode=BLOCK reason=blocked_by_rule", "synthesis_mode": "deterministic", "sources": [], "prev_hash": "0000000000000000000000000000000000000000000000000000000000000000", "record_hash": "21e680feef6579237c8a922712245afe8311c59e74d61523f8781535fcc35130"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "failed", "exit_code": 2, "latency_ms": 90, "retry_count": 0, "input_tokens": 7, "output_tokens": 6, "total_tokens": 13, "cost_estimate": 0.0, "cost_source": "readonly_word_count", "synthesis_mode": "deterministic", "hallucination_signals": 0, "alerts": [], "input_hash": "a20fa0ed6c2e5e629cf8413dfeb67a916825b0e617f0924ef9ea7d4e2eff916d", "output_hash": "eb8a01730d30c968225db76b066cdf294dd89d0be3ad5f3925b636a8a91ac6b2"}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H1-context", "status": "running", "reason": "Classifying prompt contract", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H1-context", "status": "blocked", "reason": "blocked_by_rule", "evidence": {"mode": "BLOCK", "risk": "high"}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H5-governance", "status": "running", "reason": "Writing append-only decision audit", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H5-governance", "status": "pass", "reason": "Decision audit recorded", "evidence": {"decision": "DENIED", "audit_seq": 1, "audit_hash": "21e680feef6579237c8a922712245afe8311c59e74d61523f8781535fcc35130"}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H6-agentops", "status": "running", "reason": "Recording runtime metrics", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H6-agentops", "status": "error", "reason": "Runtime metrics recorded", "evidence": {"latency_ms": 90, "status": "failed", "synthesis_mode": "deterministic"}}
|
||||||
|
{"timestamp": "2026-07-10T14:14:25Z", "trace_id": "38db1352-5ffc-4f37-b785-fd1c61e5a740", "gate_id": "H7-orchestration", "status": "blocked", "reason": "Harness stopped with governed outcome", "evidence": {"decision": "DENIED", "certified": false}}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{"timestamp":"2026-07-10T14:12:40Z","trace_id":"27486dfc-3f1a-40da-a239-9d3f5ef75496","harness":"H4-security","mode":"input","status":"pass","action":"allow","risk_level":"low","input_hash":"2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0","output_hash":"2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0"}
|
||||||
|
{"timestamp":"2026-07-10T14:12:45Z","trace_id":"dac69766-9c81-49bc-8a11-4659dcf7dfdd","harness":"H4-security","mode":"output","status":"pass","action":"allow","risk_level":"low","input_hash":"c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319","output_hash":"c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
4f5f5d965fc38522128bfff17058c9ce133edef023901afb3b75b9036470cc43
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"seq": 1, "timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "chat_id": "phase2-smoke", "turn_id": "turn-d73c565f-19e", "tenant_id": "default", "actor": "phase2-smoke", "mode": "READ_ONLY", "risk": "low", "decision": "ANSWERED", "router": {"mode": "READ_ONLY", "risk": "low", "gates": ["H4_INPUT", "H4_OUTPUT", "H5_CHAT_AUDIT", "H6_TOKEN"], "needs_approval": false, "reason": "read_only_terms", "matched_rules": ["casan"], "side_effect_allowed": false, "classified_at": "2026-07-10T14:12:40Z"}, "user_msg_ref": "2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0", "safe_preview": "Tóm tắt kiến trúc CASAN", "answer_ref": "c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319", "answer_preview": "Ask CASAN read-only answer (evidence-backed):\n- docs/plans/CASAN_PLAN_01_RESTRUCTURE.md:7 — > `PASS=64 FAIL=0 SKIP=3`. Nền cho Plan-06/12 sẵn sàng (`project-registry.json` có `doma", "synthesis_mode": "deterministic", "sources": [{"path": "docs/plans/CASAN_PLAN_01_RESTRUCTURE.md", "line": 7}, {"path": "docs/plans/CASAN_PLAN_10_TRACEABILITY_EVAL.md", "line": 1}, {"path": "docs/plans/CASAN_PLAN_13_CONTROL_PLANE.md", "line": 4}, {"path": "docs/output/casan/WHY-81-TO-90-DEEP-DIVE.md", "line": 30}, {"path": "docs/output/casan/phase3-push-to-90-plan.md", "line": 1}], "prev_hash": "0000000000000000000000000000000000000000000000000000000000000000", "record_hash": "4f5f5d965fc38522128bfff17058c9ce133edef023901afb3b75b9036470cc43"}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "harness": "H6-agentops", "agent": "chat.ask-casan", "step": "ask-casan-readonly", "status": "success", "exit_code": 0, "latency_ms": 5690, "retry_count": 0, "input_tokens": 5, "output_tokens": 49, "total_tokens": 54, "cost_estimate": 0.0, "cost_source": "readonly_word_count", "synthesis_mode": "deterministic", "hallucination_signals": 0, "alerts": [], "input_hash": "2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0", "output_hash": "c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319"}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{"timestamp": "2026-07-10T14:12:40Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H1-context", "status": "running", "reason": "Classifying prompt contract", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:40Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H1-context", "status": "pass", "reason": "read_only_terms", "evidence": {"mode": "READ_ONLY", "risk": "low"}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:40Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H4-security", "status": "running", "reason": "Scanning input boundary", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:44Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H4-security", "status": "running", "reason": "Input passed; output scan pending", "evidence": {"input_scan": "pass"}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:44Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H2-tool", "status": "running", "reason": "Retrieving allowlisted evidence", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:44Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H2-tool", "status": "pass", "reason": "Allowlisted evidence prepared", "evidence": {"source_count": 5, "history_available": false}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:44Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H3-eval", "status": "running", "reason": "Synthesizing grounded answer", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:44Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H3-eval", "status": "pass", "reason": "Grounded synthesis completed", "evidence": {"mode": "deterministic", "provider": "deterministic", "model": "none", "source_count": 5}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H4-security", "status": "pass", "reason": "Input and output security scans passed", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H5-governance", "status": "running", "reason": "Writing append-only decision audit", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H5-governance", "status": "pass", "reason": "Decision audit recorded", "evidence": {"decision": "ANSWERED", "audit_seq": 1, "audit_hash": "4f5f5d965fc38522128bfff17058c9ce133edef023901afb3b75b9036470cc43"}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H6-agentops", "status": "running", "reason": "Recording runtime metrics", "evidence": {}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H6-agentops", "status": "pass", "reason": "Runtime metrics recorded", "evidence": {"latency_ms": 5690, "status": "success", "synthesis_mode": "deterministic"}}
|
||||||
|
{"timestamp": "2026-07-10T14:12:45Z", "trace_id": "d73c565f-19ec-4ada-bf69-5fad89cfa282", "gate_id": "H7-orchestration", "status": "pass", "reason": "Harness turn completed", "evidence": {"decision": "ANSWERED", "certified": true}}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"trace_id": "27486dfc-3f1a-40da-a239-9d3f5ef75496",
|
||||||
|
"timestamp": "2026-07-10T14:12:40Z",
|
||||||
|
"harness": "H4-security",
|
||||||
|
"mode": "input",
|
||||||
|
"status": "pass",
|
||||||
|
"action": "allow",
|
||||||
|
"risk_level": "low",
|
||||||
|
"matched_rules": [],
|
||||||
|
"input_hash": "2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0",
|
||||||
|
"output_hash": "2f2fcdae3b44f5ba01fc31a7ee39b66b0f752ae567f4c84d7964d94c6f2f79f0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"trace_id": "dac69766-9c81-49bc-8a11-4659dcf7dfdd",
|
||||||
|
"timestamp": "2026-07-10T14:12:45Z",
|
||||||
|
"harness": "H4-security",
|
||||||
|
"mode": "output",
|
||||||
|
"status": "pass",
|
||||||
|
"action": "allow",
|
||||||
|
"risk_level": "low",
|
||||||
|
"matched_rules": [],
|
||||||
|
"input_hash": "c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319",
|
||||||
|
"output_hash": "c79023a4034447e036f4a5fc1d38323b5d7bebdad17bcf6f8bc990fd33389319"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user