optz: Goal orchestrator

This commit is contained in:
thanhnv
2026-07-11 12:18:59 +09:00
parent b56f7d357e
commit 4fc72332f5
34 changed files with 850 additions and 452 deletions
+54
View File
@@ -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"}
+6
View File
@@ -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"}
+31
View File
@@ -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"}
+409 -409
View File
@@ -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
``` ```
+13
View File
@@ -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

+15 -15
View File
@@ -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>
@@ -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
+20
View File
@@ -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"}
+1
View File
@@ -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"}
+1
View File
@@ -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"
}